1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 import com.sun.star.uno.*;
25 import com.sun.star.lang.*;
26 import com.sun.star.container.*;
27 import com.sun.star.beans.*;
28 import com.sun.star.form.*;
29 import com.sun.star.util.*;
30 import com.sun.star.sdbc.*;
31 
32 
33 /**************************************************************************/
34 /** A helper class for recursively locking control models which are bound
35 	to a specific field
36 */
37 
38 class LockControlModels extends ComponentTreeTraversal
39 {
40 	private String	m_sDataField;
41 	private Boolean	m_aLockIt;
42 	private int		m_nLevel;	// nesting level relative to the form we started with
43 
44 	/* ------------------------------------------------------------------ */
LockControlModels( String sDataField, boolean bLockIt )45 	public LockControlModels( String sDataField, boolean bLockIt )
46 	{
47 		m_sDataField = sDataField;
48 		m_aLockIt = new Boolean( bLockIt );
49 		m_nLevel = 0;
50 	}
51 
52 	/* ------------------------------------------------------------------ */
shouldStepInto( XIndexContainer xContainer )53 	protected boolean shouldStepInto( XIndexContainer xContainer ) throws com.sun.star.uno.Exception
54 	{
55 		if ( !super.shouldStepInto( xContainer ) )
56 			return false;	// don't try to be more clever than our base class
57 
58 		XForm xForm = (XForm)UnoRuntime.queryInterface( XForm.class, xContainer );
59 		if ( ( null != xForm ) && ( m_nLevel > 1 ) )
60 			// don't step into sub forms - we only handle the form we were originally
61 			// applied to
62 			return false;
63 
64 		return true;
65 	}
66 
67 	/* ------------------------------------------------------------------ */
handle( Object aFormComponent )68 	public void handle( Object aFormComponent ) throws com.sun.star.uno.Exception
69 	{
70 		// entering this nesting level
71 		++m_nLevel;
72 
73 		// check if the component has a DataField property
74 		XPropertySet xCompProps = UNO.queryPropertySet( aFormComponent );
75 		XPropertySetInfo xPSI = null;
76 		if ( null != xCompProps )
77 			xPSI = xCompProps.getPropertySetInfo();
78 
79 		if ( ( null != xPSI ) && xPSI.hasPropertyByName( "DataField" ) )
80 		{	// indeed it has ....
81 			String sDataField = (String)xCompProps.getPropertyValue( "DataField" );
82 			if ( sDataField.equals( m_sDataField ) )
83 			{	// we found a control model which is bound to what we're looking for
84 				xCompProps.setPropertyValue( "ReadOnly", m_aLockIt );
85 			}
86 		}
87 
88 		// allow the super class to step down, if possible
89 		super.handle( aFormComponent );
90 
91 		// leaving this nesting level
92 		--m_nLevel;
93 	}
94 };
95 
96 /**************************************************************************/
97 /** a class which automatically handles control locking.
98 	<p>The class has to be bound to a form. Upon every movement of the form,
99 	all controls which are bound to a (to be specified) field are locked
100 	on existing and unlocked on new records.</p>
101 */
102 class ControlLock implements XRowSetListener
103 {
104 	private	XPropertySet	m_xForm;
105 	private	String			m_sDataField;
106 	private boolean			m_bLockingEnabled;
107 	private boolean			m_bPreviousRoundLock;
108 
109 	/* ------------------------------------------------------------------ */
ControlLock( XPropertySet xForm, String sBoundDataField )110 	ControlLock( XPropertySet xForm, String sBoundDataField )
111 	{
112 		m_xForm = xForm;
113 		m_sDataField = sBoundDataField;
114 		m_bLockingEnabled = false;
115 		m_bPreviousRoundLock = false;
116 	}
117 
118 	/* ------------------------------------------------------------------ */
119 	/** updates the locks on the affected controls
120 	*/
updateLocks( )121 	protected void updateLocks( )
122 	{
123 		try
124 		{
125 			// first determine if we need to lock
126 			Boolean aIsNewRecord = (Boolean)m_xForm.getPropertyValue( "IsNew" );
127 
128 			boolean bNeedLock = m_bLockingEnabled && !aIsNewRecord.booleanValue();
129 
130 			if ( m_bPreviousRoundLock != bNeedLock )
131 			{
132 				LockControlModels aLocker = new LockControlModels( m_sDataField, bNeedLock );
133 				aLocker.handle( m_xForm );
134 				m_bPreviousRoundLock = bNeedLock;
135 			}
136 
137 			// please note that we choose the expensive way here: We always loop through
138 			// _all_ control models belonging to the form. This clearly slows down the
139 			// whole process.
140 			// A better solution would be to cache the affected control models. Then we
141 			// could either rely on the fact that the model hierarchy is static, or we
142 			// could add ourself as container listener to the form.
143 		}
144 		catch(com.sun.star.uno.Exception e)
145 		{
146 			System.out.println(e);
147 			e.printStackTrace();
148 		}
149 	}
150 
151 	/* ------------------------------------------------------------------ */
152 	/** enables the locking in general
153 		<p>If the control models are really locked depends on the current
154 		record of the form: on the insert row, controls are never locked.</p>
155 	*/
enableLock( boolean bLock )156 	public void enableLock( boolean bLock )
157 	{
158 		// remember this new setting
159 		m_bLockingEnabled = bLock;
160 
161 		// add or remove ourself as listener to get notified of cursor moves
162 		XRowSet xRowSet = (XRowSet)UnoRuntime.queryInterface(
163 			XRowSet.class, m_xForm );
164 		if ( m_bLockingEnabled )
165 		{
166 			xRowSet.addRowSetListener( this );
167 		}
168 		else
169 		{
170 			xRowSet.removeRowSetListener( this );
171 		}
172 
173 		// update the locks
174 		updateLocks();
175 	}
176 
177 	/* ==================================================================
178 	   = UNO callbacks
179 	   ================================================================== */
180 
181 	/* ------------------------------------------------------------------ */
182 	// XResetListener overridables
183 	/* ------------------------------------------------------------------ */
cursorMoved( EventObject aEvent )184 	public void cursorMoved( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
185 	{
186 		updateLocks( );
187 	}
188 
189 	/* ------------------------------------------------------------------ */
rowChanged( EventObject aEvent )190 	public void rowChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
191 	{
192 		// not interested in
193 	}
194 
195 	/* ------------------------------------------------------------------ */
rowSetChanged( EventObject aEvent )196 	public void rowSetChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
197 	{
198 		// not interested in
199 	}
200 
201 	/* ------------------------------------------------------------------ */
202 	// XEventListener overridables
203 	/* ------------------------------------------------------------------ */
disposing( EventObject aEvent )204 	public void disposing( EventObject aEvent )
205 	{
206 		// not interested in
207 	}
208 }
209