diff options
Diffstat (limited to 'odk/examples/DevelopersGuide/Forms/ControlLock.java')
-rw-r--r-- | odk/examples/DevelopersGuide/Forms/ControlLock.java | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/odk/examples/DevelopersGuide/Forms/ControlLock.java b/odk/examples/DevelopersGuide/Forms/ControlLock.java new file mode 100644 index 000000000..6895f73f9 --- /dev/null +++ b/odk/examples/DevelopersGuide/Forms/ControlLock.java @@ -0,0 +1,223 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * The Contents of this file are made available subject to the terms of + * the BSD license. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Sun Microsystems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *************************************************************************/ + +import com.sun.star.uno.*; +import com.sun.star.lang.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.form.*; +import com.sun.star.sdbc.*; + + +/**************************************************************************/ +/** A helper class for recursively locking control models which are bound + to a specific field +*/ + +class LockControlModels extends ComponentTreeTraversal +{ + private String m_sDataField; + private Boolean m_aLockIt; + private int m_nLevel; // nesting level relative to the form we started with + + /* ------------------------------------------------------------------ */ + public LockControlModels( String sDataField, boolean bLockIt ) + { + m_sDataField = sDataField; + m_aLockIt = Boolean.valueOf( bLockIt ); + m_nLevel = 0; + } + + /* ------------------------------------------------------------------ */ + @Override + protected boolean shouldStepInto( XIndexContainer xContainer ) + { + if ( !super.shouldStepInto( xContainer ) ) + return false; // don't try to be more clever than our base class + + XForm xForm = UnoRuntime.queryInterface( XForm.class, xContainer ); + if ( ( null != xForm ) && ( m_nLevel > 1 ) ) + // don't step into sub forms - we only handle the form we were originally + // applied to + return false; + + return true; + } + + /* ------------------------------------------------------------------ */ + @Override + public void handle( Object aFormComponent ) throws com.sun.star.uno.Exception + { + // entering this nesting level + ++m_nLevel; + + // check if the component has a DataField property + XPropertySet xCompProps = UNO.queryPropertySet( aFormComponent ); + XPropertySetInfo xPSI = null; + if ( null != xCompProps ) + xPSI = xCompProps.getPropertySetInfo(); + + if ( ( null != xPSI ) && xPSI.hasPropertyByName( "DataField" ) ) + { // indeed it has... + String sDataField = (String)xCompProps.getPropertyValue( "DataField" ); + if ( sDataField.equals( m_sDataField ) ) + { // we found a control model which is bound to what we're looking for + xCompProps.setPropertyValue( "ReadOnly", m_aLockIt ); + } + } + + // allow the super class to step down, if possible + super.handle( aFormComponent ); + + // leaving this nesting level + --m_nLevel; + } +} + +/**************************************************************************/ +/** a class which automatically handles control locking. + <p>The class has to be bound to a form. Upon every movement of the form, + all controls which are bound to a (to be specified) field are locked + on existing and unlocked on new records.</p> +*/ +class ControlLock implements XRowSetListener +{ + private XPropertySet m_xForm; + private String m_sDataField; + private boolean m_bLockingEnabled; + private boolean m_bPreviousRoundLock; + + /* ------------------------------------------------------------------ */ + ControlLock( XPropertySet xForm, String sBoundDataField ) + { + m_xForm = xForm; + m_sDataField = sBoundDataField; + m_bLockingEnabled = false; + m_bPreviousRoundLock = false; + } + + /* ------------------------------------------------------------------ */ + /** updates the locks on the affected controls + */ + private void updateLocks( ) + { + try + { + // first determine if we need to lock + Boolean aIsNewRecord = (Boolean)m_xForm.getPropertyValue( "IsNew" ); + + boolean bNeedLock = m_bLockingEnabled && !aIsNewRecord.booleanValue(); + + if ( m_bPreviousRoundLock != bNeedLock ) + { + LockControlModels aLocker = new LockControlModels( m_sDataField, bNeedLock ); + aLocker.handle( m_xForm ); + m_bPreviousRoundLock = bNeedLock; + } + + // please note that we choose the expensive way here: We always loop through + // _all_ control models belonging to the form. This clearly slows down the + // whole process. + // A better solution would be to cache the affected control models. Then we + // could either rely on the fact that the model hierarchy is static, or we + // could add ourself as container listener to the form. + } + catch(com.sun.star.uno.Exception e) + { + System.out.println(e); + e.printStackTrace(); + } + } + + /* ------------------------------------------------------------------ */ + /** enables the locking in general + <p>If the control models are really locked depends on the current + record of the form: on the insert row, controls are never locked.</p> + */ + public void enableLock( boolean bLock ) + { + // remember this new setting + m_bLockingEnabled = bLock; + + // add or remove ourself as listener to get notified of cursor moves + XRowSet xRowSet = UnoRuntime.queryInterface( + XRowSet.class, m_xForm ); + if ( m_bLockingEnabled ) + { + xRowSet.addRowSetListener( this ); + } + else + { + xRowSet.removeRowSetListener( this ); + } + + // update the locks + updateLocks(); + } + + /* ================================================================== + = UNO callbacks + ================================================================== */ + + /* ------------------------------------------------------------------ */ + // XResetListener overridables + /* ------------------------------------------------------------------ */ + public void cursorMoved( EventObject aEvent ) throws com.sun.star.uno.RuntimeException + { + updateLocks( ); + } + + /* ------------------------------------------------------------------ */ + public void rowChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException + { + // not interested in + } + + /* ------------------------------------------------------------------ */ + public void rowSetChanged( EventObject aEvent ) throws com.sun.star.uno.RuntimeException + { + // not interested in + } + + /* ------------------------------------------------------------------ */ + // XEventListener overridables + /* ------------------------------------------------------------------ */ + public void disposing( EventObject aEvent ) + { + // not interested in + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |