org.eclipse.mylyn.internal.jira.ui.editor.WorkLogPart.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.internal.jira.ui.editor.WorkLogPart.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2009 Tasktop Technologies and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.jira.ui.editor;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.mylyn.internal.jira.core.WorkLogConverter;
import org.eclipse.mylyn.internal.jira.core.model.JiraWorkLog;
import org.eclipse.mylyn.internal.jira.core.service.JiraTimeFormat;
import org.eclipse.mylyn.internal.jira.core.util.JiraUtil;
import org.eclipse.mylyn.internal.jira.ui.JiraConnectorUi;
import org.eclipse.mylyn.internal.tasks.ui.editors.EditorUtil;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.ui.TasksUiUtil;
import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPart;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

/**
 * @author Steffen Pingel
 * @author Thomas Ehrnhoefer
 */
public class WorkLogPart extends AbstractTaskEditorPart {

    private static final String ID_POPUP_MENU = "org.eclipse.mylyn.jira.ui.editor.menu.worklog"; //$NON-NLS-1$

    private final String[] columns = { Messages.WorkLogPart_Creator, Messages.WorkLogPart_Date,
            Messages.WorkLogPart_Worked, Messages.WorkLogPart_Description };

    private final int[] columnWidths = { 130, 70, 100, 150 };

    private List<TaskAttribute> logEntries;

    private boolean hasIncoming;

    private MenuManager menuManager;

    private Composite composite;

    private long newWorkDoneAmount = 0;

    private Calendar newWorkDoneDate = new GregorianCalendar();

    private String newWorkDoneDescription = ""; //$NON-NLS-1$

    private boolean newWorkDoneAutoAdjust = true;

    private DateTime dateWidget;

    private DateTime timeWidget;

    private Text timeSpentText;

    private boolean includeWorklog;

    private JiraWorkLog newWorkLog;

    private Section newWorkLogSection;

    public WorkLogPart() {
        setPartName(Messages.WorkLogPart_Work_Log);
    }

    private void createTable(FormToolkit toolkit, final Composite composite) {
        Table table = toolkit.createTable(composite, SWT.MULTI | SWT.FULL_SELECTION);
        table.setLinesVisible(true);
        table.setHeaderVisible(true);
        table.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).hint(500, SWT.DEFAULT)
                .applyTo(table);

        for (int i = 0; i < columns.length; i++) {
            TableColumn column = new TableColumn(table, SWT.LEFT, i);
            column.setText(columns[i]);
            column.setWidth(columnWidths[i]);
        }
        table.getColumn(2).setAlignment(SWT.RIGHT);

        TableViewer attachmentsViewer = new TableViewer(table);
        attachmentsViewer.setUseHashlookup(true);
        attachmentsViewer.setColumnProperties(columns);
        ColumnViewerToolTipSupport.enableFor(attachmentsViewer, ToolTip.NO_RECREATE);

        attachmentsViewer.setSorter(new ViewerSorter() {
            @Override
            public int compare(Viewer viewer, Object e1, Object e2) {
                JiraWorkLog item1 = (JiraWorkLog) e1;
                JiraWorkLog item2 = (JiraWorkLog) e2;
                Date created1 = item1.getCreated();
                Date created2 = item2.getCreated();
                if (created1 != null && created2 != null) {
                    return created1.compareTo(created2);
                } else if (created1 == null && created2 != null) {
                    return -1;
                } else if (created1 != null && created2 == null) {
                    return 1;
                } else {
                    return 0;
                }
            }
        });

        List<JiraWorkLog> workLogList = new ArrayList<JiraWorkLog>(logEntries.size());
        for (TaskAttribute attribute : logEntries) {
            JiraWorkLog log = new WorkLogConverter().createFrom(attribute);
            workLogList.add(log);
        }
        attachmentsViewer.setContentProvider(new ArrayContentProvider());
        attachmentsViewer.setLabelProvider(new WorkLogTableLabelProvider(getJiraTimeFormat()));
        attachmentsViewer.addOpenListener(new IOpenListener() {
            public void open(OpenEvent event) {
                TasksUiUtil.openUrl(
                        JiraConnectorUi.getTaskWorkLogUrl(getModel().getTaskRepository(), getModel().getTask()));
            }
        });
        attachmentsViewer.addSelectionChangedListener(getTaskEditorPage());
        attachmentsViewer.setInput(workLogList);

