import org.eclipse.core.runtime.jobs.Job;\r
import org.eclipse.draw2d.geometry.Rectangle;\r
import org.eclipse.gef.ui.parts.SelectionSynchronizer;\r
+import org.eclipse.jface.action.Action;\r
import org.eclipse.jface.dialogs.Dialog;\r
import org.eclipse.swt.SWT;\r
import org.eclipse.swt.custom.SashForm;\r
import org.eclipse.swt.layout.GridLayout;\r
import org.eclipse.swt.widgets.Composite;\r
import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.IActionBars;\r
import org.eclipse.ui.IEditorInput;\r
import org.eclipse.ui.IEditorSite;\r
import org.eclipse.ui.PartInitException;\r
+import org.eclipse.ui.actions.ActionFactory;\r
import org.eclipse.ui.ide.IDE;\r
import org.eclipse.ui.part.EditorPart;\r
import org.eclipse.ui.part.FileEditorInput;\r
mSashError.setWeights(new int[] { 80, 20 });\r
mSashError.setMaximizedControl(mLayoutCanvas);\r
\r
+ setupEditActions();\r
+\r
// Initialize the state\r
reloadPalette();\r
}\r
\r
+ private void setupEditActions() {\r
+\r
+ IActionBars actionBars = getEditorSite().getActionBars();\r
+\r
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), new Action("Copy") {\r
+ @Override\r
+ public void run() {\r
+ // TODO enable copy only when there's a selection\r
+ mLayoutCanvas.onCopy(mClipboard);\r
+ }\r
+ });\r
+\r
+ actionBars.setGlobalActionHandler(ActionFactory.CUT.getId(), new Action("Cut") {\r
+ @Override\r
+ public void run() {\r
+ // TODO enable cut only when there's a selection\r
+ mLayoutCanvas.onCut(mClipboard);\r
+ }\r
+ });\r
+\r
+ actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), new Action("Paste") {\r
+ @Override\r
+ public void run() {\r
+ mLayoutCanvas.onPaste(mClipboard);\r
+ }\r
+ });\r
+\r
+ actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),\r
+ new Action("Select All") {\r
+ @Override\r
+ public void run() {\r
+ mLayoutCanvas.onSelectAll();\r
+ }\r
+ });\r
+ }\r
+\r
/**\r
* Switches the stack to display the error label and hide the canvas.\r
* @param errorFormat The new error to display if not null.\r
import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;\r
\r
import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.Clipboard;\r
import org.eclipse.swt.events.MouseEvent;\r
import org.eclipse.swt.events.MouseListener;\r
import org.eclipse.swt.events.MouseMoveListener;\r
*/\r
private static final int SELECTION_MIN_SIZE = 6;\r
\r
+ /*\r
+ * The last valid ILayoutResult passed to {@link #setResult(ILayoutResult)}.\r
+ * This can be null.\r
+ * When non null, {@link #mLastValidViewInfoRoot} is guaranteed to be non-null too.\r
+ */\r
private ILayoutResult mLastValidResult;\r
+\r
+ /**\r
+ * The ViewInfo root created for the last update of {@link #mLastValidResult}.\r
+ * This is null when {@link #mLastValidResult} is null.\r
+ * When non null, {@link #mLastValidResult} is guaranteed to be non-null too.\r
+ */\r
private ViewInfo mLastValidViewInfoRoot;\r
\r
+ /**\r
+ * True when the last {@link #setResult(ILayoutResult)} provided a valid {@link ILayoutResult}\r
+ * in which case it is also available in {@link #mLastValidResult}.\r
+ * When false this means the canvas is displaying an out-dated result image & bounds and some\r
+ * features should be disabled accordingly such a drag'n'drop.\r
+ * <p/>\r
+ * When this is false, {@link #mLastValidResult} can be non-null and points to an older\r
+ * layout result.\r
+ */\r
+ private boolean mIsResultValid;\r
+\r
/** Current background image. Null when there's no image. */\r
private Image mImage;\r
\r
+ /** The current selection list. The list is never null, however it can be empty. */\r
private final LinkedList<Selection> mSelections = new LinkedList<Selection>();\r
\r
/** Selection border color. Do not dispose, it's a system color. */\r
/** Hover border color. Must be disposed, it's NOT a system color. */\r
private Color mHoverFgColor;\r
\r
- private AlternateSelection mAltSelection;\r
-\r
/**\r
- * True when the last {@link #setResult(ILayoutResult)} provided a valid {@link ILayoutResult}\r
- * in which case it is also available in {@link #mLastValidResult}.\r
- * When false this means the canvas is displaying an out-dated result image & bounds and some\r
- * features should be disabled accordingly such a drag'n'drop.\r
+ * The <em>current</em> alternate selection, if any, which changes when the Alt key is\r
+ * used during a selection. Can be null.\r
*/\r
- private boolean mIsResultValid;\r
+ private AlternateSelection mAltSelection;\r
\r
\r
public LayoutCanvas(Composite parent, int style) {\r
redraw();\r
}\r
\r
+ /**\r
+ * Called by the {@link GraphicalEditorPart} when the Copy action is requested.\r
+ *\r
+ * @param clipboard The shared clipboard. Must not be disposed.\r
+ */\r
+ public void onCopy(Clipboard clipboard) {\r
+ // TODO implement copy to clipbard. Also will need to provide feedback to enable\r
+ // copy only when there's a selection.\r
+ }\r
+\r
+ /**\r
+ * Called by the {@link GraphicalEditorPart} when the Cut action is requested.\r
+ *\r
+ * @param clipboard The shared clipboard. Must not be disposed.\r
+ */\r
+ public void onCut(Clipboard clipboard) {\r
+ // TODO implement copy to clipbard. Also will need to provide feedback to enable\r
+ // cut only when there's a selection.\r
+ }\r
+\r
+ /**\r
+ * Called by the {@link GraphicalEditorPart} when the Paste action is requested.\r
+ *\r
+ * @param clipboard The shared clipboard. Must not be disposed.\r
+ */\r
+ public void onPaste(Clipboard clipboard) {\r
+\r
+ }\r
+\r
+ /**\r
+ * Called by the {@link GraphicalEditorPart} when the Select All action is requested.\r
+ */\r
+ public void onSelectAll() {\r
+ // First clear the current selection, if any.\r
+ mSelections.clear();\r
+ mAltSelection = null;\r
+\r
+ // Now select everything if there's a valid layout\r
+ if (mIsResultValid && mLastValidResult != null) {\r
+ selectAllViewInfos(mLastValidViewInfoRoot);\r
+ redraw();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Delete action\r
+ */\r
+ public void onDelete() {\r
+ // TODO not implemented yet, not even hooked in yet!\r
+ }\r
+\r
//---\r
\r
/**\r
}\r
\r
/**\r
+ * Used by {@link #onSelectAll()} to add all current view infos to the selection list.\r
+ *\r
+ * @param viewInfo The root to add. This info and all its children will be added to the\r
+ * selection list.\r
+ */\r
+ private void selectAllViewInfos(ViewInfo viewInfo) {\r
+ mSelections.add(new Selection(viewInfo));\r
+ for (ViewInfo vi : viewInfo.getChildren()) {\r
+ selectAllViewInfos(vi);\r
+ }\r
+ }\r
+\r
+ /**\r
* Maps a {@link ILayoutViewInfo} in a structure more adapted to our needs.\r
* The only large difference is that we keep both the original bounds of the view info\r
* and we pre-compute the selection bounds which are absolute to the rendered image (where\r
\r
/**\r
* Constructs a {@link ViewInfo} hierarchy based on a given {@link ILayoutViewInfo}\r
- * hierarchy. This call is recursives and builds a full tree.\r
+ * hierarchy. This call is recursive and builds a full tree.\r
*\r
* @param viewInfo The root of the {@link ILayoutViewInfo} hierarchy.\r
*/\r
mSelectionRect = new Rectangle(x, y, w - 1, h - 1);\r
}\r
\r
- /** Returns the original {@link ILayoutResult} bounds, relative to the parent. */\r
+ /**\r
+ * Returns the original {@link ILayoutResult} bounds, relative to the parent.\r
+ * @deprecated TODO Remove if it's not going to be used\r
+ */\r
+ @SuppressWarnings("unused")\r
public Rectangle getRealRect() {\r
return mRealRect;\r
}\r
/**\r
* Returns the parent {@link ViewInfo}.\r
* It is null for the root and non-null for children.\r
+ * @deprecated TODO Remove if it's not going to be used\r
*/\r
+ @SuppressWarnings("unused")\r
public ViewInfo getParent() {\r
return mParent;\r
}\r