Package org.dyno.visual.swing.editors

Source Code of org.dyno.visual.swing.editors.VisualSwingEditor$CreateDesignerUIJob

/************************************************************************************
* Copyright (c) 2008 William Chen.                                                 *
*                                                                                  *
* 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 *
*                                                                                  *
* Use is subject to the terms of Eclipse Public License v1.0.                      *
*                                                                                  *
* Contributors:                                                                    *
*     William Chen - initial API and implementation.                               *
************************************************************************************/

package org.dyno.visual.swing.editors;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;

import org.dyno.visual.swing.VisualSwingPlugin;
import org.dyno.visual.swing.base.EditorAction;
import org.dyno.visual.swing.base.ExtensionRegistry;
import org.dyno.visual.swing.base.ISyncUITask;
import org.dyno.visual.swing.base.JavaUtil;
import org.dyno.visual.swing.designer.VisualDesigner;
import org.dyno.visual.swing.plugin.spi.ILookAndFeelAdapter;
import org.dyno.visual.swing.plugin.spi.ISourceParser;
import org.dyno.visual.swing.plugin.spi.ParserFactory;
import org.dyno.visual.swing.plugin.spi.WidgetAdapter;
import org.eclipse.albireo.core.AwtEnvironment;
import org.eclipse.albireo.core.SwingControl;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.views.contentoutline.ContentOutline;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.PropertySheetPage;

/**
*
* VisualSwingEditor
*
* @version 1.0.0, 2008-7-3
* @author William Chen
*/
@SuppressWarnings("unchecked")
public class VisualSwingEditor extends AbstractDesignerEditor implements IResourceChangeListener, ISelectionProvider, IPartListener, ISelectionListener {
  private static final String EDITOR_IMAGE = "/icons/editor.png";
  private static final int DELAYED_TIME = 250;
  private List<ISelectionChangedListener> listeners;
  private SwingControl embedded;
  private VisualDesigner designer;
  private VisualSwingOutline outline;
  private HashMap<String, EditorAction> actions;
  private ArrayList<EditorAction> actionList;
  private IJavaProject hostProject;
  private boolean isGeneratingCode;
  private ISelection selection;
  private PropertySheetPage sheetPage;
  private ScrolledComposite scrollPane;
  private PalettePage palettePage;
  private boolean isParsing;
  private boolean isCreatingDesignerUI;
  private String lnfClassname;

  public VisualSwingEditor() {
    super();
    actions = new HashMap<String, EditorAction>();
    actionList = new ArrayList<EditorAction>();
    listeners = new ArrayList<ISelectionChangedListener>();
  }

  public IJavaProject getHostProject() {
    return hostProject;
  }

  public void init(IEditorSite site, IEditorInput input) throws PartInitException {
    super.init(site, input);
    site.getWorkbenchWindow().getPartService().addPartListener(this);
    site.setSelectionProvider(this);
    site.getWorkbenchWindow().getSelectionService().addSelectionListener(this);
  }

  public Object getAdapter(Class adapter) {
    if (adapter == IContentOutlinePage.class) {
      if (outline == null && designer != null) {
        outline = new VisualSwingOutline(designer);
      }
      return outline;
    } else if (adapter == IPropertySheetPage.class) {
      if (sheetPage == null) {
        sheetPage = new WidgetPropertyPage();
        sheetPage.setPropertySourceProvider(new WidgetAdapterContentProvider());
      }
      return sheetPage;
    } else if (adapter == IPalettePage.class) {
      if (palettePage == null) {
        if (designer != null)
          palettePage = new PalettePage(designer);
        else
          palettePage = new PalettePage(this);
      }
      return palettePage;
    } else
      return super.getAdapter(adapter);
  }

  public boolean isDirty() {
    if (super.isDirty())
      return true;
    return !isGeneratingCode && designer != null && (designer.isLnfChanged() || designer.isDirty());
  }

  public boolean isSaveAsAllowed() {
    return super.isSaveAsAllowed();
  }

  public boolean isSaveOnCloseNeeded() {
    return super.isSaveOnCloseNeeded();
  }

  public ArrayList<EditorAction> getActions() {
    return actionList;
  }

  public VisualDesigner getDesigner() {
    return designer;
  }

  public void refreshActionState() {
    if (designer != null) {
      for (EditorAction action : actions.values())
        action.updateState();
    }
  }

  public void dispose() {
    super.dispose();
    closeRelatedView();
    ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
  }

  public void addAction(EditorAction action) {
    if (action == null) {
      actionList.add(null);
    } else if (actions.get(action.getId()) == null) {
      actions.put(action.getId(), action);
      actionList.add(action);
    }
  }

  public IAction getEditorAction(String id){
    return actions.get(id);
  }
  public void setFocus() {
    if (embedded != null) {
      embedded.setFocus();
    }
    VisualSwingPlugin.setCurrentEditor(this);
  }

  public void changeToLnf(String className) {
    LookAndFeel lnf = UIManager.getLookAndFeel();
    if (lnf == null) {
      if (className != null) {
        setLnfClassname(className);
      }
    } else {
      String lnfName = lnf.getClass().getName();
      if (className == null) {
        className = UIManager.getCrossPlatformLookAndFeelClassName();
        if (!lnfName.equals(className))
          setLnfClassname(className);
      } else if (!lnfName.equals(className)) {
        setLnfClassname(className);
      }
    }
  }

  public void createPartControl(Composite parent) {
    if (!isSwingComponent()) {
      switchToJavaEditor();
    } else {
      parent.setLayout(new FillLayout());
      Splitter splitter = new Splitter(parent, SWT.VERTICAL);
      Composite design = new Composite(splitter, SWT.NONE);
      splitter.setFirstControl(design);
      design.setLayout(new FillLayout());
      scrollPane = new ScrolledComposite(design, SWT.H_SCROLL | SWT.V_SCROLL);
      scrollPane.setExpandHorizontal(true);
      scrollPane.setExpandVertical(true);
      Composite designerContainer = new Composite(scrollPane, SWT.NONE);
      scrollPane.setContent(designerContainer);
      designerContainer.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
      designerContainer.setLayout(new FillLayout());
      embedded = new EmbeddedVisualDesigner(designerContainer);
      Composite comps = new Composite(splitter, SWT.NONE);
      splitter.setSecondControl(comps);

      comps.setLayout(new FillLayout());
      super.createPartControl(comps);
      getSite().setSelectionProvider(this);
      setTitleImage(VisualSwingPlugin.getSharedImage(EDITOR_IMAGE));
    }
  }

  @Override
  protected void createActions() {
    super.createActions();
    replaceAction(ITextEditorActionConstants.CUT);
    replaceAction(ITextEditorActionConstants.COPY);
    replaceAction(ITextEditorActionConstants.PASTE);
    replaceAction(ITextEditorActionConstants.SELECT_ALL);
    replaceAction(ITextEditorActionConstants.DELETE);
  }
  private void replaceAction(String id){
    IAction action = getAction(id);
    setAction(id, null);
    setAction(id, new DelegateAction(this, action));
  }
  private void onEditorOpen() {
    ResourcesPlugin.getWorkspace().addResourceChangeListener(this,
        IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE);
    invokeLater(new Runnable() {

      public void run() {
        validateContent();
      }
    });
    asyncRunnable(new Runnable() {

      public void run() {
        openRelatedView();
      }
    });
  }

  class CreateDesignerUIJob extends Job {
    private boolean isTimerAction;

    public CreateDesignerUIJob(boolean isTimer) {
      super(Messages.VisualSwingEditor_Designer_Creation_Job);
      setPriority(INTERACTIVE);
      this.isTimerAction = isTimer;
    }

    protected IStatus run(IProgressMonitor monitor) {
      monitor.setTaskName(Messages.VisualSwingEditor_Generating_Designer);
      try {
        createDesignerUI(monitor);
      } catch (Exception e) {
        designer.initRootWidget(null);
        designer.setError(e);
      }
      if (isTimerAction)
        validateContent();
      else
        onEditorOpen();
      isCreatingDesignerUI = false;
      designer.unlock();
      monitor.done();
      return Status.OK_STATUS;
    }
  }

