Java tutorial
/** * Copyright (C) 2008 Atlassian * * 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.atlassian.theplugin.idea.jira; import com.atlassian.connector.commons.jira.JIRAAction; import com.atlassian.connector.commons.jira.rss.JIRAException; import com.atlassian.theplugin.commons.jira.IntelliJJiraServerFacade; import com.atlassian.theplugin.commons.jira.JIRAIssueProgressTimestampCache; import com.atlassian.theplugin.commons.jira.JiraServerData; import com.atlassian.theplugin.commons.jira.JiraServerFacade; import com.atlassian.theplugin.commons.jira.api.JiraIssueAdapter; import com.atlassian.theplugin.configuration.JiraWorkspaceConfiguration; import com.atlassian.theplugin.idea.IdeaVersionFacade; import com.atlassian.theplugin.idea.action.issues.activetoolbar.tasks.PluginTaskManagerHelper; import com.atlassian.theplugin.idea.ui.DialogWithDetails; import com.atlassian.theplugin.util.PluginUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vcs.changes.ui.MultipleChangeListBrowser; import com.intellij.util.ui.UIUtil; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import org.jetbrains.annotations.NotNull; import javax.management.timer.Timer; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; 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.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class WorkLogCreateAndMaybeDeactivateDialog extends DialogWrapper { private static Icon copyIcon; private JPanel contentPane; private JTextArea comment; private JButton endDateChange; private JLabel endDateLabel; private JTextField timeSpentField; private JRadioButton btnLeaveUnchanged; private JRadioButton btnAutoUpdate; private JRadioButton btnUpdateManually; private JTextField remainingEstimateField; private JTextPane explanationText; private JPanel endTimePanel; private JButton copyButton; private JRadioButton btnChangeSetDoNothing; private JRadioButton btnChangeSetDeactivate; private JRadioButton btnChangeSetRemove; private ButtonGroup changeSetButtonGroup; private JPanel changesetPanel; private JPanel changesPanel; private JPanel timePanel; private JPanel commentPanel; private JCheckBox chkLogWork; private JCheckBox chkCommitChanges; private JiraIssueAdapter issue; private final Project project; private final boolean deactivateActiveIssue; private JiraWorkspaceConfiguration config; private Date endTime = Calendar.getInstance().getTime(); private WdhmInputListener timeSpentListener; private JTextArea issueComment; private WdhmInputListener remainingEstimateListener; private MultipleChangeListBrowser changesBrowserPanel; private JiraServerFacade facade; private JComboBox actionCombo; private JCheckBox cbPerformWorkflowAction; private JCheckBox cbCreateReviewAfterCommit; /** * Method generated by IntelliJ IDEA GUI Designer * >>> IMPORTANT!! <<< * DO NOT edit this method OR call it in your code! * * @noinspection ALL */ private void setupUI() { CellConstraints cc = new CellConstraints(); contentPane = new JPanel(new FormLayout("3dlu, fill:pref:grow, 3dlu", "3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, fill:pref:grow, 3dlu")); chkLogWork = new JCheckBox("Log Work", config.isActiveIssueLogWork() || !deactivateActiveIssue); contentPane.add(createTimePanel(), cc.xy(2, 6)); if (deactivateActiveIssue) { timePanel.setBorder( BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Time Tracking")); contentPane.add(createWorkflowActionCombo(), cc.xy(2, 2)); contentPane.add(chkLogWork, cc.xy(2, 4)); chkCommitChanges = new JCheckBox("Commit Changes", config.isActiveIssueCommitChanges()); // contentPane.add(chkCommitChanges, cc.xy(2, 8)); contentPane.add(createChangesetPanel(), cc.xy(2, 10)); JPanel basePanel = new JPanel(new FormLayout("pref, 5dlu, pref, fill:pref:grow", "pref")); basePanel.add(chkCommitChanges, cc.xy(1, 1)); cbCreateReviewAfterCommit = new JCheckBox("Create Review After Commit", false); // contentPane.add(cbCreateReviewAfterCommit, cc.xy(3, 8)); // basePanel.add(cbCreateReviewAfterCommit, cc.xy(3, 1)); contentPane.add(basePanel, cc.xy(2, 8)); contentPane.setMinimumSize(new Dimension(800, 600)); contentPane.setPreferredSize(new Dimension(800, 600)); } } private JPanel createWorkflowActionCombo() { JPanel p = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.fill = GridBagConstraints.NONE; cbPerformWorkflowAction = new JCheckBox("Perform Workflow Action"); cbPerformWorkflowAction.setEnabled(false); cbPerformWorkflowAction.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { actionCombo.setEnabled(cbPerformWorkflowAction.isSelected()); updateOKAction(); } }); p.add(cbPerformWorkflowAction, gbc); actionCombo = new JComboBox(); java.util.List<JIRAAction> actions = JiraIssueCachedAdapter.get(issue).getCachedActions(); if (actions != null) { fillActionCombo(actions); } else { Thread t = new Thread() { @Override public void run() { try { JiraServerData jiraServerData = issue.getJiraServerData(); if (jiraServerData != null) { final List<JIRAAction> actions = facade.getAvailableActions(jiraServerData, issue); JiraIssueCachedAdapter.get(issue).setCachedActions(actions); SwingUtilities.invokeLater(new Runnable() { public void run() { fillActionCombo(actions); updateOKAction(); } }); } } catch (final JIRAException e) { SwingUtilities.invokeLater(new Runnable() { public void run() { DialogWithDetails.showExceptionDialog(project, "Failed to retrieve available actions", e); } }); } } }; t.start(); } gbc.gridx++; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.LINE_START; p.add(actionCombo, gbc); JPanel filler = new JPanel(); filler.setOpaque(false); gbc.gridx++; gbc.weightx = 0.0; gbc.fill = GridBagConstraints.HORIZONTAL; p.add(filler, gbc); actionCombo.setEnabled(cbPerformWorkflowAction.isSelected()); return p; } private void fillActionCombo(List<JIRAAction> actions) { if (actions == null || actions.size() == 0) { cbPerformWorkflowAction.setSelected(false); cbPerformWorkflowAction.setEnabled(false); cbPerformWorkflowAction.setText(cbPerformWorkflowAction.getText() + " (no workflow actions available)"); } else { cbPerformWorkflowAction.setEnabled(true); cbPerformWorkflowAction.setSelected(config.isActiveIssueProgressWorkflowAction()); actionCombo.setEnabled(cbPerformWorkflowAction.isSelected()); long lastSelectedAction = config.getSelectedWorkflowAction(); JIRAAction actionToSelect = null; for (JIRAAction action : actions) { if (action.getId() == lastSelectedAction) { actionToSelect = action; } actionCombo.addItem(action); } if (actionToSelect != null) { actionCombo.setSelectedItem(actionToSelect); } } } public enum AfterCommit { DO_NOTHING, DEACTIVATE_CHANGESET, REMOVE_CHANGESET } private JPanel createChangesetPanel() { CellConstraints cc = new CellConstraints(); changesetPanel = new JPanel(new FormLayout("3dlu, fill:pref:grow, 3dlu", "3dlu, fill:d:grow, 3dlu, pref, 3dlu, pref, 3dlu, pref, pref, pref, 3dlu")); changesetPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Changes")); changesPanel = new JPanel(new BorderLayout(0, 0)); changesPanel.setPreferredSize(new Dimension(1, 1)); changesetPanel.add(changesPanel, cc.xy(2, 2)); JPanel labelPanel = new JPanel(new FormLayout("right:pref", "10dlu, pref:grow")); labelPanel.add(new JLabel("Comment:"), cc.xy(1, 1)); copyIcon = IconLoader.getIcon("/actions/copy.png"); copyButton = new JButton(copyIcon); copyButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { if (chkLogWork.isSelected()) { issueComment.setText(comment.getText()); } } }); labelPanel.add(copyButton, cc.xy(1, 2, CellConstraints.CENTER, CellConstraints.CENTER)); commentPanel = new JPanel(new FormLayout("right:pref, fill:d:grow", "40dlu")); commentPanel.add(labelPanel, cc.xy(1, 1, CellConstraints.FILL, CellConstraints.FILL)); comment = new JTextArea(); comment.setLineWrap(true); final JScrollPane scroll = new JScrollPane(); scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scroll.setViewportView(comment); commentPanel.add(scroll, cc.xyw(2, 1, 1, CellConstraints.FILL, CellConstraints.FILL)); changesetPanel.add(commentPanel, cc.xy(2, 4)); btnChangeSetDoNothing = new JRadioButton("Leave the current change list active", config.getActiveIssueAfterCommit() == AfterCommit.DO_NOTHING.ordinal()); btnChangeSetDeactivate = new JRadioButton( "Deactivate the currently active change list (activate the default change list)", config.getActiveIssueAfterCommit() == AfterCommit.DEACTIVATE_CHANGESET.ordinal()); btnChangeSetRemove = new JRadioButton( "Remove the currently active change list (activate the default change list)", config.getActiveIssueAfterCommit() == AfterCommit.REMOVE_CHANGESET.ordinal()); changeSetButtonGroup = new ButtonGroup(); changeSetButtonGroup.add(btnChangeSetDoNothing); changeSetButtonGroup.add(btnChangeSetDeactivate); changeSetButtonGroup.add(btnChangeSetRemove); if (changeSetButtonGroup.getSelection() == null) { btnChangeSetDoNothing.setSelected(true); } changesetPanel.add(new JLabel("After Commit:"), cc.xy(2, 6)); changesetPanel.add(btnChangeSetDoNothing, cc.xy(2, 8)); changesetPanel.add(btnChangeSetDeactivate, cc.xy(2, 9)); changesetPanel.add(btnChangeSetRemove, cc.xy(2, 10)); UIUtil.setEnabled(changesetPanel, chkCommitChanges.isSelected(), true); enableChangesetRadioButtons(true); return changesetPanel; } private static JTextField createFixedTextField(int width, int height) { JTextField f = new JTextField(); f.setMaximumSize(new Dimension(width, height)); f.setMinimumSize(new Dimension(width, height)); f.setPreferredSize(new Dimension(width, height)); return f; } private JPanel createTimePanel() { CellConstraints cc = new CellConstraints(); timePanel = new JPanel(new FormLayout( "3dlu, right:pref, 3dlu, left:pref, 3dlu, 10dlu, left:pref, 3dlu, left:pref:grow, 3dlu", "3dlu, pref, 3dlu, pref, pref, pref, 3dlu, pref, 10dlu, 40dlu, 3dlu")); timePanel.add(new JLabel("Time Spent:"), cc.xy(2, 2)); timeSpentField = createFixedTextField(120, 28); timePanel.add(timeSpentField, cc.xy(4, 2)); explanationText = new JTextPane(); explanationText.setText("An estimate of how much time you have spent working." + "\nThe format of this is ' *w *d *h *m ' (representing weeks," + "\ndays, hours and minutes - where * can be any number)" + "\nExamples: 4d, 5h 30m, 60m and 3w."); explanationText.setEditable(false); explanationText.setEnabled(true); explanationText .setFont(new Font(explanationText.getFont().getName(), explanationText.getFont().getStyle(), 10)); explanationText.setOpaque(false); timePanel.add(explanationText, cc.xywh(4, 4, 1, 4)); timePanel.add(new JLabel("Remaining Estimate:"), cc.xyw(6, 2, 2)); btnAutoUpdate = new JRadioButton("Auto Update", true); btnLeaveUnchanged = new JRadioButton("Leave Unchanged"); btnUpdateManually = new JRadioButton("Update Manually:"); timePanel.add(btnAutoUpdate, cc.xy(7, 4)); timePanel.add(btnLeaveUnchanged, cc.xy(7, 5)); timePanel.add(btnUpdateManually, cc.xy(7, 6)); remainingEstimateField = createFixedTextField(120, 28); timePanel.add(remainingEstimateField, cc.xy(9, 6)); ButtonGroup group = new ButtonGroup(); group.add(btnUpdateManually); group.add(btnAutoUpdate); group.add(btnLeaveUnchanged); endTimePanel = new JPanel(new FormLayout("fill:pref:grow, 3dlu, pref", "pref")); endDateLabel = new JLabel("1/01/08 12:00"); endTimePanel.add(endDateLabel, cc.xy(1, 1, CellConstraints.CENTER, CellConstraints.DEFAULT)); endDateChange = new JButton("Change"); endTimePanel.add(endDateChange, cc.xy(3, 1, CellConstraints.LEFT, CellConstraints.DEFAULT)); if (!deactivateActiveIssue) { timePanel.add(new JLabel("End Time:"), cc.xy(2, 8)); timePanel.add(endTimePanel, cc.xy(4, 8)); } timePanel.add(new JLabel("Comment:"), cc.xy(2, 10, CellConstraints.RIGHT, CellConstraints.TOP)); issueComment = new JTextArea(); issueComment.setLineWrap(true); final JScrollPane scroll = new JScrollPane(); scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); scroll.setViewportView(issueComment); timePanel.add(scroll, cc.xyw(4, 10, 6, CellConstraints.FILL, CellConstraints.FILL)); UIUtil.setEnabled(timePanel, chkLogWork.isSelected() || !deactivateActiveIssue, true); remainingEstimateField.setEnabled(false); return timePanel; } /** * @noinspection ALL */ public JComponent $$$getRootComponent$$$() { return contentPane; } private class WdhmInputListener extends JiraTimeWdhmTextFieldListener { private boolean matchFound = true; public WdhmInputListener(JTextField field) { super(field, false); } private class Period { public Period(String r) { regex = r; interval = 0; } public long getInterval() { return interval; } private long interval; public String getRegex() { return regex; } private String regex; public void findAndSet(String txt) { Pattern p = Pattern.compile("(\\d+)" + regex); Matcher m = p.matcher(txt); if (m.matches()) { String subs = txt.substring(m.start(1), m.end(1)); interval = Long.valueOf(subs); } } } private Period weeks = new Period("w"); private Period days = new Period("d"); private Period hours = new Period("h"); private Period minutes = new Period("m"); @Override public boolean stateChanged() { if (!getField().isEnabled()) { return false; } matchFound = !super.stateChanged(); updateOKAction(); if (matchFound) { String text = getField().getText(); weeks.findAndSet(text); days.findAndSet(text); hours.findAndSet(text); minutes.findAndSet(text); } return !matchFound; } public long getWeeks() { return weeks.interval; } public long getDays() { return days.interval; } public long getHours() { return hours.interval; } public long getMinutes() { return minutes.interval; } public boolean isOk() { return !matchFound; } } private void createUIComponents() { } private void updateOKAction() { boolean enable = timeSpentListener.isOk(); if (remainingEstimateField.isEnabled() && btnUpdateManually.isSelected() && enable) { enable = remainingEstimateListener.isOk(); } if (deactivateActiveIssue) { enable = enable || !chkLogWork.isSelected(); enable = enable && (!cbPerformWorkflowAction.isSelected() || actionCombo.getItemCount() > 0); } setOKActionEnabled(enable); } @Override protected void doOKAction() { if (deactivateActiveIssue) { config.setActiveIssueLogWork(chkLogWork.isSelected()); if (actionCombo != null && actionCombo.getSelectedItem() != null) { config.setSelectedWorkflowAction(((JIRAAction) actionCombo.getSelectedItem()).getId()); } config.setActiveIssueCommitChanges(chkCommitChanges.isSelected()); config.setActiveIssueProgressWorkflowAction(cbPerformWorkflowAction.isSelected()); config.setActiveIssueAfterCommit(btnChangeSetDoNothing.isSelected() ? AfterCommit.DO_NOTHING.ordinal() : (btnChangeSetDeactivate.isSelected() ? AfterCommit.DEACTIVATE_CHANGESET.ordinal() : AfterCommit.REMOVE_CHANGESET.ordinal())); } super.doOKAction(); } private static final long MILLIS_IN_HOUR = 1000 * 3600; private static final long MILLIS_IN_MINUTE = 1000 * 60; private static final long MAX_ALLOWED_HOURS = 5; @NotNull public static String getFormatedDurationString(Date startTime) { String result = ""; Date currentTime = new Date(); long timediff = currentTime.getTime() - startTime.getTime(); if (timediff <= 0) { return result; } long hours = timediff / MILLIS_IN_HOUR; // if somebody works without a break for more than 5 hours, then they are mutants and I don't serve mutants :) if (hours < MAX_ALLOWED_HOURS) { if (hours > 0) { result += Long.valueOf(hours).toString() + "h"; } long minutes = (timediff % MILLIS_IN_HOUR) / MILLIS_IN_MINUTE; if (minutes > 0) { if (hours > 0) { result += " "; } result += Long.valueOf(minutes).toString() + "m"; } } return result; } public WorkLogCreateAndMaybeDeactivateDialog(final JiraServerData jiraServer, final JiraIssueAdapter issue, final Project project, final String timeSpent, boolean deactivateActiveIssue, @NotNull final JiraWorkspaceConfiguration config) { super(false); this.issue = issue; this.project = project; this.deactivateActiveIssue = deactivateActiveIssue; this.config = config; facade = IntelliJJiraServerFacade.getInstance(); setupUI(); if (deactivateActiveIssue) { String prefix = PluginTaskManagerHelper.isValidIdeaVersion() ? "[Server Side] " : ""; setTitle(prefix + "Stop Work on Issue " + issue.getKey()); SwingUtilities.invokeLater(new Runnable() { public void run() { ChangeListManager changeListManager = ChangeListManager.getInstance(project); LocalChangeList chList = changeListManager.getDefaultChangeList(); changesBrowserPanel = IdeaVersionFacade.getInstance().getChangesListBrowser(project, changeListManager, chList.getChanges()); if (changesBrowserPanel != null) { changesPanel.add(changesBrowserPanel, BorderLayout.CENTER); changesPanel.validate(); } if (!PluginTaskManagerHelper.isValidIdeaVersion()) { if ("default".equalsIgnoreCase(chList.getName())) { btnChangeSetRemove.setEnabled(false); btnLeaveUnchanged.setSelected(btnChangeSetRemove.isSelected()); } } else { //when synchronizing task with IDEA task then do not allow to manage changelists enableChangesetRadioButtons(true); } } }); getOKAction().putValue(Action.NAME, prefix + "Stop Work"); } else { setTitle("Add Worklog for " + issue.getKey()); getOKAction().putValue(Action.NAME, "Add Worklog"); } setOKActionEnabled(false); if (timeSpent != null) { timeSpentField.setText(timeSpent); } else { Date startProgressTimestamp = JIRAIssueProgressTimestampCache.getInstance().getTimestamp(jiraServer, issue); if (startProgressTimestamp != null) { timeSpentField.setText(getFormatedDurationString(startProgressTimestamp)); } } final Calendar now = Calendar.getInstance(); endTime = now.getTime(); endDateLabel .setText(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(now.getTime())); endDateChange.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { //we catch NPE because of bug in CalendarPanel.java method private boolean isShowing(Date date); //null minDate. minDate sometines is not initialized see PL-1105 TimeDatePicker tdp = new TimeDatePicker(endTime); if (tdp.isOK()) { endTime = tdp.getSelectedDateTime(); String s = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) .format(endTime); endDateLabel.setText(s); } } catch (NullPointerException npe) { PluginUtil.getLogger().error("Cannot create TimeDatePicker object, NPE: " + npe.getMessage()); } } }); btnUpdateManually.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { boolean b = btnUpdateManually.isSelected(); remainingEstimateField.setEnabled(b); updateOKAction(); } }); if (jiraServer == null) { Messages.showErrorDialog(project, "There is no selected JIRA Server", "Error"); return; } chkLogWork.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { UIUtil.setEnabled(timePanel, chkLogWork.isSelected(), true); timeSpentListener.stateChanged(); remainingEstimateListener.stateChanged(); updateOKAction(); if (timePanel.isEnabled()) { remainingEstimateField.setEnabled(btnUpdateManually.isSelected()); } } }); if (deactivateActiveIssue) { chkCommitChanges.addActionListener((new ActionListener() { public void actionPerformed(ActionEvent e) { UIUtil.setEnabled(changesetPanel, chkCommitChanges.isSelected(), true); enableChangesetRadioButtons(false); } })); } init(); setCommentText(); validate(); timeSpentListener = new WdhmInputListener(timeSpentField); remainingEstimateListener = new WdhmInputListener(remainingEstimateField); timeSpentField.getDocument().addDocumentListener(timeSpentListener); remainingEstimateField.getDocument().addDocumentListener(remainingEstimateListener); timeSpentListener.stateChanged(); remainingEstimateListener.stateChanged(); updateOKAction(); } private void enableChangesetRadioButtons(boolean initEstimateButtons) { boolean enable = !PluginTaskManagerHelper.isValidIdeaVersion(); if (enable && initEstimateButtons) { btnLeaveUnchanged.setSelected(true); } btnChangeSetDeactivate.setEnabled(enable); btnChangeSetRemove.setEnabled(enable); btnLeaveUnchanged.setEnabled(enable); } private void setCommentText() { if (deactivateActiveIssue) { ChangeListManager changeListManager = ChangeListManager.getInstance(project); LocalChangeList chList = changeListManager.getDefaultChangeList(); if (chList != null) { if (chList.getComment().length() > 0) { comment.setText(chList.getComment()); } else { comment.setText(chList.getName()); } } else { comment.setText(""); } } } public boolean isLogTime() { return chkLogWork.isSelected(); } public boolean isCommitChanges() { return chkCommitChanges.isSelected(); } public boolean isCreateReviewAfterCommit() { // return cbCreateReviewAfterCommit.isSelected(); return false; } public AfterCommit getAfterCommitChangeSetAction() { if (btnChangeSetDeactivate.isSelected()) { return AfterCommit.DEACTIVATE_CHANGESET; } else if (btnChangeSetRemove.isSelected()) { return AfterCommit.REMOVE_CHANGESET; } return AfterCommit.DO_NOTHING; } public LocalChangeList getCurrentChangeList() { return changesBrowserPanel == null ? null : (LocalChangeList) changesBrowserPanel.getSelectedChangeList(); } public java.util.List<Change> getSelectedChanges() { return changesBrowserPanel != null ? changesBrowserPanel.getCurrentIncludedChanges() : null; } public String getTimeSpentString() { return timeSpentField.getText(); } public String getRemainingEstimateString() { return remainingEstimateField.getText(); } public void setRemainingEstimateString(String newRemainingEstimate) { remainingEstimateField.setText(newRemainingEstimate); } public Date getEndDate() { return (Date) endTime.clone(); } public Date getStartDate() { Date d = endTime; long t = d.getTime() - (timeSpentListener.getWeeks() * Timer.ONE_WEEK) - (timeSpentListener.getDays() * Timer.ONE_DAY) - (timeSpentListener.getHours() * Timer.ONE_HOUR) - (timeSpentListener.getMinutes() * Timer.ONE_MINUTE); d.setTime(t); return d; } public String getComment() { return comment.getText(); } public String getLogWorkComment() { return issueComment.getText(); } public RemainingEstimateUpdateMode getRemainingEstimateUpdateMode() { if (btnAutoUpdate.isSelected()) { return RemainingEstimateUpdateMode.AUTO; } if (btnLeaveUnchanged.isSelected()) { return RemainingEstimateUpdateMode.UNCHANGED; } return RemainingEstimateUpdateMode.MANUAL; } public void setRemainingEstimateUpdateMode(RemainingEstimateUpdateMode mode) { switch (mode) { case MANUAL: btnUpdateManually.setSelected(true); break; case UNCHANGED: btnLeaveUnchanged.setSelected(true); break; case AUTO: default: btnAutoUpdate.setSelected(true); break; } } public JIRAAction getSelectedAction() { if (!cbPerformWorkflowAction.isSelected() || actionCombo.getItemCount() == 0) { return null; } return (JIRAAction) actionCombo.getSelectedItem(); } @Override protected JComponent createCenterPanel() { return contentPane; } private class TimeDatePicker extends DatePicker { private JSpinner hour = new JSpinner(); private JSpinner minute = new JSpinner(); private SpinnerNumberModel hourModel; private SpinnerNumberModel minuteModel; TimeDatePicker(Date now) { super("Set End Time", now); init(); Calendar nowcal = Calendar.getInstance(); nowcal.setTime(now); nowcal.set(Calendar.HOUR_OF_DAY, 0); nowcal.set(Calendar.MINUTE, 0); nowcal.set(Calendar.SECOND, 0); nowcal.set(Calendar.MILLISECOND, 0); Calendar cal = Calendar.getInstance(); cal.setTime(now); hourModel = new SpinnerNumberModel(cal.get(Calendar.HOUR_OF_DAY), 0, 24, 1); minuteModel = new SpinnerNumberModel(cal.get(Calendar.MINUTE), 0, 60, 1); hour.setModel(hourModel); minute.setModel(minuteModel); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.weightx = 0.5; getPanelComponent().add(new JLabel("hour", SwingConstants.CENTER), gbc); gbc.gridy = 0; getPanelComponent().add(hour, gbc); gbc.gridx = 1; gbc.gridy = 0; getPanelComponent().add(new JLabel("minute", SwingConstants.CENTER), gbc); gbc.gridy = 1; getPanelComponent().add(minute, gbc); show(); } public Date getSelectedDateTime() { Date d = getSelectedDate(); long newTime = d.getTime(); newTime += hourModel.getNumber().intValue() * Timer.ONE_HOUR; newTime += minuteModel.getNumber().intValue() * Timer.ONE_MINUTE; d.setTime(newTime); return d; } } }