/* * Copyright 2013 Hewlett-Packard Development Company, L.P * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hp.alm.ali.idea.ui; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.vcs.versionBrowser.DateFilterComponent; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; import com.intellij.util.text.DateFormatUtil; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.LinkedList; import java.util.List; public class DateSelectorLabel extends JPanel implements LinkListener { private static final String ALL_DATES = "<all>"; private final Project project; private final LinkLabel linkLabel; private Long lowerBound; private Long upperBound; private final List<ChangeListener> listeners; public DateSelectorLabel(Project project, String title) { this.project = project; listeners = new LinkedList<ChangeListener>(); linkLabel = new LinkLabel(ALL_DATES, null); linkLabel.setListener(this, null); add(new JLabel(title + ":")); add(linkLabel); } @Override public void linkSelected(LinkLabel aSource, Object aLinkData) { Popup popup = new Popup(); popup.show(aSource, 0, 20); } public Long getLowerBound() { return lowerBound; } public Long getUpperBound() { return upperBound; } public void addChangeListener(ChangeListener changeListener) { synchronized (listeners) { listeners.add(changeListener); } } private void fireChangeEvent(Object source) { synchronized (listeners) { for(ChangeListener listener: listeners) { listener.stateChanged(new ChangeEvent(source)); } } } private static class Interval { private final String label; private final Long lowerBound; private final Long upperBound; private Interval(String label, Long lowerBound, Long upperBound) { this.label = label; this.lowerBound = lowerBound; this.upperBound = upperBound; } } private abstract class BaseActionListener implements ActionListener { protected abstract Interval calculateInterval(Calendar calendar); @Override public void actionPerformed(ActionEvent e) { Interval interval = calculateInterval(Calendar.getInstance()); linkLabel.setText(interval.label); lowerBound = interval.lowerBound; upperBound = interval.upperBound; fireChangeEvent(DateSelectorLabel.this); } } private class Popup extends JPopupMenu { public Popup() { final JMenuItem all = new JMenuItem("All"); all.addActionListener(new BaseActionListener() { @Override public Interval calculateInterval(Calendar calendar) { return new Interval(ALL_DATES, null, null); } }); add(all); add(new JSeparator()); final JMenuItem today = new JMenuItem("Today"); today.addActionListener(new BaseActionListener() { @Override public Interval calculateInterval(Calendar calendar) { stripTime(calendar); return new Interval(today.getText(), calendar.getTime().getTime(), null); } }); add(today); final JMenuItem yesterday = new JMenuItem("Yesterday"); yesterday.addActionListener(new BaseActionListener() { @Override public Interval calculateInterval(Calendar calendar) { calendar.add(Calendar.DAY_OF_MONTH, -1); stripTime(calendar); return new Interval(yesterday.getText(), calendar.getTime().getTime(), null); } }); add(yesterday); // TODO: this sprint, previous sprint? final JMenuItem lastFourWeeks = new JMenuItem("Last 4 weeks"); lastFourWeeks.addActionListener(new BaseActionListener() { @Override protected Interval calculateInterval(Calendar calendar) { stripTime(calendar); calendar.set(Calendar.DATE, -28); return new Interval(lastFourWeeks.getText(), calendar.getTime().getTime(), null); } }); add(lastFourWeeks); final JMenuItem thisYear = new JMenuItem("This year"); thisYear.addActionListener(new BaseActionListener() { @Override protected Interval calculateInterval(Calendar calendar) { stripTime(calendar); calendar.set(Calendar.MONTH, 0); calendar.set(Calendar.DAY_OF_MONTH, 1); return new Interval(thisYear.getText(), calendar.getTime().getTime(), null); } }); add(thisYear); add(new JSeparator()); JMenuItem interval = new JMenuItem("Custom..."); interval.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { final DateFormat dateFormat = DateFormatUtil.getDateFormat().getDelegate(); final DateFilterComponent dateFilterComponent = new DateFilterComponent(false, dateFormat); if (upperBound != null) { dateFilterComponent.setBefore(upperBound); } if (lowerBound != null) { dateFilterComponent.setAfter(lowerBound); } final DialogBuilder builder = new DialogBuilder(project); builder.setTitle("Specify Date Range"); builder.setOkActionEnabled(true); builder.setOkOperation(new Runnable() { @Override public void run() { if (dateFilterComponent.getAfter() >= 0) { lowerBound = dateFilterComponent.getAfter(); } else { lowerBound = null; } if (dateFilterComponent.getBefore() >= 0) { upperBound = dateFilterComponent.getBefore(); } else { upperBound = null; } builder.getDialogWrapper().close(0); if (lowerBound == null && upperBound == null) { linkLabel.setText(ALL_DATES); } else if(lowerBound == null) { linkLabel.setText("Before " + dateFormat.format(new Date(upperBound))); } else if(upperBound == null) { linkLabel.setText("After " + dateFormat.format(new Date(lowerBound))); } else { linkLabel.setText(dateFormat.format(new Date(lowerBound)) + "-" + dateFormat.format(new Date(upperBound))); } fireChangeEvent(DateSelectorLabel.this); } }); builder.setCenterPanel(dateFilterComponent.getPanel()); ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { builder.showModal(true); } }); } }); add(interval); } private void stripTime(Calendar calendar) { calendar.set(Calendar.MILLISECOND, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.HOUR_OF_DAY, 0); } } }