/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ 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.util.*; 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 = new Boolean( bLockIt ); m_nLevel = 0; } /* ------------------------------------------------------------------ */ protected boolean shouldStepInto( XIndexContainer xContainer ) throws com.sun.star.uno.Exception { if ( !super.shouldStepInto( xContainer ) ) return false; // don't try to be more clever than our base class XForm 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; } /* ------------------------------------------------------------------ */ 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.

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.

*/ 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 */ protected 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

If the control models are really locked depends on the current record of the form: on the insert row, controls are never locked.

*/ 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 = (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 } }