1 package org.columba.calendar.ui.calendar; 19 20 import java.awt.BorderLayout ; 21 import java.awt.Point ; 22 import java.awt.event.MouseAdapter ; 23 import java.awt.event.MouseEvent ; 24 import java.io.InputStream ; 25 import java.util.Calendar ; 26 import java.util.Collection ; 27 import java.util.Iterator ; 28 import java.util.logging.Logger ; 29 30 import javax.swing.JComponent ; 31 import javax.swing.JPanel ; 32 import javax.swing.JPopupMenu ; 33 import javax.swing.JToolTip ; 34 import javax.swing.event.EventListenerList ; 35 36 import org.columba.calendar.base.Activity; 37 import org.columba.calendar.base.api.IActivity; 38 import org.columba.calendar.model.api.IDateRange; 39 import org.columba.calendar.ui.calendar.api.ActivitySelectionChangedEvent; 40 import org.columba.calendar.ui.calendar.api.IActivitySelectionChangedListener; 41 import org.columba.calendar.ui.calendar.api.ICalendarView; 42 import org.columba.calendar.ui.frame.api.ICalendarMediator; 43 import org.columba.core.gui.menu.ExtendablePopupMenu; 44 import org.columba.core.gui.menu.MenuXMLDecoder; 45 46 import com.miginfocom.ashape.interaction.InteractionEvent; 47 import com.miginfocom.ashape.interaction.InteractionListener; 48 import com.miginfocom.beans.DateAreaBean; 49 import com.miginfocom.calendar.activity.view.ActivityView; 50 import com.miginfocom.calendar.category.Category; 51 import com.miginfocom.calendar.category.CategoryDepository; 52 import com.miginfocom.calendar.category.CategoryFilter; 53 import com.miginfocom.calendar.datearea.ActivityDragResizeEvent; 54 import com.miginfocom.calendar.datearea.ActivityDragResizeListener; 55 import com.miginfocom.calendar.datearea.ActivityMoveEvent; 56 import com.miginfocom.calendar.datearea.ActivityMoveListener; 57 import com.miginfocom.calendar.datearea.DateArea; 58 import com.miginfocom.calendar.datearea.DefaultDateArea; 59 import com.miginfocom.util.MigUtil; 60 import com.miginfocom.util.PropertyKey; 61 import com.miginfocom.util.dates.DateRange; 62 import com.miginfocom.util.dates.DateRangeI; 63 import com.miginfocom.util.dates.ImmutableDateRange; 64 import com.miginfocom.util.dates.MutableDateRange; 65 import com.miginfocom.util.expression.LogicalExpression; 66 import com.miginfocom.util.filter.ExpressionFilter; 67 import com.miginfocom.util.filter.Filter; 68 import com.miginfocom.util.states.ToolTipProvider; 69 70 74 public class MainCalendarController implements InteractionListener, 75 ActivityMoveListener, ICalendarView, ActivityDragResizeListener { 76 77 private static final Logger LOG = Logger 78 .getLogger("org.columba.calendar.ui.calendar"); 79 80 public static final String MAIN_WEEKS_CONTEXT = "mainWeeks"; 81 82 public static final String MAIN_DAYS_CONTEXT = "mainDays"; 83 84 private int currentViewMode = ICalendarView.VIEW_MODE_WEEK; 85 86 88 public static final String PROP_FILTERED = "filterRow"; 89 90 private static final int WEEKS_PER_YEAR = 52; 92 94 private static final int DAYS_PER_YEAR = 365; 96 98 private IActivity selectedActivity; 99 100 private com.miginfocom.beans.DateAreaBean dateAreaBean; 101 102 private com.miginfocom.beans.DateAreaBean monthlyDateAreaBean; 103 104 private com.miginfocom.beans.DateAreaBean currentDateAreaBean; 105 106 private com.miginfocom.calendar.activity.Activity selectedInternalActivitiy; 107 108 private JPanel panel = new JPanel (); 109 110 private EventListenerList listenerList = new EventListenerList (); 111 112 private ExtendablePopupMenu menu; 113 114 private ICalendarMediator mediator; 115 116 119 public MainCalendarController(ICalendarMediator mediator) { 120 super(); 121 122 this.mediator = mediator; 123 124 panel = new JPanel (); 125 panel.setLayout(new BorderLayout ()); 126 127 dateAreaBean = DateAreaBeanFactory.initDailyDateArea(); 128 registerListeners(dateAreaBean); 129 monthlyDateAreaBean = DateAreaBeanFactory.initMonthlyDateArea(); 130 registerListeners(monthlyDateAreaBean); 131 132 currentDateAreaBean = dateAreaBean; 134 135 setViewMode(currentViewMode); 136 137 panel.repaint(); 138 139 } 140 141 146 public JPopupMenu getPopupMenu() { 147 return menu; 148 } 149 150 153 public void createPopupMenu(ICalendarMediator mediator) { 154 155 InputStream is = this.getClass().getResourceAsStream( 156 "/org/columba/calendar/action/contextmenu_calendar.xml"); 157 158 menu = new MenuXMLDecoder(mediator).createPopupMenu(is); 159 160 } 161 162 private DateAreaBean initComponents(boolean dailyView) { 163 panel.removeAll(); 164 165 if (dailyView) { 166 panel.add(dateAreaBean, BorderLayout.CENTER); 167 return dateAreaBean; 168 } else { 169 panel.add(monthlyDateAreaBean, BorderLayout.CENTER); 170 return monthlyDateAreaBean; 171 } 172 173 } 174 175 178 private void registerListeners(DateAreaBean localDateAreaBean) { 179 ToolTipProvider ttp = new ToolTipProvider() { 180 public int configureToolTip(JToolTip toolTip, MouseEvent e, 181 Object source) { 182 if (e.getID() == MouseEvent.MOUSE_MOVED 183 && source instanceof ActivityView) { 184 toolTip.setTipText(((ActivityView) source).getModel() 186 .getSummary()); 187 return ToolTipProvider.SHOW_TOOLTIP; 188 } else { 189 return ToolTipProvider.HIDE_TOOLTIP; 190 } 191 } 192 }; 193 194 localDateAreaBean.getDateArea().setToolTipProvider(ttp); 195 196 ((DefaultDateArea) localDateAreaBean.getDateArea()) 197 .addMouseListener(new MyMouseListener()); 198 199 ((DefaultDateArea) localDateAreaBean.getDateArea()) 200 .addInteractionListener(this); 201 202 205 ((DefaultDateArea) localDateAreaBean.getDateArea()) 206 .addActivityDragResizeListener(this); 207 208 } 209 210 215 public IActivity getSelectedActivity() { 216 return selectedActivity; 217 } 218 219 224 public JComponent getView() { 225 return panel; 226 } 227 228 233 public void setViewMode(int mode) { 234 235 this.currentViewMode = mode; 236 237 int viewMode = -1; 238 239 int days = -1; 240 241 DateRange newVisRange = new DateRange(currentDateAreaBean.getDateArea() 242 .getVisibleDateRangeCorrected()); 243 244 switch (mode) { 245 case ICalendarView.VIEW_MODE_DAY: 246 247 viewMode = DateRangeI.RANGE_TYPE_DAY; 248 249 days = 1; 250 251 currentDateAreaBean = initComponents(true); 252 253 break; 254 case ICalendarView.VIEW_MODE_WEEK: 255 256 viewMode = DateRangeI.RANGE_TYPE_DAY; 257 258 days = 7; 259 260 currentDateAreaBean = initComponents(true); 261 262 break; 263 case ICalendarView.VIEW_MODE_WORK_WEEK: 264 265 viewMode = DateRangeI.RANGE_TYPE_DAY; 266 267 days = 5; 268 269 currentDateAreaBean = initComponents(true); 270 271 break; 272 case ICalendarView.VIEW_MODE_MONTH: 273 274 viewMode = DateRangeI.RANGE_TYPE_MONTH; 275 276 days = 1; 277 278 currentDateAreaBean = initComponents(false); 279 280 break; 281 } 282 283 DefaultDateArea dateArea = currentDateAreaBean.getDateArea(); 284 285 newVisRange.setSize(viewMode, days, MutableDateRange.ALIGN_CENTER_UP); 286 dateArea.setVisibleDateRange(newVisRange); 287 288 panel.validate(); 289 panel.repaint(); 290 291 } 292 293 296 public void printDebug(DateRange dateRange) { 297 Calendar todayCalendar = Calendar.getInstance(); 298 int today = todayCalendar.get(java.util.Calendar.DAY_OF_YEAR); 299 300 Calendar startCalendar = dateRange.getStart(); 301 int selectedStartDay = startCalendar 302 .get(java.util.Calendar.DAY_OF_YEAR); 303 304 Calendar endCalendar = dateRange.getStart(); 305 int selectedEndDay = endCalendar.get(java.util.Calendar.DAY_OF_YEAR); 306 307 } 308 309 314 public void recreateFilterRows() { 315 filterDateArea(dateAreaBean); 316 filterDateArea(monthlyDateAreaBean); 317 } 318 319 322 private void filterDateArea(DateAreaBean localDateAreaBean) { 323 Collection cats = CategoryDepository.getRoot().getChildrenDeep(); 324 325 DateArea dateArea = localDateAreaBean.getDateArea(); 326 327 for (Iterator it = cats.iterator(); it.hasNext();) { 328 Category cat = (Category) it.next(); 329 Object isHidden = cat 330 .getProperty(PropertyKey.getKey(PROP_FILTERED)); 331 if (MigUtil.isTrue(isHidden) == false) 332 it.remove(); 333 } 334 335 Filter showFilter = new CategoryFilter(new ExpressionFilter( 336 "hideFilter", new LogicalExpression(Category.PROP_IS_HIDDEN, 337 LogicalExpression.NOT_EQUALS, Boolean.TRUE))); 338 dateArea.setActivityViewFilter(showFilter); 339 340 if (cats.size() == 0) { 341 342 dateArea.setRowFilters(null); 343 344 } else { 345 346 CategoryFilter[] catRestr = new CategoryFilter[cats.size()]; 347 int i = 0; 348 for (Iterator it = cats.iterator(); it.hasNext();) { 349 Category cat = (Category) it.next(); 350 catRestr[i++] = new CategoryFilter(cat, true, true); 351 } 352 353 dateArea.setRowFilters(catRestr); 354 } 355 356 localDateAreaBean.revalidate(); 357 localDateAreaBean.repaint(); 358 } 359 360 365 public void interactionOccured(InteractionEvent e) { 366 Object value = e.getCommand().getValue(); 367 368 System.out.println("interactionOccured=" + value.toString()); 369 370 if (MigUtil.equals(value, DefaultDateArea.AE_MOUSE_ENTERED)) { 371 com.miginfocom.calendar.activity.Activity activity = ((ActivityView) e 373 .getInteractor().getInteracted()).getModel(); 374 System.out.println("MouseOver - activity=" + activity.getID()); 375 378 } 379 380 final Object o = e.getInteractor().getInteracted(); 381 382 if (e.getSourceEvent() instanceof MouseEvent ) { 383 final Point p = ((MouseEvent ) e.getSourceEvent()).getPoint(); 384 Object commandValue = e.getCommand().getValue(); 385 386 389 401 if (o instanceof ActivityView) { 403 selectedInternalActivitiy = ((ActivityView) o).getModel(); 405 406 selectedActivity = new Activity(selectedInternalActivitiy); 408 409 fireSelectionChanged(new IActivity[] { selectedActivity }); 411 412 if (DefaultDateArea.AE_POPUP_TRIGGER.equals(commandValue)) { 414 415 419 menu.show(currentDateAreaBean.getDateArea(), p.x, p.y); 421 422 } else if (DefaultDateArea.AE_DOUBLE_CLICKED 423 .equals(commandValue)) { 424 425 mediator.fireStartActivityEditing(selectedActivity); 426 } 427 } else { 428 System.out.println("---> event in calendar"); 430 431 if (DefaultDateArea.AE_DOUBLE_CLICKED.equals(commandValue)) { 432 433 } 436 } 437 } 438 } 439 440 446 public void activityMoved(ActivityMoveEvent e) { 447 448 com.miginfocom.calendar.activity.Activity activity = e.getActivity(); 449 System.out.println("activity moved=" + activity.getID()); 450 } 451 452 457 public void viewToday() { 458 DateRange newVisRange = new DateRange(currentDateAreaBean.getDateArea() 459 .getVisibleDateRange()); 460 printDebug(newVisRange); 461 462 Calendar todayCalendar = Calendar.getInstance(); 463 long difference = todayCalendar.getTimeInMillis() 464 - newVisRange.getMiddleMillis(); 465 long difference_in_days = difference / (1000 * 60 * 60 * 24); 466 467 newVisRange = rollWithYears(newVisRange, 468 java.util.Calendar.DAY_OF_YEAR, (int) (difference_in_days)); 469 470 currentDateAreaBean.getDateArea().setVisibleDateRange(newVisRange); 471 472 currentDateAreaBean.revalidate(); 473 currentDateAreaBean.repaint(); 474 } 475 476 public static int getWeekOfYear(Calendar arg) { 477 return ((arg.get(java.util.Calendar.DAY_OF_YEAR) - 1) / 7) + 1; 479 } 480 481 public static DateRange rollWithYears(DateRange range, int mode, int amount) { 482 DateRange newVisRange = range; 483 DateRange rolledMiddle; 484 485 switch (mode) { 486 case java.util.Calendar.DAY_OF_YEAR: 487 488 rolledMiddle = new DateRange(newVisRange.getMiddle(), newVisRange 489 .getMiddle().getTimeZone(), newVisRange.getLocale()); 490 491 if ((rolledMiddle.getStartField(java.util.Calendar.DAY_OF_YEAR) 492 + amount <= 0)) { 493 int days_of_year = rolledMiddle.getStartField(java.util.Calendar.DAY_OF_YEAR); 494 rolledMiddle.roll(java.util.Calendar.DAY_OF_YEAR, amount); 495 int day_difference = days_of_year - Math.abs(amount); 497 int years = (int) (Math.floor((day_difference) / DAYS_PER_YEAR) + (day_difference <= 0 ? -1 : 0) ); 498 rolledMiddle.roll(java.util.Calendar.YEAR, years); 499 } else if (rolledMiddle 500 .getStartField(java.util.Calendar.DAY_OF_YEAR) 501 + amount > DAYS_PER_YEAR) { 502 rolledMiddle.roll(java.util.Calendar.DAY_OF_YEAR, amount); 503 rolledMiddle.roll(java.util.Calendar.YEAR, 504 ((amount - 1) / DAYS_PER_YEAR) + 1); 505 } else { 506 rolledMiddle.roll(java.util.Calendar.DAY_OF_YEAR, amount); 507 } 508 509 rolledMiddle.setSize(DateRange.RANGE_TYPE_DAY, newVisRange.getSize( 510 DateRange.RANGE_TYPE_DAY, true), 511 MutableDateRange.ALIGN_CENTER_DOWN); 512 513 newVisRange.setStart(rolledMiddle.getStart()); 514 newVisRange.setEnd(rolledMiddle.getEnd(), true); 515 516 break; 517 case java.util.Calendar.WEEK_OF_YEAR: 518 rolledMiddle = rollWithYears(new DateRange(newVisRange.getMiddle(), 519 newVisRange.getMiddle().getTimeZone(), newVisRange 520 .getLocale()), java.util.Calendar.DAY_OF_YEAR, 521 amount * 7); 522 523 rolledMiddle.setSize(DateRange.RANGE_TYPE_DAY, newVisRange.getSize( 524 DateRange.RANGE_TYPE_DAY, true), 525 MutableDateRange.ALIGN_CENTER_DOWN); 526 527 if (getWeekOfYear(rolledMiddle.getStart()) > getWeekOfYear(rolledMiddle 528 .getEnd())) { 529 rolledMiddle.setSize(DateRange.RANGE_TYPE_DAY, 1, 532 MutableDateRange.ALIGN_CENTER_UP); 533 rolledMiddle.setSize(DateRange.RANGE_TYPE_DAY, newVisRange 534 .getSize(DateRange.RANGE_TYPE_DAY, true), 535 MutableDateRange.ALIGN_CENTER_UP); 536 } 537 538 newVisRange.setStart(rolledMiddle.getStart()); 539 newVisRange.setEnd(rolledMiddle.getEnd(), true); 540 541 break; 542 default: 543 LOG.severe("Cannot roll! " + mode); 544 } 545 546 return newVisRange; 547 } 548 549 554 public void viewNext() { 555 DateRange newVisRange = new DateRange(currentDateAreaBean.getDateArea() 556 .getVisibleDateRangeCorrected()); 557 558 switch (currentViewMode) { 559 case ICalendarView.VIEW_MODE_DAY: 560 561 newVisRange = rollWithYears(newVisRange, 563 java.util.Calendar.DAY_OF_YEAR, 1); 564 565 break; 566 case ICalendarView.VIEW_MODE_WEEK: 567 568 newVisRange = rollWithYears(newVisRange, 570 java.util.Calendar.DAY_OF_YEAR, 7); 571 572 break; 573 case ICalendarView.VIEW_MODE_WORK_WEEK: 574 575 newVisRange = rollWithYears(newVisRange, 577 java.util.Calendar.DAY_OF_YEAR, 7); 578 579 break; 580 case ICalendarView.VIEW_MODE_MONTH: 581 582 newVisRange = rollWithYears(newVisRange, 584 java.util.Calendar.WEEK_OF_YEAR, 1); 585 586 break; 587 } 588 589 currentDateAreaBean.getDateArea().setVisibleDateRange(newVisRange); 590 591 currentDateAreaBean.revalidate(); 592 currentDateAreaBean.repaint(); 593 } 594 595 600 public void viewPrevious() { 601 DateRange newVisRange = new DateRange(currentDateAreaBean.getDateArea() 602 .getVisibleDateRangeCorrected()); 603 604 switch (currentViewMode) { 605 case ICalendarView.VIEW_MODE_DAY: 606 607 newVisRange = rollWithYears(newVisRange, 609 java.util.Calendar.DAY_OF_YEAR, -1); 610 611 break; 612 case ICalendarView.VIEW_MODE_WEEK: 613 614 newVisRange = rollWithYears(newVisRange, 616 java.util.Calendar.DAY_OF_YEAR, -7); 617 618 break; 619 case ICalendarView.VIEW_MODE_WORK_WEEK: 620 621 newVisRange = rollWithYears(newVisRange, 623 java.util.Calendar.DAY_OF_YEAR, -7); 624 625 break; 626 case ICalendarView.VIEW_MODE_MONTH: 627 628 newVisRange = rollWithYears(newVisRange, 630 java.util.Calendar.WEEK_OF_YEAR, -1); 631 632 break; 633 } 634 635 currentDateAreaBean.getDateArea().setVisibleDateRange(newVisRange); 636 637 currentDateAreaBean.revalidate(); 638 currentDateAreaBean.repaint(); 639 } 640 641 646 public void setVisibleDateRange(IDateRange dateRange) { 647 ImmutableDateRange newRange = new ImmutableDateRange(dateRange 648 .getStartTime().getTimeInMillis(), dateRange.getEndTime() 649 .getTimeInMillis(), false, null, null); 650 651 currentDateAreaBean.getDateArea().setVisibleDateRange(newRange); 652 653 currentDateAreaBean.revalidate(); 654 } 655 656 661 public void activityDragResized(ActivityDragResizeEvent e) { 662 System.out.println(e); 663 664 com.miginfocom.calendar.activity.ActivityList activityList = (com.miginfocom.calendar.activity.ActivityList) e 665 .getSource(); 666 667 for (int i = 0, size = activityList.size(); i < size; i++) { 668 System.out.println("Changed: " + activityList.get(i)); 669 671 mediator.fireActivityMoved(selectedActivity); 672 } 673 674 } 675 676 679 public void addSelectionChangedListener( 680 IActivitySelectionChangedListener listener) { 681 listenerList.add(IActivitySelectionChangedListener.class, listener); 682 } 683 684 687 public void removeSelectionChangedListener( 688 IActivitySelectionChangedListener listener) { 689 listenerList.remove(IActivitySelectionChangedListener.class, listener); 690 } 691 692 696 private void fireSelectionChanged(IActivity[] selection) { 697 ActivitySelectionChangedEvent e = new ActivitySelectionChangedEvent( 698 this, selection); 699 Object [] listeners = listenerList.getListenerList(); 701 702 for (int i = listeners.length - 2; i >= 0; i -= 2) { 705 if (listeners[i] == IActivitySelectionChangedListener.class) { 706 ((IActivitySelectionChangedListener) listeners[i + 1]) 707 .selectionChanged(e); 708 } 709 } 710 } 711 712 class MyMouseListener extends MouseAdapter { 713 714 @Override 715 public void mouseClicked(MouseEvent e) { 716 handleEvent(e); 717 } 718 719 @Override 720 public void mousePressed(MouseEvent e) { 721 handlePopupEvent(e); 722 } 723 724 @Override 725 public void mouseReleased(MouseEvent e) { 726 handlePopupEvent(e); 727 } 728 729 732 private void handlePopupEvent(MouseEvent e) { 733 Point p = e.getPoint(); 734 if (e.isPopupTrigger()) { 735 menu.show(e.getComponent(), p.x, p.y); 737 System.out.println("--> popup"); 738 } else 739 System.out.println("--> no popup"); 740 } 741 742 745 private void handleEvent(MouseEvent e) { 746 747 Point p = e.getPoint(); 748 ActivityView view = currentDateAreaBean.getDateArea() 749 .getActivityViewAt(p.x, p.y); 750 751 if (view != null) { 752 selectedInternalActivitiy = ((ActivityView) view).getModel(); 754 755 selectedActivity = new Activity(selectedInternalActivitiy); 757 758 fireSelectionChanged(new IActivity[] { selectedActivity }); 760 } else { 761 selectedInternalActivitiy = null; 763 764 fireSelectionChanged(new Activity[] {}); 765 } 766 767 if (e.getClickCount() == 2) { 768 MutableDateRange range = currentDateAreaBean.getDateArea() 769 .getDateRangeForPoint(e.getPoint(), true, true, true); 770 mediator 771 .fireCreateActivity(new org.columba.calendar.model.DateRange( 772 range.getStart(), range.getEnd(true))); 773 } 774 } 775 } 776 } | Popular Tags |