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