com.appnativa.studio.RMLDocument.java Source code

Java tutorial

Introduction

Here is the source code for com.appnativa.studio.RMLDocument.java

Source

/*
 * @(#)SDFDocument.java
 *
 * Copyright (c) appNativa. All rights reserved.
 *
 * Use is subject to license terms.
 */

package com.appnativa.studio;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Arrays;
import java.util.EventObject;
import java.util.List;

import javax.swing.SwingUtilities;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.UndoableEdit;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.properties.IPropertySource;

import com.appnativa.rare.Platform;
import com.appnativa.rare.TemplateHandler;
import com.appnativa.rare.iPlatformAppContext;
import com.appnativa.rare.net.ActionLink;
import com.appnativa.rare.platform.swing.ui.view.UtilityPanel;
import com.appnativa.rare.spot.Font;
import com.appnativa.rare.spot.GridCell;
import com.appnativa.rare.spot.GridPane;
import com.appnativa.rare.spot.GroupBox;
import com.appnativa.rare.spot.MainWindow;
import com.appnativa.rare.spot.MenuBar;
import com.appnativa.rare.spot.Navigator;
import com.appnativa.rare.spot.SplitPane;
import com.appnativa.rare.spot.TabPane;
import com.appnativa.rare.spot.Table;
import com.appnativa.rare.spot.TemplateContext;
import com.appnativa.rare.spot.Widget;
import com.appnativa.rare.ui.ColorUtils;
import com.appnativa.rare.ui.UIColor;
import com.appnativa.rare.ui.UIDimension;
import com.appnativa.rare.ui.UIFontHelper;
import com.appnativa.rare.ui.event.iChangeListener;
import com.appnativa.rare.ui.painter.iBackgroundPainter;
import com.appnativa.rare.ui.painter.iPlatformPainter;
import com.appnativa.rare.util.JavaHandler;
import com.appnativa.rare.viewer.SplitPaneViewer;
import com.appnativa.rare.viewer.WidgetPaneViewer;
import com.appnativa.rare.viewer.WindowViewer;
import com.appnativa.rare.viewer.iContainer;
import com.appnativa.rare.viewer.iViewer;
import com.appnativa.rare.widget.iWidget;
import com.appnativa.spot.SDFNode;
import com.appnativa.spot.SPOTAny;
import com.appnativa.spot.SPOTSequence;
import com.appnativa.spot.SPOTSet;
import com.appnativa.spot.iSPOTElement;
import com.appnativa.studio.dialogs.SequenceArrayEditor;
import com.appnativa.studio.dialogs.SplitPaneEditor;
import com.appnativa.studio.editors.MultiPageEditor;
import com.appnativa.studio.editors.RMLEditor;
import com.appnativa.studio.properties.EditorHelper;
import com.appnativa.studio.properties.SPOTInspector;
import com.appnativa.studio.properties.SequenceProperty;
import com.appnativa.studio.properties.WidgetProperty;
import com.appnativa.studio.views.PropertiesView;
import com.appnativa.studio.views.ToolboxView.Tool;
import com.appnativa.util.MutableInteger;

public class RMLDocument implements iDesignListener, UndoableEditListener, IDocumentListener, iChangeListener {
    private static StructuredSelection emptySelection = new StructuredSelection();
    private static WidgetAdaptable[] emptyWSelection = new WidgetAdaptable[0];
    public boolean badCfg;
    public iSPOTElement cfg;
    public DesignPane designPane;
    public RMLEditor editor;
    public IFile file;
    ListenerList listenerList = new ListenerList();
    Project project;
    Tool selectedTool;
    private boolean allowScrolling;
    private boolean fitToPane;
    private boolean ignoreProjetChangeEvents;
    private WidgetPaneViewer paneParentViewer;
    private int projectModCount;
    private final IUndoContext undoContext;
    List<Widget> oldSelections;

    public RMLDocument(RMLEditor editor, IUndoContext undoContext) {
        this.editor = editor;
        this.undoContext = undoContext;
        editor.getInputDocument().addDocumentListener(this);

        try {
            if (editor.getEditorInput() instanceof IFileEditorInput) {
                file = ((IFileEditorInput) editor.getEditorInput()).getFile();
            }
        } catch (Exception ignore) {
        }
    }

    public void addSelectionChangedListener(iSelectionListener listener) {
        listenerList.add(listener);
    }

    public iSPOTElement createConfiguration(iViewer v) throws Exception {
        if (this.cfg == null) {
            this.cfg = createConfigurationEx(v);
        }

        return this.cfg;
    }

