/* * Copyright 2014 Tomi Virtanen * * 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 org.tltv.gantt.demo; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Optional; import java.util.TimeZone; import javax.servlet.annotation.WebServlet; import org.tltv.gantt.Gantt; import org.tltv.gantt.Gantt.MoveEvent; import org.tltv.gantt.Gantt.ResizeEvent; import org.tltv.gantt.GanttTimeUtil; import org.tltv.gantt.client.shared.AbstractStep; import org.tltv.gantt.client.shared.Resolution; import org.tltv.gantt.client.shared.Step; import org.tltv.gantt.client.shared.SubStep; import org.tltv.gantt.demo.util.CssColorToColorPickerConverter; import org.tltv.gantt.demo.util.UriFragmentWrapperFactory; import org.tltv.gantt.demo.util.Util; import com.vaadin.annotations.Theme; import com.vaadin.annotations.Title; import com.vaadin.annotations.VaadinServletConfiguration; import com.vaadin.data.Binder; import com.vaadin.data.HasValue.ValueChangeEvent; import com.vaadin.data.HasValue.ValueChangeListener; import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinServlet; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.MouseEventDetails.MouseButton; import com.vaadin.shared.Registration; import com.vaadin.shared.ui.datefield.DateTimeResolution; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.CheckBox; import com.vaadin.ui.ColorPicker; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Component; import com.vaadin.ui.DateTimeField; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.ItemCaptionGenerator; import com.vaadin.ui.MenuBar; import com.vaadin.ui.MenuBar.Command; import com.vaadin.ui.MenuBar.MenuItem; import com.vaadin.ui.NativeSelect; import com.vaadin.ui.Notification; import com.vaadin.ui.Notification.Type; import com.vaadin.ui.Panel; import com.vaadin.ui.Slider; import com.vaadin.ui.TextField; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; @Theme("demo") @Title("Gantt Add-on Demo") @SuppressWarnings("serial") public class DemoUI extends UI { @WebServlet(value = "/*", asyncSupported = true) @VaadinServletConfiguration(productionMode = false, ui = DemoUI.class, widgetset = "org.tltv.gantt.demo.DemoWidgetSet") public static class Servlet extends VaadinServlet { } private TimeZone defaultTimeZone; private Gantt gantt; private NativeSelect<Locale> localeSelect; private NativeSelect<Resolution> reso; private DateTimeField start; private DateTimeField end; private SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd HH:mm:ss zzz yyyy"); private HorizontalLayout controls; private HorizontalLayout subControls; private GanttListener ganttListener; private AttachListener ganttAttachListener = new AttachListener() { @Override public void attach(AttachEvent event) { syncLocale(); } }; private ClickListener createStepClickListener = new ClickListener() { @Override public void buttonClick(ClickEvent event) { Step newStep = new Step(); Date now = new Date(); newStep.setStartDate(now.getTime()); newStep.setEndDate(now.getTime() + (7 * 24 * 3600000)); openStepEditor(newStep); } }; private Optional<Registration> startDateValueChangeRegistration; private ValueChangeListener<LocalDateTime> startDateValueChangeListener = new ValueChangeListener<LocalDateTime>() { @Override public void valueChange(ValueChangeEvent<LocalDateTime> event) { gantt.setStartDate(event.getValue()); } }; private Optional<Registration> endDateValueChangeRegistration; private ValueChangeListener<LocalDateTime> endDateValueChangeListener = new ValueChangeListener<LocalDateTime>() { @Override public void valueChange(ValueChangeEvent<LocalDateTime> event) { gantt.setEndDate(event.getValue()); } }; private Optional<Registration> resolutionValueChangeRegistration; private ValueChangeListener<org.tltv.gantt.client.shared.Resolution> resolutionValueChangeListener = new ValueChangeListener<org.tltv.gantt.client.shared.Resolution>() { @Override public void valueChange(ValueChangeEvent<org.tltv.gantt.client.shared.Resolution> event) { if (validateResolutionChange(event.getValue())) { gantt.setResolution(event.getValue()); } } }; private ValueChangeListener<Locale> localeValueChangeListener = new ValueChangeListener<Locale>() { @Override public void valueChange(ValueChangeEvent<Locale> event) { gantt.setLocale(event.getValue()); syncLocale(); } }; private ValueChangeListener<String> timezoneValueChangeListener = new ValueChangeListener<String>() { @Override public void valueChange(ValueChangeEvent<String> event) { String tzId = event.getValue(); if ("Default".equals(tzId)) { gantt.setTimeZone(getDefaultTimeZone()); } else { gantt.setTimeZone(TimeZone.getTimeZone(tzId)); } syncLocale(); } }; @Override protected void init(VaadinRequest request) { ganttListener = null; createGantt(); MenuBar menu = controlsMenuBar(); Panel controls = createControls(); Component wrapper = UriFragmentWrapperFactory.wrapByUriFragment(UI.getCurrent().getPage().getUriFragment(), gantt); if (wrapper instanceof GanttListener) { ganttListener = (GanttListener) wrapper; } final VerticalLayout layout = new VerticalLayout(); layout.setStyleName("demoContentLayout"); layout.setMargin(false); layout.setSizeFull(); layout.addComponent(menu); layout.addComponent(controls); layout.addComponent(wrapper); layout.setExpandRatio(wrapper, 1); setContent(layout); } private void createGantt() { gantt = new Gantt(); gantt.setWidth(100, Unit.PERCENTAGE); gantt.setHeight(500, Unit.PIXELS); gantt.setResizableSteps(true); gantt.setMovableSteps(true); gantt.addAttachListener(ganttAttachListener); gantt.setTimeZone(getDefaultTimeZone()); Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); gantt.setStartDate(cal.getTime()); cal.add(Calendar.YEAR, 1); gantt.setEndDate(cal.getTime()); cal.setTime(new Date()); Step step1 = new Step("First step"); step1.setDescription("Description tooltip"); step1.setShowProgress(true); step1.setProgress(50.0); step1.setStartDate(cal.getTime().getTime()); cal.add(Calendar.MONTH, 2); step1.setEndDate(cal.getTime().getTime()); Step step2 = new Step("Second step"); step2.setDescription("Description tooltip for second step"); step2.setShowProgress(true); step2.setProgress(15.0); cal.add(Calendar.DATE, 1); step2.setStartDate(cal.getTime().getTime()); cal.add(Calendar.MONTH, 4); step2.setEndDate(cal.getTime().getTime()); step2.setPredecessor(step1); Step step3 = new Step("Third step"); step3.setDescription("<b>HTML</b> <i>content</i> is <u>supported</u> in tooltips."); cal.add(Calendar.DATE, 1); step3.setStartDate(cal.getTime().getTime()); cal.add(Calendar.MONTH, 12); step3.setEndDate(cal.getTime().getTime()); step3.setPredecessor(step2); Step step4 = new Step("Fourth step"); step4.setDescription("Tooltip is <b>VTooltip</b>. <p>Looks same for all Vaadin components."); step4.setStartDate(step2.getStartDate()); step4.setEndDate(step2.getEndDate()); step4.setPredecessor(step1); Step stepWithSubSteps = new Step("Step with sub-steps"); stepWithSubSteps.setDescription("Tooltip for Step with sub-steps"); cal.setTime(new Date(step1.getStartDate())); cal.add(Calendar.DATE, 7); SubStep subStep1 = new SubStep("Sub-step A"); subStep1.setDescription("Tooltip for Sub-step A"); subStep1.setBackgroundColor("A8D9DD"); subStep1.setStartDate(step1.getStartDate()); subStep1.setEndDate(cal.getTime()); SubStep subStep2 = new SubStep("Sub-step B"); subStep2.setDescription("Tooltip for Sub-step B"); subStep2.setBackgroundColor("A8D9BB"); subStep2.setStartDate(cal.getTime()); cal.add(Calendar.MONTH, 1); subStep2.setEndDate(cal.getTime()); SubStep subStep3 = new SubStep("Sub-step C"); subStep3.setDescription("Tooltip for Sub-step C"); subStep3.setBackgroundColor("A8D999"); subStep3.setStartDate(cal.getTime()); cal.add(Calendar.MONTH, 1); subStep3.setEndDate(step1.getEndDate()); stepWithSubSteps.addSubStep(subStep1); stepWithSubSteps.addSubStep(subStep2); stepWithSubSteps.addSubStep(subStep3); gantt.addStep(step1); gantt.addStep(step2); gantt.addStep(step3); gantt.addStep(step4); gantt.addStep(stepWithSubSteps); String[] colors = new String[] { "11FF11", "33FF33", "55FF55", "77FF77", "99FF99", "BBFFBB", "DDFFDD" }; cal.setTime(new Date()); for (int i = 0; i < 10; i++) { Step step = new Step("Step " + i); step.setStartDate(cal.getTime().getTime()); cal.add(Calendar.DATE, 14); step.setEndDate(cal.getTime().getTime()); step.setBackgroundColor(colors[i % colors.length]); gantt.addStep(step); } gantt.addClickListener(new Gantt.ClickListener() { @Override public void onGanttClick(org.tltv.gantt.Gantt.ClickEvent event) { if (event.getDetails().isDoubleClick()) { Notification.show(String.format("Double Click on Step %s", event.getStep().getCaption()), Type.TRAY_NOTIFICATION); } if (MouseButton.RIGHT.equals(event.getDetails().getButton())) { Notification.show(String.format("Right Click on Step %s", event.getStep().getCaption()), Type.TRAY_NOTIFICATION); } else { openStepEditor(event.getStep()); } } }); gantt.addMoveListener(new Gantt.MoveListener() { @Override public void onGanttMove(MoveEvent event) { Date start = new Date(event.getStartDate()); Date end = new Date(event.getEndDate()); dateFormat.setTimeZone(gantt.getTimeZone()); String message = "Moved " + event.getStep().getCaption() + " to Start Date: " + dateFormat.format(start) + " End Date: " + dateFormat.format(end); if (gantt.isMovableStepsBetweenRows() && event.getStepIndex() != event.getPreviousStepIndex()) { message += " New Step index: " + event.getStepIndex(); if (ganttListener != null && event.getStep() instanceof Step) { ganttListener.stepMoved((Step) event.getStep(), event.getStepIndex(), event.getPreviousStepIndex()); } } showNotificationWithMousedetails(message, event.getDetails()); } }); gantt.addResizeListener(new Gantt.ResizeListener() { @Override public void onGanttResize(ResizeEvent event) { Date start = new Date(event.getStartDate()); Date end = new Date(event.getEndDate()); dateFormat.setTimeZone(gantt.getTimeZone()); showNotificationWithMousedetails("Resized " + event.getStep().getCaption() + " to Start Date: " + dateFormat.format(start) + " End Date: " + dateFormat.format(end), event.getDetails()); } }); } private void showNotificationWithMousedetails(String msg, MouseEventDetails details) { String detailsTxt = ""; if (details.isCtrlKey()) { detailsTxt = "(Ctrl down) "; } Notification.show(detailsTxt + msg, Type.TRAY_NOTIFICATION); } private void syncLocale() { startDateValueChangeRegistration.ifPresent(Registration::remove); endDateValueChangeRegistration.ifPresent(Registration::remove); try { start.setLocale(gantt.getLocale()); start.setValue(gantt.getStartLocalDateTime()); end.setLocale(gantt.getLocale()); end.setValue(gantt.getEndLocalDateTime()); } finally { startDateValueChangeRegistration = Optional.of(start.addValueChangeListener(startDateValueChangeListener)); endDateValueChangeRegistration = Optional.of(end.addValueChangeListener(endDateValueChangeListener)); } dateFormat = new SimpleDateFormat("MMM dd HH:mm:ss zzz yyyy", gantt.getLocale()); } private Panel createControls() { Panel panel = new Panel(); panel.setWidth(100, Unit.PERCENTAGE); controls = new HorizontalLayout(); controls.setSpacing(true); controls.setMargin(true); panel.setContent(controls); subControls = new HorizontalLayout(); subControls.setSpacing(true); subControls.setVisible(false); start = createStartDateField(); end = createEndDateField(); Button createStep = new Button("Create New Step...", createStepClickListener); HorizontalLayout heightAndUnit = new HorizontalLayout(Util.createHeightEditor(gantt), Util.createHeightUnitEditor(gantt)); HorizontalLayout widthAndUnit = new HorizontalLayout(Util.createWidthEditor(gantt), Util.createWidthUnitEditor(gantt)); reso = new NativeSelect<Resolution>("Resolution"); reso.setEmptySelectionAllowed(false); reso.setItems(org.tltv.gantt.client.shared.Resolution.Hour, org.tltv.gantt.client.shared.Resolution.Day, org.tltv.gantt.client.shared.Resolution.Week); reso.setValue(gantt.getResolution()); resolutionValueChangeRegistration = Optional.of(reso.addValueChangeListener(resolutionValueChangeListener)); localeSelect = new NativeSelect<Locale>("Locale") { @Override public void attach() { super.attach(); if (getValue() == null) { // use default locale setValue(gantt.getLocale()); addValueChangeListener(localeValueChangeListener); } } }; localeSelect.setEmptySelectionAllowed(false); localeSelect.setItems(Locale.getAvailableLocales()); localeSelect.setItemCaptionGenerator((l) -> l.getDisplayName(getLocale())); ComboBox<String> timezoneSelect = new ComboBox<String>("Timezone"); timezoneSelect.setWidth(300, Unit.PIXELS); timezoneSelect.setEmptySelectionAllowed(false); timezoneSelect.setItemCaptionGenerator(new ItemCaptionGenerator<String>() { @Override public String apply(String item) { if ("Default".equals(item)) { return "Default (" + getDefaultTimeZone().getDisplayName() + ")"; } TimeZone tz = TimeZone.getTimeZone(item); return tz.getID() + " (raw offset " + (tz.getRawOffset() / 60000) + "m)"; } }); List<String> items = new ArrayList<>(); items.add("Default"); items.addAll(Gantt.getSupportedTimeZoneIDs()); timezoneSelect.setItems((caption, fltr) -> caption.contains(fltr), items); timezoneSelect.setValue("Default"); timezoneSelect.addValueChangeListener(timezoneValueChangeListener); final Button toggleSubControlsBtn = new Button("Show More Settings..."); toggleSubControlsBtn.addStyleName("link"); toggleSubControlsBtn.addClickListener(new ClickListener() { @Override public void buttonClick(ClickEvent event) { subControls.setVisible(!subControls.isVisible()); toggleSubControlsBtn.setCaption(subControls.isVisible() ? "Less Settings..." : "More Settings..."); } }); controls.addComponent(start); controls.addComponent(end); controls.addComponent(reso); controls.addComponent(subControls); controls.addComponent(toggleSubControlsBtn); controls.setComponentAlignment(toggleSubControlsBtn, Alignment.BOTTOM_CENTER); subControls.addComponent(localeSelect); subControls.addComponent(timezoneSelect); subControls.addComponent(heightAndUnit); subControls.addComponent(widthAndUnit); subControls.addComponent(createStep); subControls.setComponentAlignment(createStep, Alignment.MIDDLE_LEFT); return panel; } private DateTimeField createStartDateField() { DateTimeField f = new DateTimeField("Start date"); f.setResolution(DateTimeResolution.SECOND); startDateValueChangeRegistration = Optional.of(f.addValueChangeListener(startDateValueChangeListener)); return f; } private DateTimeField createEndDateField() { DateTimeField f = new DateTimeField("End date"); f.setResolution(DateTimeResolution.SECOND); endDateValueChangeRegistration = Optional.of(f.addValueChangeListener(endDateValueChangeListener)); return f; } private boolean validateResolutionChange(final org.tltv.gantt.client.shared.Resolution res) { long max = 5 * 12 * 4 * 7 * 24 * 3600000L; if (res == org.tltv.gantt.client.shared.Resolution.Hour && (gantt.getEndDate().getTime() - gantt.getStartDate().getTime()) > max) { // revert to previous resolution setResolution(gantt.getResolution()); // make user to confirm hour resolution, if the timeline range is // very long. Util.showConfirmationPopup( "Timeline range is a quite long for hour resolution. Rendering may be slow. Continue anyway?", new Runnable() { @Override public void run() { setResolution(res); gantt.setResolution(res); } }); return false; } return true; } private void setResolution(org.tltv.gantt.client.shared.Resolution resolution) { resolutionValueChangeRegistration.ifPresent(Registration::remove); try { reso.setValue(resolution); } finally { resolutionValueChangeRegistration = Optional.of(reso.addValueChangeListener(resolutionValueChangeListener)); } } private MenuBar controlsMenuBar() { MenuBar menu = new MenuBar(); MenuItem editItem = menu.addItem("Edit", null); MenuItem formatItem = menu.addItem("Format", null); MenuItem viewItem = menu.addItem("View", null); MenuItem item = editItem.addItem("Enabled", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setEnabled(!gantt.isEnabled()); selectedItem.setChecked(gantt.isEnabled()); } }); item.setCheckable(true); item.setChecked(gantt.isEnabled()); item = editItem.addItem("Read-only", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setReadOnly(!gantt.isReadOnly()); selectedItem.setChecked(gantt.isReadOnly()); } }); item.setCheckable(true); item.setChecked(gantt.isReadOnly()); editItem.addSeparator(); item = editItem.addItem("Movable Steps", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setMovableSteps(!gantt.isMovable()); selectedItem.setChecked(gantt.isMovable()); } }); item.setCheckable(true); item.setChecked(gantt.isMovable()); item = editItem.addItem("Movable Steps between rows", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setMovableStepsBetweenRows(!gantt.isMovableStepsBetweenRows()); selectedItem.setChecked(gantt.isMovableStepsBetweenRows()); } }); item.setCheckable(true); item.setChecked(gantt.isMovableStepsBetweenRows()); item = editItem.addItem("Resizable Steps", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setResizableSteps(!gantt.isResizableSteps()); selectedItem.setChecked(gantt.isResizableSteps()); } }); item.setCheckable(true); item.setChecked(gantt.isResizableSteps()); item = editItem.addItem("Disable Default Context Menu", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setDefaultContextMenuEnabled(!gantt.isDefaultContextMenuEnabled()); selectedItem.setChecked(!gantt.isDefaultContextMenuEnabled()); } }); item.setCheckable(true); item.setChecked(!gantt.isDefaultContextMenuEnabled()); editItem.addSeparator(); item = editItem.addItem("Create New Step...", new Command() { @Override public void menuSelected(MenuItem selectedItem) { createStepClickListener.buttonClick(null); } }); item = formatItem.addItem("Set 'MMM' month format", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineMonthFormat("MMM"); } }); item = formatItem.addItem("Set 'MMMM' month format", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineMonthFormat("MMMM"); } }); item = formatItem.addItem("Set 'yyyy MMMM' month format", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineMonthFormat("yyyy MMMM"); } }); item = formatItem.addItem("Set 'dd.' week format", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineWeekFormat("dd."); } }); item = formatItem.addItem("Set week number week format", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineWeekFormat(null); } }); item = formatItem.addItem("Set 'dd. EEEE' day format for Hour resolution", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineDayFormat("dd. EEEE"); } }); item = formatItem.addItem("Set 'k' hour format for Hour resolution", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setTimelineHourFormat("k"); } }); item = viewItem.addItem("Show Control Panel", new Command() { @Override public void menuSelected(MenuItem selectedItem) { controls.setVisible(!controls.isVisible()); selectedItem.setChecked(controls.isVisible()); } }); item.setCheckable(true); item.setChecked(true); viewItem.addSeparator(); item = viewItem.addItem("Show years", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setYearsVisible(!gantt.isYearsVisible()); selectedItem.setChecked(gantt.isYearsVisible()); } }); item.setCheckable(true); item.setChecked(gantt.isYearsVisible()); item = viewItem.addItem("Show months", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setMonthsVisible(!gantt.isMonthsVisible()); selectedItem.setChecked(gantt.isMonthsVisible()); } }); item.setCheckable(true); item.setChecked(gantt.isMonthsVisible()); item = viewItem.addItem("Show current time pointer", new Command() { @Override public void menuSelected(MenuItem selectedItem) { gantt.setShowCurrentTime(!gantt.isShowCurrentTime()); selectedItem.setChecked(gantt.isShowCurrentTime()); } }); item.setCheckable(true); item.setChecked(gantt.isShowCurrentTime()); item = viewItem.addItem("Show Gantt with Grid", new Command() { @Override public void menuSelected(MenuItem selectedItem) { getPage().setLocation("#grid"); getPage().reload(); } }); item = viewItem.addItem("Show Gantt with TreeGrid", new Command() { @Override public void menuSelected(MenuItem selectedItem) { getPage().setLocation("#treegrid"); getPage().reload(); } }); item = viewItem.addItem("Show Gantt alone", new Command() { @Override public void menuSelected(MenuItem selectedItem) { getPage().setLocation("#"); getPage().reload(); } }); return menu; } private <T extends AbstractStep> void openStepEditor(T step) { final Window win = new Window("Step Editor"); win.setResizable(false); win.center(); final Collection<Component> hidden = new ArrayList<Component>(); Binder<T> binder = new Binder<T>((Class<T>) step.getClass()); binder.setBean(step); TextField captionField = new TextField("Caption"); binder.bind(captionField, "caption"); TextField descriptionField = new TextField("Description"); binder.bind(descriptionField, "description"); descriptionField.setVisible(false); hidden.add(descriptionField); TextField styleField = new TextField("Style name"); binder.bind(styleField, "styleName"); styleField.setVisible(false); hidden.add(styleField); NativeSelect<Step.CaptionMode> captionMode = new NativeSelect<Step.CaptionMode>("Caption Mode"); captionMode.setItems(Step.CaptionMode.TEXT, Step.CaptionMode.HTML); binder.bind(captionMode, "captionMode"); captionMode.setVisible(false); hidden.add(captionMode); CheckBox resizable = new CheckBox("Resizable"); binder.bind(resizable, "resizable"); resizable.setVisible(false); hidden.add(resizable); CheckBox showProgress = new CheckBox("Show progress"); binder.bind(showProgress, "showProgress"); showProgress.setVisible(false); hidden.add(showProgress); Slider progress = new Slider("Progress"); progress.setWidth(100, Unit.PERCENTAGE); binder.bind(progress, "progress"); progress.setVisible(false); hidden.add(progress); NativeSelect<AbstractStep> predecessorSelect = new NativeSelect<AbstractStep>("Predecessor Step"); predecessorSelect.setWidth(100, Unit.PERCENTAGE); predecessorSelect.setItemCaptionGenerator(i -> i.getCaption()); fillPredecessorCanditatesToSelect(step, predecessorSelect); predecessorSelect.setEnabled(step instanceof Step); if (step instanceof Step) { binder.bind(predecessorSelect, "predecessor"); } predecessorSelect.setVisible(false); hidden.add(predecessorSelect); final NativeSelect<Step> parentStepSelect = new NativeSelect<Step>("Parent Step"); parentStepSelect.setWidth(100, Unit.PERCENTAGE); parentStepSelect.setItemCaptionGenerator(i -> i.getCaption()); parentStepSelect.setEnabled(false); fillParentStepCanditatesToSelect(step, parentStepSelect); parentStepSelect.setVisible(false); hidden.add(parentStepSelect); HorizontalLayout colorLayout = new HorizontalLayout(); colorLayout.setWidth(100, Unit.PERCENTAGE); colorLayout.setVisible(false); hidden.add(colorLayout); final TextField bgField = new TextField("Background color"); binder.bind(bgField, "backgroundColor"); bgField.setEnabled(false); final ColorPicker bgColorPicker = new ColorPicker(); bgColorPicker.setPosition(300, 100); bgColorPicker.setValue(new CssColorToColorPickerConverter().convertToModel(step.getBackgroundColor())); bgColorPicker.addValueChangeListener(e -> bgField.setValue(e.getValue().getCSS())); colorLayout.addComponent(bgField); colorLayout.addComponent(bgColorPicker); colorLayout.setExpandRatio(bgField, 1); colorLayout.setComponentAlignment(bgColorPicker, Alignment.BOTTOM_LEFT); DateTimeField startDate = new DateTimeField("Start date"); startDate.setLocale(gantt.getLocale()); startDate.setResolution(DateTimeResolution.SECOND); binder.bind(startDate, (s) -> GanttTimeUtil.getStartLocalDateTime(s), (s, v) -> GanttTimeUtil.setStartDate(s, v)); DateTimeField endDate = new DateTimeField("End date"); endDate.setLocale(gantt.getLocale()); endDate.setResolution(DateTimeResolution.SECOND); binder.bind(endDate, (s) -> GanttTimeUtil.getEndLocalDateTime(s), (s, v) -> GanttTimeUtil.setEndDate(s, v)); CheckBox showMore = new CheckBox("Show all settings"); showMore.addValueChangeListener(new ValueChangeListener<Boolean>() { @Override public void valueChange(ValueChangeEvent<Boolean> event) { for (Component c : hidden) { c.setVisible(event.getValue()); } win.center(); } }); VerticalLayout content = new VerticalLayout(); content.setMargin(true); content.setSpacing(true); win.setContent(content); content.addComponent(captionField); content.addComponent(captionMode); content.addComponent(descriptionField); content.addComponent(styleField); content.addComponent(resizable); content.addComponent(showProgress); content.addComponent(progress); content.addComponent(predecessorSelect); content.addComponent(parentStepSelect); content.addComponent(colorLayout); content.addComponent(startDate); content.addComponent(endDate); content.addComponent(showMore); HorizontalLayout buttons = new HorizontalLayout(); content.addComponent(buttons); Button ok = new Button("Ok", new ClickListener() { @Override public void buttonClick(ClickEvent event) { commit(win, binder, parentStepSelect); } }); Button cancel = new Button("Cancel", new ClickListener() { @Override public void buttonClick(ClickEvent event) { cancel(win, binder); } }); Button delete = new Button("Delete", new ClickListener() { @Override public void buttonClick(ClickEvent event) { delete(win, binder); } }); buttons.addComponent(ok); buttons.addComponent(cancel); buttons.addComponent(delete); win.setClosable(true); getUI().addWindow(win); } private void fillPredecessorCanditatesToSelect(AbstractStep step, final NativeSelect<AbstractStep> predecessorSelect) { List<AbstractStep> items = new ArrayList<>(); for (Step stepCanditate : gantt.getSteps()) { if (!stepCanditate.equals(step) && stepCanditate instanceof Step) { items.add(stepCanditate); } } predecessorSelect.setItems(items); } private void fillParentStepCanditatesToSelect(AbstractStep step, final NativeSelect<Step> parentStepSelect) { if (!gantt.getSteps().contains(step)) { // new step parentStepSelect.setEnabled(true); List<Step> items = new ArrayList<>(); for (Step parentStepCanditate : gantt.getSteps()) { items.add(parentStepCanditate); if (step instanceof SubStep) { if (parentStepCanditate.getSubSteps().contains(step)) { parentStepSelect.setValue(parentStepCanditate); parentStepSelect.setEnabled(false); break; } } } parentStepSelect.setItems(items); } } private void commit(final Window win, final Binder<? extends AbstractStep> binder, final NativeSelect<Step> parentStepSelect) { AbstractStep step = binder.getBean(); gantt.markStepDirty(step); if (parentStepSelect.isEnabled() && parentStepSelect.getValue() != null) { SubStep subStep = addSubStep(parentStepSelect, step); step = subStep; } if (step instanceof Step && !gantt.getSteps().contains(step)) { gantt.addStep((Step) step); } if (ganttListener != null && step instanceof Step) { ganttListener.stepModified((Step) step); } win.close(); } private void cancel(final Window win, final Binder<? extends AbstractStep> binder) { win.close(); } private void delete(final Window win, final Binder<? extends AbstractStep> binder) { AbstractStep step = binder.getBean(); if (step instanceof SubStep) { SubStep substep = (SubStep) step; substep.getOwner().removeSubStep(substep); } else { gantt.removeStep((Step) step); if (ganttListener != null) { ganttListener.stepDeleted((Step) step); } } win.close(); } private SubStep addSubStep(final NativeSelect parentStepSelect, AbstractStep dataSource) { SubStep subStep = new SubStep(); subStep.setCaption(dataSource.getCaption()); subStep.setCaptionMode(dataSource.getCaptionMode()); subStep.setStartDate(dataSource.getStartDate()); subStep.setEndDate(dataSource.getEndDate()); subStep.setBackgroundColor(dataSource.getBackgroundColor()); subStep.setDescription(dataSource.getDescription()); subStep.setProgress(dataSource.getProgress()); subStep.setShowProgress(dataSource.isShowProgress()); subStep.setStyleName(dataSource.getStyleName()); ((Step) parentStepSelect.getValue()).addSubStep(subStep); return subStep; } private TimeZone getDefaultTimeZone() { if (defaultTimeZone != null) { return defaultTimeZone; } TimeZone tz = TimeZone.getDefault(); if (Gantt.getSupportedTimeZoneIDs().contains(tz.getID())) { defaultTimeZone = tz; } else { defaultTimeZone = TimeZone.getTimeZone("Europe/Helsinki"); } return defaultTimeZone; } }