xref: /AOO41X/main/odk/examples/DevelopersGuide/Forms/SalesFilter.java (revision 34dd1e2512dbacb6a9a7e4c7f17b9296daa8eff3)
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.beans.*;
26 import com.sun.star.form.*;
27 import com.sun.star.lang.*;
28 import com.sun.star.sdb.*;
29 import com.sun.star.sdbc.*;
30 import com.sun.star.sdbcx.*;
31 import com.sun.star.container.*;
32 import com.sun.star.awt.*;
33 
34 import java.util.Vector;
35 import java.util.Calendar;
36 import java.util.GregorianCalendar;
37 
38 /**************************************************************************/
39 /** helper class for filtering the sales form
40 */
41 class SalesFilter implements XActionListener, XPropertyChangeListener, XResetListener
42 {
43     private DocumentHelper  m_aDocument;
44     private XPropertySet        m_xSalesForm;
45 
46     private XPropertySet        m_xFilterList;
47     private XPropertySet        m_xManualFilter;
48     private XPropertySet        m_xApplyFilter;
49 
50     private boolean         m_bSettingsDirty;
51     private boolean         m_bSettingDate;
52     private boolean         m_bAdjustingFilterList;
53     private short               m_nPreviousFilterIndex;
54     private java.util.Vector    m_aFilterDates;
55 
56     /* ------------------------------------------------------------------ */
SalesFilter( DocumentHelper aDocument, XPropertySet xSalesForm, XPropertySet xFilterListBox, XPropertySet xManualFilterEdit, XPropertySet xStartFilterButton )57     public SalesFilter( DocumentHelper aDocument, XPropertySet xSalesForm,
58         XPropertySet xFilterListBox, XPropertySet xManualFilterEdit, XPropertySet xStartFilterButton )
59     {
60         m_aFilterDates = new java.util.Vector();
61         m_bSettingsDirty = false;
62         m_bSettingDate = false;
63         m_bAdjustingFilterList = false;
64         m_nPreviousFilterIndex = -1;
65         initFilterDates();
66 
67         // -------------------------------------------------------------
68         // remember the components
69         m_aDocument = aDocument;
70         m_xSalesForm = xSalesForm;
71 
72         m_xFilterList = xFilterListBox;
73         m_xManualFilter = xManualFilterEdit;
74         m_xApplyFilter = xStartFilterButton;
75 
76         try
77         {
78             // ----------------------------------------------------------
79             // init control models
80             m_xFilterList.setPropertyValue( "Dropdown", new Boolean( true ) );
81             m_xFilterList.setPropertyValue( "LineCount", new Short( (short)11 ) );
82             m_xFilterList.setPropertyValue( "StringItemList", new String[] { "ever (means no filter)", "this morning", "1 week ago", "1 month ago", "1 year ago", "<other>" } );
83             m_xFilterList.setPropertyValue( "DefaultSelection", new Short[] { new Short( (short)0 ) } );
84 
85             m_xApplyFilter.setPropertyValue( "Label", "Apply Filter" );
86 
87             updateFilterControl();
88             updateApplyButton();
89 
90             // ----------------------------------------------------------
91             // add as listener to the events which require action
92 
93             // want to know about changed selection
94             m_xFilterList.addPropertyChangeListener( "SelectedItems", this );
95             m_xManualFilter.addPropertyChangeListener( "Date", this );
96 
97             // want to know about the date field beeing reset
98             XReset xReset = UNO.queryReset( m_xManualFilter );
99             xReset.addResetListener( this );
100 
101             // for the button, we can add to the control only, not to the model
102             // - clicking a button is something which happens on the _control_.
103             DocumentViewHelper aView = m_aDocument.getCurrentView();
104             XButton xButton = (XButton)aView.getFormControl( m_xApplyFilter, XButton.class );
105             xButton.addActionListener( this );
106         }
107         catch ( com.sun.star.uno.Exception e )
108         {
109             System.out.println(e);
110             e.printStackTrace();
111         }
112     }
113 
114     /* ==================================================================
115        = helper
116        ================================================================== */
117     /* ------------------------------------------------------------------ */
initFilterDates()118     protected void initFilterDates()
119     {
120         m_aFilterDates.clear();
121         java.util.Date aNowAndHere = new java.util.Date();
122         aNowAndHere.setHours( 0 );
123         aNowAndHere.setMinutes( 0 );
124         aNowAndHere.setSeconds( 0 );
125 
126         // for every list entry, we add a java.util.Date to m_aFilterDates indicating
127         // since when the sales should be listed
128 
129         // ever
130         m_aFilterDates.add( null );
131 
132         // this morning
133         m_aFilterDates.add( aNowAndHere );
134 
135         // one week ago
136         GregorianCalendar aCalendar = new GregorianCalendar( );
137         aCalendar.setTime( aNowAndHere );
138         aCalendar.add( Calendar.DATE, -7 );
139         m_aFilterDates.add( aCalendar.getTime() );
140 
141         // one month ago
142         aCalendar.setTime( aNowAndHere );
143         aCalendar.add( Calendar.MONTH, -1 );
144         m_aFilterDates.add( aCalendar.getTime() );
145 
146         // one year ago
147         aCalendar.setTime( aNowAndHere );
148         aCalendar.add( Calendar.YEAR, -1 );
149         m_aFilterDates.add( aCalendar.getTime() );
150 
151         // the custom date
152         m_aFilterDates.add( null );
153     }
154 
155     /* ------------------------------------------------------------------ */
156     /** translates a date from the AWT Toolkit format to a java.util.date, or
157         vice versa.
158     */
translateDate( Object aDate )159     protected Object translateDate( Object aDate ) throws java.lang.Exception
160     {
161         Object aReturn = null;
162 
163         GregorianCalendar aCalDate = new GregorianCalendar();
164         if ( aDate.getClass().equals( Class.forName( "java.util.Date" ) ) )
165         {
166             aCalDate.setTime( (java.util.Date)aDate );
167 
168             int nDate = aCalDate.get( Calendar.YEAR );
169             nDate = nDate * 100 + aCalDate.get( Calendar.MONTH ) + 1;
170             nDate = nDate * 100 + aCalDate.get( Calendar.DAY_OF_MONTH );
171 
172             aReturn = new Integer( nDate );
173         }
174         else if ( aDate.getClass().equals( Class.forName( "java.lang.Integer" ) ) )
175         {
176             int nToolkitDate = ((Integer)aDate).intValue();
177             aCalDate.set( Calendar.DAY_OF_MONTH, ( nToolkitDate % 100 ) );
178             nToolkitDate /= 100;
179             aCalDate.set( Calendar.MONTH, ( nToolkitDate % 100 ) - 1 );
180             nToolkitDate /= 100;
181             aCalDate.set( Calendar.YEAR, ( nToolkitDate % 10000 ) );
182 
183             // default the time
184             aCalDate.set( Calendar.HOUR_OF_DAY, 0 );
185             aCalDate.set( Calendar.MINUTE, 0 );
186             aCalDate.set( Calendar.SECOND, 0 );
187 
188             aReturn = aCalDate.getTime();
189         }
190 
191         return aReturn;
192     }
193 
194     /* ------------------------------------------------------------------ */
195     /** translates the given date into the ODBC date notation, which then can be used
196         for setting a filter at a row set
197     */
getOdbcDate( Object aDate )198     protected String getOdbcDate( Object aDate ) throws java.lang.Exception
199     {
200         String sOdbcDate = "";
201         if ( null != aDate )
202         {
203             if ( !aDate.getClass().equals( Class.forName( "java.util.Date" ) ) )
204                 aDate = translateDate( aDate );
205 
206             if ( aDate.getClass().equals( Class.forName( "java.util.Date" ) ) )
207             {
208                 GregorianCalendar aCal = new GregorianCalendar();
209                 aCal.setTime( (java.util.Date)aDate );
210 
211                 sOdbcDate += new String( "{D '" );
212                 sOdbcDate += (new Integer( aCal.get( Calendar.YEAR ) ) ).toString();
213                 sOdbcDate += "-";
214 
215                 int nMonth = aCal.get( Calendar.MONTH ) + 1;
216                 if ( nMonth < 10 )
217                     sOdbcDate += "0";
218                 sOdbcDate += (new Integer( nMonth ) ).toString();
219                 sOdbcDate += "-";
220 
221                 int nDay = aCal.get( Calendar.DAY_OF_MONTH );
222                 if ( nDay < 10 )
223                     sOdbcDate += "0";
224                 sOdbcDate += (new Integer( nDay ) ).toString();
225                 sOdbcDate += "'}";
226             }
227         }
228         return sOdbcDate;
229     }
230 
231     /* ------------------------------------------------------------------ */
updateApplyButton()232     protected void updateApplyButton()
233     {
234         try
235         {
236             m_xApplyFilter.setPropertyValue( "Enabled", new Boolean( m_bSettingsDirty ) );
237         }
238         catch ( com.sun.star.uno.Exception e )
239         {
240             System.out.println(e);
241             e.printStackTrace();
242         }
243     }
244 
245     /* ------------------------------------------------------------------ */
246     /** creates a normalized calendar object from the given java.util.Date
247     */
getCalendarObject( java.util.Date aDate )248     protected GregorianCalendar getCalendarObject( java.util.Date aDate )
249     {
250         // the date part
251         GregorianCalendar aReturn = null;
252         if ( null != aDate )
253         {
254             aReturn = new GregorianCalendar( );
255             aReturn.setTime( aDate );
256 
257             // normalize the time part
258             aReturn.set( Calendar.HOUR_OF_DAY, 0 );
259             aReturn.set( Calendar.MINUTE, 0 );
260             aReturn.set( Calendar.SECOND, 0 );
261         }
262 
263         return aReturn;
264     }
265 
266     /* ------------------------------------------------------------------ */
getCurrentSelectedFilter( )267     final protected short getCurrentSelectedFilter( ) throws com.sun.star.uno.Exception
268     {
269         short[] aSelected = (short[])m_xFilterList.getPropertyValue( "SelectedItems" );
270         if ( 0 < aSelected.length )
271             return aSelected[0];
272         return -1;
273     }
274 
275     /* ------------------------------------------------------------------ */
276     /** checks if the given filter index referes to the "<other>" entry which
277         allows the user to manually enter a date
278     */
isManualFilter( short nFilterIndex )279     final protected boolean isManualFilter( short nFilterIndex )
280     {
281         return ( 5 == nFilterIndex );
282     }
283 
284     /* ------------------------------------------------------------------ */
updateFilterControl()285     protected void updateFilterControl()
286     {
287         try
288         {
289             if ( isManualFilter( m_nPreviousFilterIndex ) )
290             {   // previously, the "custom" filter date was selected
291                 // -> remember the date entered
292                 Object aDate = translateDate( m_xManualFilter.getPropertyValue( "Date" ) );
293                 m_aFilterDates.set( m_nPreviousFilterIndex, aDate );
294             }
295 
296             // check the current selection
297             if ( !m_bAdjustingFilterList )
298             {
299                 m_nPreviousFilterIndex = getCurrentSelectedFilter( );
300 
301                 // custom filter?
302                 boolean bCustomFilter = isManualFilter( m_nPreviousFilterIndex );
303                 m_xManualFilter.setPropertyValue( "Enabled", new Boolean( bCustomFilter ) );
304                 if ( bCustomFilter )
305                     m_aDocument.getCurrentView().grabControlFocus( m_xManualFilter );
306 
307                 m_bSettingDate = true;
308                 Object aSelectedDateLimit = m_aFilterDates.elementAt( m_nPreviousFilterIndex );
309                 if ( null != aSelectedDateLimit )
310                 {
311                     // translate this date into one the AWT Toolkit understands
312                     Integer aTKDate = (Integer)translateDate( aSelectedDateLimit );
313                     m_xManualFilter.setPropertyValue( "Date", aTKDate );
314                 }
315                 else
316                     m_xManualFilter.setPropertyValue( "Date", new Any( new Type(), null ) );
317                 m_bSettingDate = false;
318             }
319         }
320         catch ( java.lang.Exception e )
321         {
322             System.out.println(e);
323             e.printStackTrace();
324         }
325     }
326 
327     /* ------------------------------------------------------------------ */
328     /** compares the date part of two calendars
329         <p>For some strange reason I do not understand, GregorianCalendar.equals( GregorianCalendar )
330         seems to always return false, as well as . Thus here is a method which compare two calendars,
331         restricted to their date part</p>
332     */
equalDate( Calendar aLHS, Calendar aRHS )333     protected boolean equalDate( Calendar aLHS, Calendar aRHS )
334     {
335         if ( ( null == aLHS ) != ( null == aRHS ) )
336             // only one of them is null
337             return false;
338 
339         if ( null == aLHS )
340             // both are null
341             return true;
342 
343         return  ( aLHS.get( Calendar.YEAR ) == aRHS.get( Calendar.YEAR ) )
344             &&  ( aLHS.get( Calendar.MONTH ) == aRHS.get( Calendar.MONTH ) )
345             &&  ( aLHS.get( Calendar.DAY_OF_MONTH ) == aRHS.get( Calendar.DAY_OF_MONTH ) );
346     }
347 
348     /* ------------------------------------------------------------------ */
349     /** adds the current user filter to the list of date filters
350         @return
351             the index of the newly added date filter in the filter list
352     */
addCurrentFilter( )353     protected short addCurrentFilter( ) throws java.lang.Exception
354     {
355         // the current string items
356         String[] aOldFilterItems = (String[])m_xFilterList.getPropertyValue( "StringItemList" );
357 
358         // translate this into a vector - much more comfort to work with a vector than with an array ....
359         java.util.Vector aFilterItems = new java.util.Vector();
360         for ( int i=0; i<aOldFilterItems.length; ++i )
361             aFilterItems.add( aOldFilterItems[i] );
362 
363         // the currently entered user defined filter date
364         Object aDate = translateDate( m_xManualFilter.getPropertyValue( "Date" ) );
365         GregorianCalendar aDateCal = getCalendarObject( (java.util.Date)aDate );
366         // check if this date is already present in the list of user defined dates
367         for ( int i=0; i<m_aFilterDates.size(); ++i )
368         {
369             if ( !isManualFilter( (short)i ) )  // do not compare with the manual filter
370             {
371                 GregorianCalendar aCheckCal = getCalendarObject( (java.util.Date)m_aFilterDates.elementAt( i ) );
372                 if ( equalDate( aDateCal, aCheckCal ) )
373                     return (short)i;
374             }
375         }
376         System.out.println( );
377 
378         if ( aFilterItems.size() > 10 ) // (6 standard items + 5 user defined items)
379         {
380             // the first (and thus oldes) user defined item
381             aFilterItems.removeElementAt( 6 );
382             // keep our date vector synchron
383             m_aFilterDates.removeElementAt( 6 );
384         }
385 
386         // add the current user defined filter
387         aFilterItems.add( aDate.toString() );
388         m_aFilterDates.add( aDate );
389 
390         // write back the string item list
391         m_bAdjustingFilterList = true;
392         String[] aNewFilterItems = new String[ aFilterItems.size() ];
393         for ( int i=0; i<aFilterItems.size(); ++i )
394             aNewFilterItems[i] = (String)aFilterItems.elementAt( i );
395         m_xFilterList.setPropertyValue( "StringItemList", aNewFilterItems );
396         m_bAdjustingFilterList = false;
397 
398         return (short)(aNewFilterItems.length - 1 );
399     }
400 
401     /* ------------------------------------------------------------------ */
executeCurrentFilter()402     protected void executeCurrentFilter()
403     {
404         try
405         {
406             // we keep the date field consistent with whatever the user chooses in the
407             // list box, so just ask the field
408             Object aDate = translateDate( m_xManualFilter.getPropertyValue( "Date" ) );
409             String sOdbcDate = getOdbcDate( aDate );
410 
411             // if this filter was a manually entered filter, we add it to the filter list
412             // box to allow quick-select it later on.
413             if ( isManualFilter( getCurrentSelectedFilter() ) )
414             {
415                 short nNewUserDefinedFilterPos = addCurrentFilter();
416                 m_xFilterList.setPropertyValue( "SelectedItems", new short[] { nNewUserDefinedFilterPos } );
417             }
418 
419             // set this as filter on the form
420             String sCompleteFilter = "";
421             if ( ( null != sOdbcDate ) && ( 0 != sOdbcDate.length() ) )
422             {
423                 sCompleteFilter = "SALEDATE >= ";
424                 sCompleteFilter += sOdbcDate;
425             }
426             m_xSalesForm.setPropertyValue( "Filter", sCompleteFilter );
427             m_xSalesForm.setPropertyValue( "ApplyFilter", new Boolean( true ) );
428 
429             // and reload the form
430             XLoadable xLoad = (XLoadable)UnoRuntime.queryInterface(
431                 XLoadable.class, m_xSalesForm );
432             xLoad.reload();
433 
434             m_aDocument.getCurrentView().grabControlFocus(  m_xFilterList );
435         }
436         catch ( java.lang.Exception e )
437         {
438             System.out.println(e);
439             e.printStackTrace();
440         }
441     }
442 
443     /* ==================================================================
444        = UNO callbacks
445        ================================================================== */
446     /* ------------------------------------------------------------------ */
447     // XActionListener overridables
448     /* ------------------------------------------------------------------ */
approveReset( EventObject aEvent )449     public boolean approveReset( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
450     {
451         return false;
452             // do not allow the date field to be reset - it would set it's content
453             // to the current date
454             // Note that another possible solution would be to wait for the resetted
455             // event and correct the value there
456     }
457 
458     /* ------------------------------------------------------------------ */
resetted( EventObject aEvent )459     public void resetted( EventObject aEvent ) throws com.sun.star.uno.RuntimeException
460     {
461     }
462 
463     /* ------------------------------------------------------------------ */
464     // XActionListener overridables
465     /* ------------------------------------------------------------------ */
actionPerformed( ActionEvent aEvent )466     public void actionPerformed( ActionEvent aEvent ) throws com.sun.star.uno.RuntimeException
467     {
468         executeCurrentFilter();
469 
470         m_bSettingsDirty = false;
471         updateApplyButton();
472     }
473 
474     /* ------------------------------------------------------------------ */
475     // XItemListener overridables
476     /* ------------------------------------------------------------------ */
propertyChange( PropertyChangeEvent aEvent )477     public void propertyChange( PropertyChangeEvent aEvent ) throws com.sun.star.uno.RuntimeException
478     {
479         if ( aEvent.PropertyName.equals( "SelectedItems" ) )
480         {
481             updateFilterControl();
482 
483             m_bSettingsDirty = true;
484             updateApplyButton();
485         }
486         else if ( aEvent.PropertyName.equals( "Date" ) && !m_bSettingDate )
487         {
488             m_bSettingsDirty = true;
489             updateApplyButton();
490         }
491     }
492 
493     /* ------------------------------------------------------------------ */
494     // XEventListener overridables
495     /* ------------------------------------------------------------------ */
disposing( EventObject aEvent )496     public void disposing( EventObject aEvent )
497     {
498         // not interested in
499     }
500 
501 };
502