    public iSPOTElement createConfigurationEx(iViewer v) throws Exception {
        Project project = getProject();
        WindowViewer w = v.getAppContext().getWindowViewer();
        IDocument doc = editor.getInputDocument();
        URL turl = getURL();
        URL url;

        TemplateHandler.setInstance(Platform.getAppContext(),
                (project == null) ? null : project.getTemplateHandler());

        if ((designPane == null) || (cfg == null)) {
            url = w.createInlineURL(doc.get(), "text/x-sdf");
        } else {
            url = w.createInlineURL(cfg.toString(), "text/x-sdf");
        }

        ActionLink l = w.createActionLink(url);

        if (turl != null) {
            v.setContextURL(turl);
        } else {
            if (project != null) {
                v.setContextURL(project.baseURL);
            }
        }

        l.setContext(v);

        iSPOTElement cfg = w.createConfigurationObject(l);

        if (cfg instanceof com.appnativa.rare.spot.Application) {
            cfg = new Application((com.appnativa.rare.spot.Application) cfg);
            ((Application) cfg).contextURL.setValue(URLHelper.toString(turl));
        }

        TemplateHandler.setInstance(Platform.getAppContext(), null);

        if (project != null) {
            projectModCount = project.getModCount();
        }

        cfg.spot_setLinkedData(v.getContextURL());

        return cfg;
    }

    public com.appnativa.rare.spot.Application createPreviewApplication() throws Exception {
        iSPOTElement cfg = createConfigurationEx(Platform.getContextRootViewer());
        com.appnativa.rare.spot.Application a;
        Project project = getProject();

        if ((project != null) && (project.application == null)) {
            project = null;
        }

        if (cfg instanceof com.appnativa.studio.Application) {
            a = (com.appnativa.rare.spot.Application) ((Application) cfg).application.clone();
        } else if (project != null) {
            a = (com.appnativa.rare.spot.Application) project.application.clone();
        } else {
            a = new com.appnativa.rare.spot.Application();
        }

        a.managedScreenSizes.spot_clear();

        boolean isapp = (cfg instanceof com.appnativa.studio.Application);

        if (cfg instanceof MainWindow) {
            a.setMainWindow((MainWindow) cfg);
        } else {
            MainWindow mw = a.getMainWindow();

            if ((mw == null) || (!isapp)) {
                mw = (project == null) ? new MainWindow() : project.getPreviewMainWindow(!isapp);
                a.setMainWindow(mw);
            }

            if (!isapp) {
                mw.viewer.setValue(cfg);
            }
        }

        a.contextURL.spot_clear();

        return a;
    }

    public iContainer createWidget(WindowViewer win, iViewer v) throws Exception {
        iSPOTElement cfg = createConfiguration(v);
        iWidget w;
        Project p = getProject();

        if (cfg instanceof Application) {
            com.appnativa.rare.spot.Application aa = (com.appnativa.rare.spot.Application) ((Application) cfg).application;
            URL u = null;
            MainWindow wm = aa.getMainWindow();
            ActionLink link = null;

            if (p != null) {
                if (wm == null) {
                    wm = p.getMainWindow();
                    link = p.getMainWindowActionLink();
                }

                if (wm == null) {
                    wm = p.application.getMainWindowReference();
                }

                u = p.getBaseURL();
            } else {
                aa = ((Application) cfg).application;
                wm = aa.getMainWindowReference();

                if (aa.contextURL.spot_hasValue()) {
                    u = v.getURL(aa.contextURL.getValue());
                }
            }

            if (p != null) {
                p.setTemplateHandler();
            }

            w = DesignWindowManager.createApplicationWindowViewer(win.getAppContext(), wm, u);

            if (p != null) {
                p.clearTemplateHandler();
            }

            if (link != null) {
                ((iViewer) w).setViewerActionLink(link);
            }
        } else if (cfg instanceof MainWindow) {
            URL u = null;
            MainWindow wm = (MainWindow) cfg;

            if ((p != null) && (p.application != cfg)) {
                u = p.getBaseURL();
            }

            if (p != null) {
                p.setTemplateHandler();
            }

            w = DesignWindowManager.createApplicationWindowViewer(win.getAppContext(), wm, u);

            if (p != null) {
                p.clearTemplateHandler();
            }
        } else {
            if (p != null) {
                p.setTemplateHandler();
            }

            w = win.createWidget(v, (Widget) cfg);

            if (p != null) {
                p.clearTemplateHandler();
                p.adjustBoundsToWindow(w, (Widget) cfg);
            }
        }

        w.setVisible(true);

        iContainer c;

        if (w instanceof iContainer) {
            c = (iContainer) w;
        } else {
            c = new DesignContainer(w);
        }

        return c;
    }

    public void dispose() {
        if (project != null) {
            project.removeChangeListener(this);
        }

        project = null;
        file = null;
        editor = null;
    }

    @Override
    public void documentAboutToBeChanged(DocumentEvent e) {
    }

    @Override
    public void documentChanged(DocumentEvent e) {
        this.cfg = null;
    }

    public void documentFocused() {
        if (designPane != null) {
            Project p = getProject();

            if ((p != null) && (projectModCount != p.getModCount())) {
                projectModCount = p.getModCount();
                cfg = null;
                reloadDesign(null);
            } else {
                designPane.requestRepaint();
            }
        }
    }

