1 /************************************************************************* 2 * 3 * The Contents of this file are made available subject to the terms of 4 * the BSD license. 5 * 6 * Copyright 2000, 2010 Oracle and/or its affiliates. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 31 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 *************************************************************************/ 34 35 import com.sun.star.uno.*; 36 import com.sun.star.lang.*; 37 import com.sun.star.container.*; 38 import com.sun.star.beans.*; 39 import com.sun.star.form.*; 40 import com.sun.star.util.*; 41 import com.sun.star.sdbc.*; 42 43 44 /**************************************************************************/ 45 /** A helper class for recursively locking control models which are bound 46 to a specific field 47 */ 48 49 class LockControlModels extends ComponentTreeTraversal 50 { 51 private String m_sDataField; 52 private Boolean m_aLockIt; 53 private int m_nLevel; // nesting level relative to the form we started with 54 55 /* ------------------------------------------------------------------ */ 56 public LockControlModels( String sDataField, boolean bLockIt ) 57 { 58 m_sDataField = sDataField; 59 m_aLockIt = new Boolean( bLockIt ); 60 m_nLevel = 0; 61 } 62 63 /* ------------------------------------------------------------------ */ 64 protected boolean shouldStepInto( XIndexContainer xContainer ) throws com.sun.star.uno.Exception 65 { 66 if ( !super.shouldStepInto( xContainer ) ) 67 return false; // don't try to be more clever than our base class 68 69 XForm xForm = (XForm)UnoRuntime.queryInterface( XForm.class, xContainer ); 70 if ( ( null != xForm ) && ( m_nLevel > 1 ) ) 71 // don't step into sub forms - we only handle the form we were originally 72 // applied to 73 return false; 74 75 return true; 76 } 77 78 /* ------------------------------------------------------------------ */ 79 public void handle( Object aFormComponent ) throws com.sun.star.uno.Exception 80 { 81 // entering this nesting level 82 ++m_nLevel; 83 84 // check if the component has a DataField property 85 XPropertySet xCompProps = UNO.queryPropertySet( aFormComponent ); 86 XPropertySetInfo xPSI = null; 87 if ( null != xCompProps ) 88 xPSI = xCompProps.getPropertySetInfo(); 89 90 if ( ( null != xPSI ) && xPSI.hasPropertyByName( "DataField" ) ) 91 { // indeed it has .... 92 String sDataField = (String)xCompProps.getPropertyValue( "DataField" ); 93 if ( sDataField.equals( m_sDataField ) ) 94 { // we found a control model which is bound to what we're looking for 95 xCompProps.setPropertyValue( "ReadOnly", m_aLockIt ); 96 } 97 } 98 99 // allow the super class to step down, if possible 100 super.handle( aFormComponent ); 101 102 // leaving this nesting level 103 --m_nLevel; 104 } 105 }; 106 107 /**************************************************************************/ 108 /** a class which automatically handles control locking. 109 <p>The class has to be bound to a form. Upon every movement of the form, 110 all controls which are bound to a (to be specified) field are locked 111 on existing and unlocked on new records.</p> 112 */ 113 class ControlLock implements XRowSetListener 114 { 115 private XPropertySet m_xForm; 116 private String m_sDataField; 117 private boolean m_bLockingEnabled; 118 private boolean m_bPreviousRoundLock; 119 120 /* ------------------------------------------------------------------ */ 121 ControlLock( XPropertySet xForm, String sBoundDataField ) 122 { 123 m_xForm = xForm; 124 m_sDataField = sBoundDataField; 125 m_bLockingEnabled = false; 126 m_bPreviousRoundLock = false; 127 } 128 129 /* ------------------------------------------------------------------ */ 130 /** updates the locks on the affected controls 131 */ 132 protected void updateLocks( ) 133 { 134 try 135 { 136 // first determine if we need to lock 137 Boolean aIsNewRecord = (Boolean)m_xForm.getPropertyValue( "IsNew" ); 138 139 boolean bNeedLock = m_bLockingEnabled && !aIsNewRecord.booleanValue(); 140 141 if ( m_bPreviousRoundLock != bNeedLock ) 142 { 143 LockControlModels aLocker = new LockControlModels( m_sDataField, bNeedLock ); 144 aLocker.handle( m_xForm ); 145 m_bPreviousRoundLock = bNeedLock; 146 } 147 148 // please note that we choose the expensive way here: We always loop through 149 // _all_ control models belonging to the form. This clearly slows down the 150 // whole process. 151 // A better solution would be to cache the affected control models. Then we 152 // could either rely on the fact that the model hierarchy is static, or we 153 // could add ourself as container listener to the form. 154 } 155 catch(com.sun.star.uno.Exception e) 156 { 157 System.out.println(e); 158 e.printStackTrace(); 159 } 160 } 161 162 /* ------------------------------------------------------------------ */ 163 /** enables the locking in general 164 <p>If the control models are really locked depends on the current 165 record of the form: on the insert row, controls are never locked.</p> 166 */ 167 public void enableLock( boolean bLock ) 168 { 169 // remember this new setting 170 m_bLockingEnabled = bLock; 171 172 // add or remove ourself as listener to get notified of cursor moves 173 XRowSet xRowSet = (XRowSet)UnoRuntime.queryInterface( 174 XRowSet.class, m_xForm ); 175 if ( m_bLockingEnabled ) 176 { 177 xRowSet.addRowSetListener( this ); 178 } 179 else 180 { 181 xRowSet.removeRowSetListener( this ); 182 } 183 184 // update the locks 185 updateLocks(); 186 } 187 188 /* ================================================================== 189 = UNO callbacks 190 ================================================================== */ 191 192 /* ------------------------------------------------------------------ */ 193 // XResetListener overridables 194 /* ------------------------------------------------------------------ */ 195 public void cursorMoved( EventObject aEvent ) throws com.sun.star.uno.RuntimeException 196 { 197 updateLocks( ); 198 } 199 200 /* ------------------------------------------------------------------ */ 201 public void rowChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException 202 { 203 // not interested in 204 } 205 206 /* ------------------------------------------------------------------ */ 207 public void rowSetChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException 208 { 209 // not interested in 210 } 211 212 /* ------------------------------------------------------------------ */ 213 // XEventListener overridables 214 /* ------------------------------------------------------------------ */ 215 public void disposing( EventObject aEvent ) 216 { 217 // not interested in 218 } 219 } 220