1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir import com.sun.star.uno.Type;
28*cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime;
29*cdf0e10cSrcweir import com.sun.star.table.XCell;
30*cdf0e10cSrcweir import com.sun.star.util.XModifyListener;
31*cdf0e10cSrcweir import com.sun.star.beans.XPropertySet;
32*cdf0e10cSrcweir import com.sun.star.text.XTextRange;
33*cdf0e10cSrcweir import com.sun.star.form.binding.IncompatibleTypesException;
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir /** a value binding to be connected to a form control
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir     This binding synchronizes the text contained in a table cell (which you must
38*cdf0e10cSrcweir     pass upon construction) to the text in an XBindableValue.
39*cdf0e10cSrcweir 
40*cdf0e10cSrcweir     Well, in real it does not synchronize both directions. The ValueBinding
41*cdf0e10cSrcweir     service has not much room for own activity: It allows notification of changes
42*cdf0e10cSrcweir     in the own value, and it allows external instances to set the current value.
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir     Note that we implement this binding as a separate thread, which is (more or
45*cdf0e10cSrcweir     less permanently) polling for a new text at the cell. This is unfortunate, but
46*cdf0e10cSrcweir     sadly the Writer table cells do not support actively notifying changes in their
47*cdf0e10cSrcweir     content to other interested parties.
48*cdf0e10cSrcweir */
49*cdf0e10cSrcweir public class TableCellTextBinding
50*cdf0e10cSrcweir                 extends     java.lang.Thread
51*cdf0e10cSrcweir                 implements  com.sun.star.form.binding.XValueBinding,
52*cdf0e10cSrcweir                             com.sun.star.util.XModifyBroadcaster
53*cdf0e10cSrcweir {
54*cdf0e10cSrcweir     private XTextRange  m_cellText;
55*cdf0e10cSrcweir     private Object      m_writeSignal;
56*cdf0e10cSrcweir     private String      m_newCellText;
57*cdf0e10cSrcweir     private String      m_lastKnownCellText;
58*cdf0e10cSrcweir     private boolean     m_haveNewCellText;
59*cdf0e10cSrcweir     private java.util.List  m_listeners;
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir     /** Creates a new instance of TableCellTextBinding */
62*cdf0e10cSrcweir     public TableCellTextBinding( XCell cell )
63*cdf0e10cSrcweir     {
64*cdf0e10cSrcweir         m_cellText = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, cell );
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir         m_newCellText = new String();
67*cdf0e10cSrcweir         m_listeners = new java.util.LinkedList();
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir         start();
70*cdf0e10cSrcweir     }
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir     /** retrieves the list of data types which this binding can exchange
73*cdf0e10cSrcweir     */
74*cdf0e10cSrcweir     public com.sun.star.uno.Type[] getSupportedValueTypes()
75*cdf0e10cSrcweir     {
76*cdf0e10cSrcweir         try
77*cdf0e10cSrcweir         {
78*cdf0e10cSrcweir             // well, only strings here ...
79*cdf0e10cSrcweir             return new Type[] {
80*cdf0e10cSrcweir                 getStringType()
81*cdf0e10cSrcweir             };
82*cdf0e10cSrcweir         }
83*cdf0e10cSrcweir         catch( java.lang.Exception e )
84*cdf0e10cSrcweir         {
85*cdf0e10cSrcweir         }
86*cdf0e10cSrcweir         return new Type[] { };
87*cdf0e10cSrcweir     }
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir     /** retrieves the current value
90*cdf0e10cSrcweir     */
91*cdf0e10cSrcweir     public Object getValue(com.sun.star.uno.Type type) throws com.sun.star.form.binding.IncompatibleTypesException
92*cdf0e10cSrcweir     {
93*cdf0e10cSrcweir         if ( !type.equals( getStringType() ) )
94*cdf0e10cSrcweir             throw new com.sun.star.form.binding.IncompatibleTypesException();
95*cdf0e10cSrcweir 
96*cdf0e10cSrcweir         return m_cellText.getString();
97*cdf0e10cSrcweir     }
98*cdf0e10cSrcweir 
99*cdf0e10cSrcweir     /** sets a new value
100*cdf0e10cSrcweir     */
101*cdf0e10cSrcweir     public void setValue(Object obj) throws com.sun.star.form.binding.IncompatibleTypesException
102*cdf0e10cSrcweir     {
103*cdf0e10cSrcweir         String text;
104*cdf0e10cSrcweir         try
105*cdf0e10cSrcweir         {
106*cdf0e10cSrcweir             text = (String)obj;
107*cdf0e10cSrcweir         }
108*cdf0e10cSrcweir         catch( java.lang.ClassCastException e )
109*cdf0e10cSrcweir         {
110*cdf0e10cSrcweir             throw new com.sun.star.form.binding.IncompatibleTypesException();
111*cdf0e10cSrcweir         }
112*cdf0e10cSrcweir         // remember the new text
113*cdf0e10cSrcweir         synchronized( m_newCellText )
114*cdf0e10cSrcweir         {
115*cdf0e10cSrcweir             m_newCellText = text;
116*cdf0e10cSrcweir             m_haveNewCellText = true;
117*cdf0e10cSrcweir         }
118*cdf0e10cSrcweir         // and wake up the thread which is waiting for it
119*cdf0e10cSrcweir         synchronized( m_writeSignal )
120*cdf0e10cSrcweir         {
121*cdf0e10cSrcweir             m_writeSignal.notify();
122*cdf0e10cSrcweir         }
123*cdf0e10cSrcweir     }
124*cdf0e10cSrcweir 
125*cdf0e10cSrcweir     /** determines whether a given value type is supported
126*cdf0e10cSrcweir     */
127*cdf0e10cSrcweir     public boolean supportsType(com.sun.star.uno.Type type)
128*cdf0e10cSrcweir     {
129*cdf0e10cSrcweir         return type.equals( getStringType() );
130*cdf0e10cSrcweir     }
131*cdf0e10cSrcweir 
132*cdf0e10cSrcweir     /** retrieves the UNO type for the string class
133*cdf0e10cSrcweir     */
134*cdf0e10cSrcweir     private static final Type getStringType()
135*cdf0e10cSrcweir     {
136*cdf0e10cSrcweir         return new com.sun.star.uno.Type( String.class );
137*cdf0e10cSrcweir     }
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir     /** runs the thread
140*cdf0e10cSrcweir     */
141*cdf0e10cSrcweir     public void run()
142*cdf0e10cSrcweir     {
143*cdf0e10cSrcweir         try
144*cdf0e10cSrcweir         {
145*cdf0e10cSrcweir             m_writeSignal = new Object();
146*cdf0e10cSrcweir             while ( true )
147*cdf0e10cSrcweir             {
148*cdf0e10cSrcweir                 // go sleep a while
149*cdf0e10cSrcweir                 synchronized( m_writeSignal )
150*cdf0e10cSrcweir                 {
151*cdf0e10cSrcweir                     m_writeSignal.wait( 200 );
152*cdf0e10cSrcweir                 }
153*cdf0e10cSrcweir 
154*cdf0e10cSrcweir                 // if there's new text in the control, propagate it to the cell
155*cdf0e10cSrcweir                 synchronized ( m_newCellText )
156*cdf0e10cSrcweir                 {
157*cdf0e10cSrcweir                     if ( m_haveNewCellText )
158*cdf0e10cSrcweir                     {
159*cdf0e10cSrcweir                         m_cellText.setString( m_newCellText );
160*cdf0e10cSrcweir                         m_lastKnownCellText = m_newCellText;
161*cdf0e10cSrcweir                     }
162*cdf0e10cSrcweir                     m_haveNewCellText = false;
163*cdf0e10cSrcweir                 }
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir                 // if there's new text in the cell, propagate it to the control
166*cdf0e10cSrcweir                 String currentCellText = m_cellText.getString();
167*cdf0e10cSrcweir                 if ( !currentCellText.equals( m_lastKnownCellText ) )
168*cdf0e10cSrcweir                 {
169*cdf0e10cSrcweir                     m_lastKnownCellText = currentCellText;
170*cdf0e10cSrcweir                     // notify the modification
171*cdf0e10cSrcweir                     synchronized( m_listeners )
172*cdf0e10cSrcweir                     {
173*cdf0e10cSrcweir                         com.sun.star.lang.EventObject eventSource = new com.sun.star.lang.EventObject( this );
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir                         java.util.Iterator loop = m_listeners.iterator();
176*cdf0e10cSrcweir                         while ( loop.hasNext() )
177*cdf0e10cSrcweir                         {
178*cdf0e10cSrcweir                             ((XModifyListener)loop.next()).modified( eventSource );
179*cdf0e10cSrcweir                         }
180*cdf0e10cSrcweir                     }
181*cdf0e10cSrcweir                 }
182*cdf0e10cSrcweir             }
183*cdf0e10cSrcweir         }
184*cdf0e10cSrcweir         catch( java.lang.Exception e )
185*cdf0e10cSrcweir         {
186*cdf0e10cSrcweir             e.printStackTrace(System.err);
187*cdf0e10cSrcweir         }
188*cdf0e10cSrcweir     }
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir     public void addModifyListener(com.sun.star.util.XModifyListener xModifyListener)
191*cdf0e10cSrcweir     {
192*cdf0e10cSrcweir         synchronized( m_listeners )
193*cdf0e10cSrcweir         {
194*cdf0e10cSrcweir             m_listeners.add( xModifyListener );
195*cdf0e10cSrcweir         }
196*cdf0e10cSrcweir     }
197*cdf0e10cSrcweir 
198*cdf0e10cSrcweir     public void removeModifyListener(com.sun.star.util.XModifyListener xModifyListener)
199*cdf0e10cSrcweir     {
200*cdf0e10cSrcweir         synchronized( m_listeners )
201*cdf0e10cSrcweir         {
202*cdf0e10cSrcweir             m_listeners.remove( xModifyListener );
203*cdf0e10cSrcweir         }
204*cdf0e10cSrcweir     }
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir     public void disposing(com.sun.star.lang.EventObject eventObject)
207*cdf0e10cSrcweir     {
208*cdf0e10cSrcweir         // not interested in
209*cdf0e10cSrcweir     }
210*cdf0e10cSrcweir }
211