    public void editWithDialog(final Widget wc, final iWidget w) {
        Studio.runInSWTThread(new Runnable() {
            @Override
            public void run() {
                editWithDialogEx(wc, w);
            }
        });
    }

    public void editorSaved(RMLEditor editor) {
        if (designPane != null) {
            designPane.clean();
        }

        Project p = getProjectEx();

        if (p == null) {
            return;
        }

        boolean reload = false;

        if (cfg == null) {
            reload = p.isReloadRequired(editor.getEditorInput());
        } else {
            reload = (cfg instanceof Application) || (cfg instanceof MainWindow)
                    || (cfg instanceof TemplateContext);
        }

        if (reload) {
            ignoreProjetChangeEvents = true;

            try {
                p.setDirty(true);
            } catch (Exception e) {
                Studio.showError(e, false);
            }

            ignoreProjetChangeEvents = false;
        }
    }

    public void endPreview(iPlatformAppContext app) {
        Project p = getProject();

        if (p != null) {
            p.resetAfterPreview();
        }
    }

    public void formatSource() {
        WindowViewer w = Platform.getWindowViewer();

        if (w != null) {
            iSPOTElement e = cfg;

            cfg = null;

            try {
                createConfiguration(w);
                updateSource(true);
            } catch (Exception ex) {
                cfg = e;
                Studio.showError(ex, false);
            }
        }
    }

    public void globalPreferencesChanged() {
        projectChanged();
    }

    public void handleToolDoubleClicked() {
        if (selectedTool != null) {
            final Widget cfg = (Widget) ((Widget) Studio.getAttribute(selectedTool.id)).clone();
            Runnable r = new Runnable() {
                @Override
                public void run() {
                    try {
                        designPane.handleDrop(null, cfg, null);
                    } finally {
                        Display.getDefault().asyncExec(new Runnable() {
                            @Override
                            public void run() {
                                resetCursors();
                            }
                        });
                    }
                }
            };

            Studio.runInSwingThread(r);
        }
    }