        menuManager = new MenuManager();
        menuManager.setRemoveAllWhenShown(true);
        menuManager.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                // TODO provide popup menu
            }
        });
        getTaskEditorPage().getEditorSite().registerContextMenu(ID_POPUP_MENU, menuManager, attachmentsViewer,
                false);
        Menu menu = menuManager.createContextMenu(table);
        table.setMenu(menu);
    }

    @Override
    public void createControl(Composite parent, final FormToolkit toolkit) {
        initialize();

        int style = ExpandableComposite.TWISTIE;
        if (hasIncoming) {
            style |= ExpandableComposite.EXPANDED;
        }
        final Section section = createSection(parent, toolkit, style);
        EditorUtil.setTitleBarForeground(section, toolkit.getColors().getColor(IFormColors.TITLE));
        section.redraw();
        section.setText(getPartName() + " (" + logEntries.size() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
        if (hasIncoming) {
            expandSection(toolkit, section);
        } else {
            section.addExpansionListener(new ExpansionAdapter() {
                @Override
                public void expansionStateChanged(ExpansionEvent event) {
                    if (composite == null) {
                        expandSection(toolkit, section);
                        getTaskEditorPage().reflow();
                    }
                }
            });
        }
        setSection(toolkit, section);
    }

    private void expandSection(FormToolkit toolkit, Section section) {
        composite = toolkit.createComposite(section);
        composite.setLayout(new GridLayout(1, false));
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));

        getTaskEditorPage().registerDefaultDropListener(section);

        if (logEntries.size() > 0) {
            createTable(toolkit, composite);
        } else {
            Label label = toolkit.createLabel(composite, Messages.WorkLogPart_No_work_logged);
            getTaskEditorPage().registerDefaultDropListener(label);
        }
        newWorkLogSection = createNewWorkLogSection(toolkit, composite);
        newWorkLogSection.addExpansionListener(new ExpansionAdapter() {
            private boolean firstTime = true;

            @Override
            public void expansionStateChanged(ExpansionEvent e) {
                if (firstTime) {
                    firstTime = false;
                } else {
                    setTimeSpendDecorator();
                }
            }
        });
        GridDataFactory.fillDefaults().grab(true, false).applyTo(newWorkLogSection);
        section.setClient(composite);

        toolkit.paintBordersFor(composite);
    }

    @Override
    public void dispose() {
        if (menuManager != null) {
            menuManager.dispose();
        }
        super.dispose();
    }

    private void initialize() {
        logEntries = getTaskData().getAttributeMapper().getAttributesByType(getTaskData(),
                WorkLogConverter.TYPE_WORKLOG);
        for (TaskAttribute attachmentAttribute : logEntries) {
            if (getModel().hasIncomingChanges(attachmentAttribute)) {
                hasIncoming = true;
                break;
            }
        }

        TaskAttribute newWorkLogAttribute = getTaskData().getRoot()
                .getAttribute(WorkLogConverter.ATTRIBUTE_WORKLOG_NEW);
        JiraWorkLog log = null;
        if (newWorkLogAttribute != null) {
            log = new WorkLogConverter().createFrom(newWorkLogAttribute);
        }

        if (newWorkLogAttribute != null && log != null) {
            newWorkDoneAmount = log.getTimeSpent();
            newWorkDoneDate = new GregorianCalendar();
            if (log.getStartDate() != null) {
                newWorkDoneDate.setTime(log.getStartDate());
            }
            newWorkDoneDescription = log.getComment();
            newWorkDoneAutoAdjust = log.isAutoAdjustEstimate();
            TaskAttribute newWorkLogSubmitAttribute = newWorkLogAttribute
                    .getAttribute(WorkLogConverter.ATTRIBUTE_WORKLOG_NEW_SUBMIT_FLAG);
            if (newWorkLogSubmitAttribute != null
                    && newWorkLogSubmitAttribute.getValue().equals(String.valueOf(true))) {
                includeWorklog = true;
            }
        }
    }

    private JiraTimeFormat getJiraTimeFormat() {
        return JiraUtil.getTimeFormat(getTaskEditorPage().getTaskRepository());
    }

    private Section createNewWorkLogSection(FormToolkit toolkit, Composite parent) {
        final Section newWorkLogSection = toolkit.createSection(parent,
                ExpandableComposite.LEFT_TEXT_CLIENT_ALIGNMENT | ExpandableComposite.TWISTIE
                        | ExpandableComposite.CLIENT_INDENT);
        newWorkLogSection.setText(""); //$NON-NLS-1$

        final Button createNewWorkLog = toolkit.createButton(newWorkLogSection, Messages.WorkLogPart_Log_Work_Done,
                SWT.CHECK);
        GridDataFactory.fillDefaults().grab(true, false).align(SWT.LEFT, SWT.CENTER).applyTo(createNewWorkLog);
        createNewWorkLog.setSelection(includeWorklog);
        newWorkLogSection.setExpanded(includeWorklog);
        createNewWorkLog.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (e.getSource().equals(createNewWorkLog)) {
                    newWorkLogSection.setExpanded(createNewWorkLog.getSelection());
                    addWorkLogToModel();
                    includeWorklog = createNewWorkLog.getSelection();
                    setSubmitWorklog();
                }
            }
        });
        newWorkLogSection.setTextClient(createNewWorkLog);

        Composite newWorkLogComposite = toolkit.createComposite(newWorkLogSection, SWT.NONE);
        newWorkLogSection.setClient(newWorkLogComposite);
        newWorkLogComposite.setLayout(GridLayoutFactory.swtDefaults().spacing(10, 5).numColumns(3).create());

        toolkit.createLabel(newWorkLogComposite, Messages.WorkLogPart_Time_Spent);
        timeSpentText = toolkit.createText(newWorkLogComposite,
                getJiraTimeFormat().format(new Long(newWorkDoneAmount)));
        timeSpentText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                setTimeSpendDecorator();

                addWorkLogToModel();
            }
        });
        timeSpentText.setToolTipText(NLS.bind(Messages.WorkLogPart_Time_Spent_Explanation_Tooltip,
                JiraUtil.getWorkDaysPerWeek(getTaskEditorPage().getTaskRepository()),
                JiraUtil.getWorkHoursPerDay(getTaskEditorPage().getTaskRepository())));
        GridDataFactory.fillDefaults().span(2, 1).hint(135, SWT.DEFAULT).align(SWT.BEGINNING, SWT.FILL)
                .applyTo(timeSpentText);

        toolkit.createLabel(newWorkLogComposite, Messages.WorkLogPart_Start_Date);
        dateWidget = new DateTime(newWorkLogComposite, SWT.DATE);
        dateWidget.setYear(newWorkDoneDate.get(Calendar.YEAR));
        dateWidget.setMonth(newWorkDoneDate.get(Calendar.MONTH));
        dateWidget.setDay(newWorkDoneDate.get(Calendar.DAY_OF_MONTH));
        dateWidget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
        toolkit.adapt(dateWidget, true, true);
        GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.FILL).applyTo(dateWidget);
        dateWidget.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                collectDate();
                addWorkLogToModel();
            }
        });

        timeWidget = new DateTime(newWorkLogComposite, SWT.TIME);
        timeWidget.setHours(newWorkDoneDate.get(Calendar.HOUR_OF_DAY));
        timeWidget.setMinutes(newWorkDoneDate.get(Calendar.MINUTE));
        timeWidget.setSeconds(newWorkDoneDate.get(Calendar.SECOND));
        timeWidget.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
        toolkit.adapt(timeWidget, true, true);
        GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.FILL).applyTo(timeWidget);
        timeWidget.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                collectDate();
                addWorkLogToModel();
            }
        });

        toolkit.createLabel(newWorkLogComposite, Messages.WorkLogPart_Adjust_Estimate);
        Composite adjustComposite = toolkit.createComposite(newWorkLogComposite);
        adjustComposite.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).create());
        GridDataFactory.fillDefaults().span(2, 1).applyTo(adjustComposite);
        final Button autoAdjustButton = toolkit.createButton(adjustComposite, Messages.WorkLogPart_Auto_Adjust,
                SWT.RADIO);
        autoAdjustButton.setSelection(newWorkDoneAutoAdjust);
        autoAdjustButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                newWorkDoneAutoAdjust = autoAdjustButton.getSelection();
                addWorkLogToModel();
            }
        });
        autoAdjustButton.setToolTipText(Messages.WorkLogPart_Auto_Adjust_Explanation_Tooltip);
        Button leaveAdjustButton = toolkit.createButton(adjustComposite,
                Messages.WorkLogPart_Leave_Existing_Estimate, SWT.RADIO);
        leaveAdjustButton.setSelection(!newWorkDoneAutoAdjust);
        leaveAdjustButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                newWorkDoneAutoAdjust = autoAdjustButton.getSelection();
                addWorkLogToModel();
            }
        });
        leaveAdjustButton.setToolTipText(Messages.WorkLogPart_Leave_Existing_Explanation_Tooltip);

        toolkit.createLabel(newWorkLogComposite, Messages.WorkLogPart_Work_Description);
        final Text descriptionText = toolkit.createText(newWorkLogComposite, newWorkDoneDescription,
                SWT.WRAP | SWT.MULTI | SWT.V_SCROLL);
        descriptionText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                newWorkDoneDescription = descriptionText.getText();
                addWorkLogToModel();
            }
        });
        GridDataFactory.fillDefaults().grab(true, true).hint(150, 100).span(2, 1).applyTo(descriptionText);

        toolkit.paintBordersFor(newWorkLogComposite);
        return newWorkLogSection;
    }

    protected void collectDate() {
        if (newWorkDoneDate == null) {
            newWorkDoneDate = new GregorianCalendar();
        }
        newWorkDoneDate.set(dateWidget.getYear(), dateWidget.getMonth(), dateWidget.getDay(), timeWidget.getHours(),
                timeWidget.getMinutes(), timeWidget.getSeconds());
    }

    /**
     * Updates the worklog and returns true if it has changed
     */
    private boolean updateNewWorkLog() {
        JiraWorkLog tempworkLog = new JiraWorkLog();
        tempworkLog.setAuthor(getTaskEditorPage().getTaskRepository().getUserName());
        tempworkLog.setComment(newWorkDoneDescription);
        tempworkLog.setStartDate(newWorkDoneDate.getTime());
        tempworkLog.setTimeSpent(newWorkDoneAmount);
        tempworkLog.setAutoAdjustEstimate(newWorkDoneAutoAdjust);
        if (tempworkLog.equals(newWorkLog)) {
            return false;
        }
        newWorkLog = tempworkLog;
        return true;
    }

    private void addWorkLogToModel() {
        if (updateNewWorkLog()) {
            TaskAttribute attribute = getTaskData().getRoot().getAttribute(WorkLogConverter.ATTRIBUTE_WORKLOG_NEW);
            if (attribute == null) {
                attribute = getTaskData().getRoot().createAttribute(WorkLogConverter.ATTRIBUTE_WORKLOG_NEW);
            }
            new WorkLogConverter().applyTo(newWorkLog, attribute);
            getModel().attributeChanged(attribute);
        }
    }

    private void setSubmitWorklog() {
        TaskAttribute attribute = getTaskData().getRoot().getAttribute(WorkLogConverter.ATTRIBUTE_WORKLOG_NEW);
        if (attribute != null) {
            attribute.createAttribute(WorkLogConverter.ATTRIBUTE_WORKLOG_NEW_SUBMIT_FLAG)
                    .setValue(String.valueOf(includeWorklog));
            getModel().attributeChanged(attribute);
        }
    }

    private void setTimeSpendDecorator() {
        try {
            newWorkDoneAmount = getJiraTimeFormat().parse(timeSpentText.getText());
        } catch (ParseException e) {
            //ignore
        }
        JiraEditorUtil.setTimeSpentDecorator(timeSpentText, false, getTaskEditorPage().getTaskRepository());
    }
}