  private void createDesignerUI(IProgressMonitor monitor) throws Exception {
    final IFileEditorInput file = (IFileEditorInput) getEditorInput();
    asyncRunnable(new Runnable() {

      public void run() {
        setPartName(file.getName());
        setTitleToolTip(file.getToolTipText());
      }
    });
    ParserFactory factory = ParserFactory.getDefaultParserFactory();
    if (factory == null)
      throw new Exception("No parser factory available!");
    ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file.getFile());
    hostProject = unit.getJavaProject();
    ISourceParser sourceParser = factory.newParser();
    isParsing = true;
    VisualSwingPlugin.setCurrentEditor(this);
    this.designer.setCompilationUnit(unit);
    try {
      WidgetAdapter adapter = sourceParser.parse(unit, monitor);
      if (adapter != null) {
        designer.initRootWidget(adapter);
        setUpLookAndFeel(adapter.getWidget().getClass());
        designer.initNamespaceWithUnit(unit);
        refreshTree();
      } else {
        throw new Exception("This class is not a valid swing class!");
      }
    } catch (Exception e) {
      throw e;
    } finally {
      isParsing = false;
    }
  }

  private void setUpLookAndFeel(Class rootClass) {
    try {
      Field field = rootClass.getDeclaredField("PREFERRED_LOOK_AND_FEEL");
      if (field.getType() == String.class) {
        field.setAccessible(true);
        String lnf = (String) field.get(null);
        String className = UIManager.getCrossPlatformLookAndFeelClassName();
        if (lnf == null) {
          lnf = className;
        }
        setLnfClassname(lnf);
      }
    } catch (NoSuchFieldException nsfe) {
      String className = UIManager.getCrossPlatformLookAndFeelClassName();
      setLnfClassname(className);
    } catch (Exception e) {
      VisualSwingPlugin.getLogger().error(e);
      String className = UIManager.getCrossPlatformLookAndFeelClassName();
      setLnfClassname(className);
    }
  }

  private void refreshTree() {
    asyncRunnable(new Runnable() {

      public void run() {
        if (outline != null)
          outline.refreshTree();
      }
    });
  }

  private void safeSave(final IProgressMonitor monitor) {
    getDisplay().syncExec(new Runnable() {

      public void run() {
        doSave(monitor);
      }
    });
  }

  public void saveWithProgress() {
    try {
      IRunnableWithProgress runnable = new IRunnableWithProgress() {
        public void run(IProgressMonitor monitor) {
          safeSave(monitor);
        }
      };
      ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
      dialog.run(true, true, runnable);
    } catch (Exception e) {
      VisualSwingPlugin.getLogger().error(e);
      return;
    }
  }

  public void doSave(IProgressMonitor monitor) {
    if (super.isDirty()) {
      super.doSave(monitor);
    } else {
      isGeneratingCode = true;
      try {
        IFileEditorInput file = (IFileEditorInput) getEditorInput();
        setPartName(file.getName());
        setTitleToolTip(file.getToolTipText());
        ParserFactory factory = ParserFactory.getDefaultParserFactory();
        if (factory != null) {
          ISourceParser sourceParser = factory.newParser();
          Component root = designer.getRoot();
          if (root != null) {
            WidgetAdapter rootAdapter = WidgetAdapter.getWidgetAdapter(root);
            JavaUtil.hideMenu();
            String lnfCN = getLnfClassname();
            rootAdapter.setPreferredLookAndFeel(lnfCN); //$NON-NLS-1$
            ICompilationUnit unit = sourceParser.generate(rootAdapter, monitor);
            rootAdapter.setPreferredLookAndFeel(null); //$NON-NLS-1$
            if (unit != null) {
              designer.initNamespaceWithUnit(unit);
              designer.setLnfChanged(false);
            }
            designer.clearDirty();
            fireDirty();
          }
        }
      } catch (Exception e) {
        VisualSwingPlugin.getLogger().error(e);
      }
      isGeneratingCode = false;
    }
  }

  class EmbeddedVisualDesigner extends SwingControl {
    public EmbeddedVisualDesigner(Composite parent) {
      super(parent, SWT.NONE);
    }

    protected JComponent createSwingComponent() {
      designer = new VisualDesigner(VisualSwingEditor.this, this);
      JPanel backgroundPanel = new JPanel();
      backgroundPanel.setOpaque(true);
      backgroundPanel.setLayout(new BorderLayout());
      backgroundPanel.add(designer, BorderLayout.CENTER);
      backgroundPanel.setBackground(java.awt.Color.white);
      refreshActionState();
      if (!isCreatingDesignerUI) {
        isCreatingDesignerUI = true;
        new CreateDesignerUIJob(false).schedule();
      }
      return backgroundPanel;
    }

    public Composite getLayoutAncestor() {
      return getParent();
    }

  }

  public void setLnfClassname(String lnfClassname) {
    ILookAndFeelAdapter adapter = ExtensionRegistry.getLnfAdapter(lnfClassname);
    if (adapter != null) {
      try {
        LookAndFeel oldlnf = UIManager.getLookAndFeel();
        LookAndFeel newlnf = adapter.getLookAndFeelInstance();
        if (!isLnfEqual(oldlnf, newlnf)) {
          AwtEnvironment.runWithLnf(newlnf, new ISyncUITask() {

            public Object doTask() throws Throwable {
              if (designer != null) {
                Window window = SwingUtilities.getWindowAncestor(designer);
                if (window != null)
                  SwingUtilities.updateComponentTreeUI(window);
              }
              return null;
            }
          });
        }
      } catch (Throwable e) {
        VisualSwingPlugin.getLogger().error(e);
      }
    }
    this.lnfClassname = lnfClassname;
  }

  private boolean isLnfEqual(LookAndFeel lnf1, LookAndFeel lnf2) {
    if (lnf1 == null) {
      if (lnf2 == null) {
        return true;
      } else {
        return false;
      }
    } else {
      if (lnf2 == null) {
        return false;
      } else {
        String lnfId1 = lnf1.getID();
        String lnfId2 = lnf2.getID();
        if (!lnfId1.equals(lnfId2)) {
          return false;
        } else {
          Class clazz1 = lnf1.getClass();
          Class clazz2 = lnf2.getClass();
          return clazz1.equals(clazz2);
        }
      }
    }
  }

  public String getLnfClassname() {
    return lnfClassname;
  }

  public void resourceChanged(IResourceChangeEvent event) {
    switch (event.getType()) {
    case IResourceChangeEvent.POST_BUILD:
    case IResourceChangeEvent.POST_CHANGE:
      if (!isGeneratingCode) {
        IResourceDelta delta = event.getDelta();
        checkChange(delta);
      }
      break;
    case IResourceChangeEvent.PRE_CLOSE:
    case IResourceChangeEvent.PRE_DELETE:
      if (!isGeneratingCode) {
        IResource resource = event.getResource();
        if (hostProject.getProject() == resource) {
          closeRelatedView();
          closeMe();
        }
      }
      break;
    }
  }

  private void checkChange(IResourceDelta delta) {
    switch (delta.getKind()) {
    case IResourceDelta.REMOVED:
      IPath deltaPath = delta.getFullPath();
      IPath path = ((IFileEditorInput) getEditorInput()).getFile().getFullPath();
      if (deltaPath.equals(path)) {
        closeRelatedView();
        closeMe();
      }
      break;
    case IResourceDelta.CHANGED:
      deltaPath = delta.getFullPath();
      path = ((IFileEditorInput) getEditorInput()).getFile().getFullPath();
      if (deltaPath.equals(path)) {
        if (!isCreatingDesignerUI && !designer.isLocked()) {
          isCreatingDesignerUI = true;
          new CreateDesignerUIJob(true).schedule();
        }
      } else {
        IResourceDelta[] children = delta.getAffectedChildren(IResourceDelta.CHANGED | IResourceDelta.REMOVED);
        if (children != null && children.length > 0) {
          for (IResourceDelta res : children) {
            checkChange(res);
          }
        }
      }
    }
  }

  public void doSaveAs() {
    super.doSaveAs();
  }

  public void fireDirty() {
    asyncRunnable(new Runnable() {

      public void run() {
        firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY);
      }
    });
  }

  public void addSelectionChangedListener(ISelectionChangedListener listener) {
    if (!listeners.contains(listener))
      listeners.add(listener);
  }

  public ISelection getSelection() {
    if (embedded!=null&&embedded.isFocusControl())
      return selection;
    else
      return super.getSelectionProvider().getSelection();
  }

  public void removeSelectionChangedListener(ISelectionChangedListener listener) {
    if (listeners.contains(listener))
      listeners.remove(listener);
  }

  private void fireSelectionChanged() {
    SelectionChangedEvent evt = new SelectionChangedEvent(this, selection);
    for (ISelectionChangedListener listener : listeners) {
      listener.selectionChanged(evt);
    }
  }

  public void setSelection(ISelection selection) {
    if (this.selection == null) {
      if (selection != null && !selection.isEmpty()) {
        this.selection = selection;
        fireSelectionChanged();
      } else {
        if (outline != null)
          outline.refreshTree();
      }
    } else {
      if (selection == null) {
        if (!this.selection.isEmpty()) {
          this.selection = null;
          fireSelectionChanged();
        } else {
          if (outline != null)
            outline.refreshTree();
        }
      } else {
        if (selection.isEmpty()) {
          if (!this.selection.isEmpty()) {
            this.selection = selection;
            fireSelectionChanged();
          } else {
            fireSelectionChanged();
          }
        } else {
          if (this.selection.isEmpty()) {
            this.selection = selection;
            fireSelectionChanged();
          } else if (!this.selection.equals(selection)) {
            this.selection = selection;
            fireSelectionChanged();
          }
        }
      }
    }
    if (outline != null)
      outline.refreshTree();
  }

  public void validateContent() {
    if (designer != null && scrollPane != null) {
      final Dimension size = designer.getPreferredSize();
      asyncRunnable(new Runnable() {
        public void run() {
          scrollPane.setMinSize(size.width, size.height);
        }
      });
      designer.refreshDesigner();
    }
  }

  public void asyncRunnable(Runnable runnable) {
    getDisplay().asyncExec(runnable);
  }

  private void invokeLater(Runnable runnable) {
    SwingUtilities.invokeLater(runnable);
  }

  public void partActivated(IWorkbenchPart part) {
    if (part == this) {
      delaySwingExec(DELAYED_TIME, new ChangeLnfAction());
    }
  }

  private class ChangeLnfAction implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      if (isParsing)
        return;
      changeToLnf(getLnfClassname());
      if (designer != null)
        designer.clearCapture();
    }
  }

  private void delaySwingExec(int millies, ActionListener action) {
    Timer timer = new Timer(millies, action);
    timer.setRepeats(false);
    timer.start();
  }

  public void partBroughtToTop(IWorkbenchPart part) {
    if (part == this) {
      delaySwingExec(DELAYED_TIME, new ChangeLnfAction());
    }
  }

  public void partClosed(IWorkbenchPart part) {
  }

  public void partDeactivated(IWorkbenchPart part) {
    if (part == this) {
      if (designer != null)
        designer.capture();
    }
  }

  public void partOpened(IWorkbenchPart part) {
    if (part == this) {
      delaySwingExec(DELAYED_TIME, new ChangeLnfAction());
    }
  }

  public void clearToolSelection() {
    palettePage.clearToolSelection();
  }

  public void selectionChanged(IWorkbenchPart part, ISelection selection) {
    if (part instanceof ContentOutline && !selection.isEmpty() && selection instanceof IStructuredSelection) {
      designer.clearSelection();
      for (Object obj : ((IStructuredSelection) selection).toList()) {
        if (obj instanceof Component) {
          Component comp = (Component) obj;
          WidgetAdapter adapter = WidgetAdapter.getWidgetAdapter(comp);
          adapter.setSelected(true);
        }
      }
      designer.refreshDesigner();
    }
  }

  public boolean isFocusOnDesigner() {
    return embedded.isFocusControl();
  }
}
TOP

Related Classes of org.dyno.visual.swing.editors.VisualSwingEditor$CreateDesignerUIJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.