    public void reloadDesign(final Widget selectConfig) {
        if (SwingUtilities.isEventDispatchThread()) {
            reloadDesignEx(selectConfig);
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    reloadDesignEx(selectConfig);
                }
            });
        }
    }

    public void removeSelectionChangedListener(iSelectionListener listener) {
        listenerList.remove(listener);
    }

    public void resetCursors() {
        if (selectedTool != null) {
            selectedTool = null;
            setCursor(null, null);
        }
    }

    public Rectangle shatterPane() {
        Rectangle r = null;

        if (this.designPane != null) {
            designPane.removeDesignListener(this);
            r = this.designPane.shatter();
        }

        if (paneParentViewer != null) {
            paneParentViewer.dispose();
            paneParentViewer = null;
        }

        designPane = null;
        fireSelectionChanged(emptySelection, emptyWSelection);

        return r;
    }

    @Override
    public void somethingHappened(final DesignEvent event) {
        switch (event.getEvent()) {
        case RELOAD_REQUEST:
            reloadDesign((Widget) event.getData());

            return;

        case WIDGET_ACTION:
            checkIfActive((MultiPageEditor) event.getOwner());
            handleWidgetAction(event.getWidget());

            return;

        case MOTION_TRACKING_CLICK:
            handleMotionTrackingClick(event);

            return;

        default:
            break;
        }

        Studio.runInSWTThread(new Runnable() {
            @Override
            public void run() {
                somethingHappenedEx(event);
            }
        });
    }

    @Override
    public void stateChanged(EventObject e) {
        projectChanged();
    }

    public void toolboxItemSelected(Tool tool) {
        Cursor cursor = null;
        java.awt.Cursor scursor = null;

        if (!"Pointer".equals(tool.name)) {
            if ((selectedTool != null) && (selectedTool == tool)) {
                return;
            }

            Image img = Studio.getResourceAsIcon(tool.id);

            if (img != null) {
                cursor = new Cursor(Display.getDefault(), img.getImageData(), 3, 3);
                scursor = com.appnativa.studio.Utilities.createCursor(tool.name,
                        Studio.getResourceAsBufferedImage(tool.id));
            }

            setCursor(cursor, scursor);
            selectedTool = tool;
        } else {
            resetCursors();
        }
    }

    @Override
    public void undoableEditHappened(UndoableEditEvent event) {
        IOperationHistory history = editor.getSite().getWorkbenchWindow().getWorkbench().getOperationSupport()
                .getOperationHistory();
        UndoableOperation op = new UndoableOperation("Design Change", event.getEdit());

        op.addContext(undoContext);

        try {
            history.execute(op, null, null);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public void updateSelections() {
        List<Widget> sels = (designPane == null) ? null : designPane.getSelectedWidgetConfigs();
        StructuredSelection s;
        final int count = (sels == null) ? 0 : sels.size();
        WidgetAdaptable[] a;
        WidgetAdaptable wa;

        if (count == 0) {
            s = emptySelection;
            a = emptyWSelection;
        } else if (count == 1) {
            s = new StructuredSelection(wa = new WidgetAdaptable(this, sels.get(0)));
            a = new WidgetAdaptable[] { wa };
        } else {
            int len = sels.size();

            a = new WidgetAdaptable[len];

            for (int i = 0; i < len; i++) {
                a[i] = new WidgetAdaptable(this, sels.get(i));
            }

            s = new StructuredSelection(Arrays.asList(a));
        }

        fireSelectionChanged(s, a);
    }

    public boolean updateSource(boolean force) {
        if (!force && (designPane != null)) {
            force = designPane.isDirty();
        }

        if (force && (cfg != null)) {
            IDocument doc = editor.getInputDocument();

            if (cfg instanceof TemplateContext) {
                doc.set(cfg.toString());
            } else {
                doc.set(removeTemplateElements().toString());
            }

            return true;
        }

        return false;
    }

    public void setAllowScrolling(boolean allowScrolling) {
        this.allowScrolling = allowScrolling;

        if (paneParentViewer != null) {
            ((UtilityPanel) paneParentViewer.getWidgetPanel().getView()).setLockViewSize(!allowScrolling);
            paneParentViewer.update();
        }
    }

    public void setCursor(final Cursor swtcursor, final java.awt.Cursor awtcursor) {
        Display.getDefault().asyncExec(new Runnable() {
            @Override
            public void run() {
                if (editor != null) {
                    editor.getEditorSite().getShell().setCursor(swtcursor);
                }
            }
        });
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                if (designPane != null) {
                    designPane.setCursor(awtcursor);
                    designPane.setMotionTracking(awtcursor != null);
                }
            }
        });
    }

    public void setDesignPane(WidgetPaneViewer parentViewer, DesignPane designPane) {
        this.designPane = designPane;
        this.designPane.addDesignListener(this);
        this.designPane.addUndoableEditListener(this);
        this.paneParentViewer = parentViewer;
        parentViewer.setAutoResizeWidgets(fitToPane);
        ((UtilityPanel) parentViewer.getWidgetPanel().getView()).setLockViewSize(!allowScrolling);

        Project p = getProject();

        if (p != null) {
            designPane.setSelectionColor(p.getSelectionColor());
            designPane.setTrackingColor(p.getTrackingColor());
            designPane.setGridColor(p.getGridColor());
            designPane.setCanvasColor(p.getCanvasColor());
        }
    }

    public void setFitToPane(boolean fitToPane) {
        this.fitToPane = fitToPane;

        if (paneParentViewer != null) {
            paneParentViewer.setAutoResizeWidgets(fitToPane);
        }
    }

    public void setShowGrid(boolean showGrid) {
        if (designPane != null) {
            designPane.setShowGrid(showGrid);
        }
    }

    public String getAssetsRelativePrefix() {
        if (editor.getEditorInput() instanceof IFileEditorInput) {
            IFile f = ((IFileEditorInput) editor.getEditorInput()).getFile();
            String s = f.getProjectRelativePath().toString();
            int n = s.lastIndexOf('/');

            if (n != -1) {
                s = s.substring(0, n + 1);
            }

            return s;
        }

        return null;
    }

    public URL getBaseURL() {
        Project p = (file == null) ? null : Project.getProject(file, true);

        if (p != null) {
            return p.getBaseURL();
        }

        return getURL();
    }

    public iWidget getContextWidget() {
        DesignPane pane = getDesignPane();
        iWidget widget = null;

        if (pane != null) {
            widget = pane.getSelectedWidget();

            if (widget == null) {
                widget = pane.getGridWidget();
            }

            if (widget == null) {
                widget = pane.getRootWidget();
            }
        }

        return widget;
    }

    public DesignPane getDesignPane() {
        return designPane;
    }

    public IProject getIProject() {
        if (file != null) {
            return file.getProject();
        }

        return null;
    }

    public iSPOTElement getLayoutConfig() {
        if (designPane == null) {
            return null;
        }

        iWidget gw = designPane.getGridWidget();
        iWidget.WidgetType wt = (gw == null) ? iWidget.WidgetType.Label : gw.getWidgetType();
        iSPOTElement cfg = null;

        switch (wt) {
        case TabPane:
        case SplitPane:
            cfg = (iSPOTElement) gw.getLinkedData();

            break;

        case GridPane:
            cfg = ((GridPane) gw.getLinkedData()).regions;

            break;

        case Form:
        case GroupBox:
            cfg = (iSPOTElement) gw.getLinkedData();

            if (!((GroupBox) cfg).layout.stringValue().equals("forms")) {
                cfg = null;
            }

            break;

        default:
            break;
        }

        return cfg;
    }

    public Dimension getPreferredSize() {
        if ((designPane != null) && (designPane.getRootWidget() != null)) {
            UIDimension d = designPane.getRootWidget().getContainerComponent().getPreferredSize();

            return new Dimension(d.intWidth(), d.intHeight());
        }

        return null;
    }

    public Project getProject() {
        if ((project == null) && (Platform.getAppContext() != null)) {
            if (file != null) {
                project = Project.getProject(file, true);

                if (project != null) {
                    project.addChangeListener(this);
                }
            }
        }

        if ((project != null) && project.isDirty()) {
            ignoreProjetChangeEvents = true;

            try {
                project.reloadApplicationConfig();
            } catch (Exception e) {
                Studio.showError(e, false);
            }

            ignoreProjetChangeEvents = false;
        }

        return project;
    }

    public URL getURL() {
        try {
            return editor.getInputURI().toURL();
        } catch (MalformedURLException e) {
            return null;
        }
    }

    public WindowViewer getWindowViewer() {
        return paneParentViewer.getWindow();
    }

    public boolean isAllowScrolling() {
        return allowScrolling;
    }

    public boolean isFitToPane() {
        return fitToPane;
    }

    public boolean isGUIWidget() {
        if (cfg == null) {
            try {
                IDocument doc = editor.getInputDocument();
                SDFNode node = SDFNode.parse(new StringReader(doc.get()));

                node = node.getFirstNode();

                if (node != null) {
                    String s = node.getNodeName();

                    if (s.indexOf('.') == -1) {
                        s = "com.appnativa.rare.spot." + s;

                        Class cls = Class.forName(s);

                        if (Widget.class.isAssignableFrom(cls)) {
                            return true;
                        }

                        if (com.appnativa.rare.spot.Application.class.isAssignableFrom(cls)) {
                            return true;
                        }

                        if (com.appnativa.rare.spot.MainWindow.class.isAssignableFrom(cls)) {
                            return true;
                        }

                        return false;
                    }
                }
            } catch (Exception e) {
                Studio.showError(e, false);
            }
        }

        return (cfg instanceof Widget) || (cfg instanceof MainWindow)
                || (cfg instanceof com.appnativa.rare.spot.Application);
    }

    void editWithDialogEx(final Widget wc, final iWidget w) {
        SPOTSet set = null;
        String name = null;

        switch (w.getWidgetType()) {
        case SplitPane: {
            SplitPane sp = (SplitPane) wc;
            SPOTSet props = sp.getSplitProportions();
            float splits[];

            if (props == null) {
                splits = new float[] { .5f };
            } else {
                splits = props.floatValues();
            }

            SplitPaneEditor ed = new SplitPaneEditor(Display.getCurrent().getActiveShell(), splits);

            if (ed.open() == IDialogConstants.OK_ID) {
                splits = ed.getSplits();

                try {
                    MutableInteger changed = new MutableInteger(0);
                    // convert strings to get rid of impercise garbage
                    String[] ssplits = new String[splits.length];

                    for (int i = 0; i < splits.length; i++) {
                        ssplits[i] = String.valueOf(splits[i]);
                    }

                    FormChanger.changeValue(designPane, sp.getSplitProportionsReference(), ssplits, false, true,
                            changed);

                    if (changed.get() == 1) {
                        ((SplitPaneViewer) w).setSplitProportions(splits);
                        w.update();
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }

            break;
        }

        case TabPane: {
            set = ((TabPane) wc).tabs;
            name = "Tab";

            break;
        }

        case Table: {
            set = ((Table) wc).columns;
            name = "Column";

            break;
        }

        case MenuBar: {
            set = ((MenuBar) wc).getPopupMenuReference();
            name = "MenuItem";

            break;
        }

        case Navigator: {
            set = ((Navigator) wc).actions;
            name = "Action";

            break;
        }

        default:
            break;
        }

        if (set != null) {
            SequenceArrayEditor ed = new SequenceArrayEditor(Display.getCurrent().getActiveShell(), set, name,
                    true);

            designPane.startEditsCapture();

            if ((ed.open() == IDialogConstants.OK_ID) && designPane.hasCapturedEdits()) {
                SPOTSet e = (SPOTSet) ed.getSPOTElement();

                set.spot_copy(e, false);
                Studio.runInSwingThread(new Runnable() {
                    @Override
                    public void run() {
                        designPane.endEditsCapture(false, true, wc);
                    }
                });
            } else {
                designPane.endEditsCapture(true, false, null);
            }
        }
    }

    void reload() {
        if (designPane != null) {
            reloadDesign(null);
        } else {
            updateSource(true);
        }
    }

    void somethingHappenedEx(DesignEvent event) {
        switch (event.getEvent()) {
        case RELOAD_REQUEST:
            reloadDesign((Widget) event.getData());

            break;

        case WIDGET_ACTION:
            checkIfActive((MultiPageEditor) event.getOwner());
            handleWidgetAction(event.getWidget());

            break;

        case SELECTION_CHANGED:
            updateSelections();

            break;

        case MOTION_TRACKING_CLICK:
            handleMotionTrackingClick(event);

            break;

        case DOCUMENT_MODIFIED:
            if (designPane != null) {
                editor.setDirty(designPane.isDirty());
            }

            break;

        case OPEN_DOCUMENT:
            URL u = (URL) event.getData();

            try {
                final IFile[] a = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(u.toURI());
                final IFile efile;
                final File jfile;

                if ((a != null) && (a.length > 0)) {
                    efile = a[0];
                    jfile = null;
                } else {
                    FileEx f = new FileEx(u.getPath());

                    if (f.exists() && f.isFile()) {
                        jfile = f;
                    } else {
                        jfile = null;
                    }

                    efile = null;
                }

                if ((efile != null) || (jfile != null)) {
                    Display.getDefault().asyncExec(new Runnable() {
                        public void run() {
                            IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
                                    .getActivePage();

                            try {
                                if (jfile != null) {
                                    IFileStore fileStore = EFS.getLocalFileSystem().getStore(jfile.toURI());

                                    IDE.openEditorOnFileStore(page, fileStore);
                                } else {
                                    IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry()
                                            .getDefaultEditor(efile.getName());

                                    page.openEditor(new FileEditorInput(efile), desc.getId());
                                }
                            } catch (Exception e) {
                            }
                        }
                    });
                }

                break;
            } catch (URISyntaxException e1) {
            }

            Display.getDefault().beep();

            break;

        default:
            break;
        }
    }

    protected boolean cleanElement(iSPOTElement root, iSPOTElement e) {
        if (e == null) {
            return false;
        }

        if (e.spot_getLinkedData() == TemplateHandler.TAG) {
            if (root == cfg) {
                cfg = null;
            }

            e.spot_clear();

            return true;
        }

        if (e instanceof SPOTAny) {
            cleanElement(root, ((SPOTAny) e).getValue());
        } else if (e instanceof SPOTSequence) {
            SPOTSequence seq = (SPOTSequence) e;
            int len = seq.spot_getCount();

            for (int i = 0; i < len; i++) {
                if (cleanElement(root, e = seq.spot_elementAt(i))) {
                    seq.spot_clearReferenceVariable(e);
                }
            }
        } else if (e instanceof SPOTSet) {
            SPOTSet set = (SPOTSet) e;
            int len = set.size();

            for (int i = 0; i < len; i++) {
                cleanElement(root, (iSPOTElement) set.get(i));
            }
        }

        return false;
    }

    protected void fireSelectionChanged(final StructuredSelection selection, final WidgetAdaptable[] wa) {
        if (!isNewSelection()) {
            return;
        }

        Runnable r = new Runnable() {
            public void run() {
                Object[] listeners = listenerList.getListeners();

                for (int i = 0; i < listeners.length; ++i) {
                    ((iSelectionListener) listeners[i]).selectionChanged(selection);
                }

                if (designPane == null) {
                    PropertiesView.widgetSelectionChanged(emptyWSelection);
                } else {
                    PropertiesView.widgetSelectionChanged(wa);
                }
            }
        };

        Studio.runInSWTThread(r);
    }

    protected boolean isNewSelection() {
        List<Widget> cfgs = null;

        do {
            if (designPane == null) {
                break;
            }

            cfgs = designPane.getSelectedWidgetConfigs();

            int len = cfgs.size();

            if ((oldSelections == null) || (oldSelections.size() != cfgs.size())) {
                break;
            }

            int i = 0;

            for (i = 0; i < len; i++) {
                if (oldSelections.get(i) != cfgs.get(i)) {
                    break;
                }
            }

            if (i == len) {
                return false;
            }
        } while (false);

        oldSelections = cfgs;

        return true;
    }

    protected void handleMotionTrackingClick(DesignEvent event) {
        try {
            Point p = (Point) event.getData();
            Widget cfg = (Widget) ((Widget) Studio.getAttribute(selectedTool.id)).clone();

            designPane.handleDrop(p, cfg, null);
        } finally {
            Studio.runInSWTThread(new Runnable() {
                @Override
                public void run() {
                    resetCursors();
                }
            });
        }
    }

    protected void handleWidgetAction(iWidget w) {
        Widget wc = (w == null) ? null : (Widget) w.getLinkedData();

        if (wc == null) {
            return;
        }

        if ((w instanceof com.appnativa.rare.viewer.iViewer)) {
            switch (w.getWidgetType()) {
            case TabPane:
            case SplitPane:
            case Table:
            case MenuBar:
                editWithDialog(wc, w);

                break;

            default:
                break;
            }
        } else {
            switch (w.getWidgetType()) {
            case Navigator:
                editWithDialog(wc, w);

                break;

            case Line:
                // cfg=w.linkedData.linesReference
                // dialog=window.openDialog("lines.sdf","Line Chooser",cfg).returnValue
                // if(dialog!=null && dialog.okPressed) {
                // var changed=new com.appnativa.util.MutableInteger(0);
                // FormChanger.changeValue(this.designPanel.glassPane,cfg,dialog.lines,false,true,changed)
                // if(changed.value>0) {
                // this.designPanel.glassPane.requestReload(null)
                // }
                // }
                break;

            default:
                Studio.runInSwingThread(new Runnable() {
                    @Override
                    public void run() {
                        if (designPane != null) {
                            designPane.inplaceEdit();
                        }
                    }
                });
            }

            return;
        }
    }

    protected void projectChanged() {
        if (!ignoreProjetChangeEvents && (Studio.getSelectedDocument() == this)) {
            if (file != null) {
                Project p = Project.getProject(file, false);

                if (p != null) {
                    if (designPane != null) {
                        designPane.setSelectionColor(p.getSelectionColor());
                        designPane.setTrackingColor(p.getTrackingColor());
                        designPane.setGridColor(p.getGridColor());
                        designPane.setCanvasColor(p.getCanvasColor());
                        reloadDesign(null);
                    }
                }
            }
        }
    }

    protected iSPOTElement removeTemplateElements() {
        iSPOTElement e = cfg;

        e.spot_setLinkedData(null);
        cleanElement(e, e);

        if (e != cfg) {
            cfg = null;
        }

        return e;
    }

    private void checkIfActive(final MultiPageEditor e) {
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                e.setFocus();
            }
        });
    }

    private void reloadDesignEx(Widget cfg) {
        if (designPane != null) {
            designPane.prepareForReload();
            iWidget w = paneParentViewer.removeWidget();
            WindowViewer win = Platform.getWindowViewer();
            try {
                iContainer c = createWidget(win, paneParentViewer);
                paneParentViewer.setWidget(c);
                paneParentViewer.update();
                designPane.setReloadedRootWidget(c, cfg == null);
                if (cfg != null) {
                    designPane.selectByElementEquals(cfg);
                }
            } catch (Exception e) {
                Studio.showError(e, true);
            } finally {
                if (w != null) {
                    w.dispose();
                }
            }
        }
    }

    private void updateDesignPane() {
        designPane.prepareForReload();

        iWidget w = designPane.getRootWidget();

        paneParentViewer.setWidget((iWidget) null, false);

        WindowViewer win = (WindowViewer) paneParentViewer.getWindow().getViewer();

        try {
            iContainer c = createWidget(win, paneParentViewer);

            if (w != null) {
                w.setVisible(false);
            }

            paneParentViewer.setWidget(c);
            paneParentViewer.update();
            designPane.setReloadedRootWidget(c, true);
        } catch (Exception e) {
            Studio.showError(e, true);
        } finally {
            if (w != null) {
                w.dispose();
            }
        }
    }

    private Project getProjectEx() {
        if ((project == null)) {
            if (file != null) {
                project = Project.getProject(file, false);

                if (project != null) {
                    project.addChangeListener(this);
                }
            }
        }

        return project;
    }

    public static class WidgetAdaptable implements IAdaptable { // ,IWorkbenchAdapter
        SequenceProperty attributes;
        SPOTSequence config;
        List<SPOTSequence> configs;
        RMLDocument document;
        WidgetProperty property;
        boolean sorted;
        iWidget widget;
        private boolean showingAttributes;

        public WidgetAdaptable(RMLDocument doc, SPOTSequence config) {
            this.document = doc;
            this.config = config;
        }

        public WidgetAdaptable(RMLDocument doc, List<SPOTSequence> configs, SPOTSequence base) {
            this.document = doc;
            this.configs = configs;
            this.config = base;
        }

        public void dispose() {
            if (property != null) {
                property.dispose();
            }

            document = null;
            widget = null;
            property = null;
        }

        public void handleReloadRequest(final iSPOTElement e, final Object value, final String prop,
                final boolean reload) {
            Studio.runInSwingThread(new Runnable() {
                @Override
                public void run() {
                    handleReloadRequestEx(e, value, prop, reload);
                }
            });
        }

        public void propertyChanged(iSPOTElement e, Object value, boolean b) {
            if (value instanceof SequenceProperty) {
                return;
            }

            MutableInteger changed = new com.appnativa.util.MutableInteger(0);

            try {
                if (showingAttributes) {
                    if (value instanceof iSPOTElement) {
                        value = Utilities.toString((iSPOTElement) value);
                    }

                    if (configs != null) {
                        FormChanger.changeAttributes(document.designPane, configs, e.spot_getName(), value);
                    } else {
                        FormChanger.changeAttribute(document.designPane, config, e.spot_getName(), value);
                    }
                } else {
                    boolean reload = SPOTInspector.needsReload(e);
                    String prop = SPOTInspector.getComponentProperty(e, value);

                    if (configs != null) {
                        FormChanger.changeValues(document.designPane, configs, e, value, changed);
                    } else {
                        FormChanger.changeValue(document.designPane, e, value, false, reload, changed);
                    }

                    if (changed.getValue() > 0) {
                        if ("borders".equals(e.spot_getName()) && (value instanceof SPOTSet)
                                && ((SPOTSet) value).size() == 0) {
                            if (config instanceof Widget) {
                                ((Widget) config).setBorders(null);
                            } else if (config instanceof GridCell) {
                                ((GridCell) config).setBorders(null);
                            }
                        }

                        handleReloadRequest(e, value, prop, reload);
                    }
                }
            } catch (MalformedURLException e1) {
                e1.printStackTrace();
            }
        }

        public void setShowAttributes(boolean showAttributes) {
            if (this.showingAttributes != showAttributes) {
                this.showingAttributes = showAttributes;

                if (attributes == null) {
                    attributes = EditorHelper.getAttributesSequenceProperty(config, configs);
                }

                property = null;
            }
        }

        public void setSorted(boolean sorted) {
            this.sorted = sorted;

            if (property != null) {
                property.setSorted(sorted);
            }
        }

        @Override
        public Object getAdapter(Class adapter) {
            if (adapter == IPropertySource.class) {
                if ((property == null) && (config != null)) {
                    if (showingAttributes) {
                        property = new WidgetProperty(this, attributes.getSequence(),
                                attributes.getPropertyDescriptors());
                    } else {
                        property = new WidgetProperty(this, config);
                    }

                    property.setSorted(sorted);
                }

                return property;
            }

            if (adapter == IWorkbenchAdapter.class) {
                return this;
            }

            return null;
        }

        public Object[] getChildren(Object o) {
            return new Object[0];
        }

        public RMLDocument getDocument() {
            return document;
        }

        public SPOTSequence getElement() {
            return config;
        }

        public ImageDescriptor getImageDescriptor(Object object) {
            return null;
        }

        public String getLabel(Object o) {
            return config.spot_getClassShortName();
        }

        public Object getParent(Object o) {
            return null;
        }

        public iWidget getWidget() {
            if (((widget == null) || widget.isDisposed()) && (document != null)) {
                DesignPane pane = document.getDesignPane();

                if (pane != null) {
                    widget = pane.getSelectedWidget();

                    if (widget == null) {
                        widget = pane.getGridWidget();
                    }

                    if (widget == null) {
                        widget = pane.getRootWidget();
                    }
                }

                if ((widget != null) && (widget.getLinkedData() != config)) {
                    widget = null;
                }
            }

            return widget;
        }

        public boolean isShowAttributes() {
            return showingAttributes;
        }

        public boolean isSorted() {
            return sorted;
        }

        void handleReloadRequestEx(iSPOTElement e, Object value, String prop, boolean reload) {
            do {
                iWidget w = getWidget();

                if ((w != null) && (configs == null)) {
                    if (value instanceof UIColor) {
                        if ("foreground".equals(prop)) {
                            w.setForeground((UIColor) value);
                        } else if ("background".equals(prop)) {
                            iPlatformPainter p = ColorUtils.getPainter((UIColor) value);

                            w.setBackgroundPainter((iBackgroundPainter) p);

                            if (p == null) {
                                w.setBackground((UIColor) value);
                            }
                        }

                        w.update();

                        break;
                    }

                    if (value instanceof Font) {
                        if ("font".equals(prop)) {
                            w.setFont(UIFontHelper.getFont((Font) value));
                            w.update();

                            break;
                        }
                    }

                    if ((value != null) && (prop != null) && (prop.length() > 1) && !prop.equals("reload")) {
                        char c = prop.charAt(0);
                        StringBuilder sb = new StringBuilder(prop.length() + 5);

                        sb.append("set").append(Character.toUpperCase(c)).append(prop, 1, prop.length());

                        if (value instanceof iSPOTElement) {
                            value = w.expandString(value.toString(), false);
                        }

                        if (JavaHandler.setFunctionValueEx(w, sb.toString(), value)) {
                            w.update();

                            break;
                        }
                    }
                }

                if (reload) {
                    document.updateDesignPane();
                }
            } while (false);
        }
    }

    static class UndoableOperation extends AbstractOperation {
        UndoableEdit edit;

        public UndoableOperation(String label, UndoableEdit e) {
            super(label);
            edit = e;
        }

        @Override
        public boolean canRedo() {
            return edit.canRedo();
        }

        @Override
        public boolean canUndo() {
            return edit.canUndo();
        }

        @Override
        public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
            return Status.OK_STATUS;
        }

        @Override
        public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
            edit.redo();

            RMLDocument doc = Studio.getSelectedDocument();

            if (doc != null) {
                doc.reload();
            }

            return Status.OK_STATUS;
        }

        @Override
        public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
            edit.undo();

            RMLDocument doc = Studio.getSelectedDocument();

            if (doc != null) {
                doc.reload();
            }

            return Status.OK_STATUS;
        }
    }
}