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 being 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