package org.droiddraw.gui; import org.droiddraw.AndroidEditor; import org.droiddraw.widget.AbsoluteLayout; import org.droiddraw.widget.AnalogClock; import org.droiddraw.widget.AutoCompleteTextView; import org.droiddraw.widget.Button; import org.droiddraw.widget.CheckBox; import org.droiddraw.widget.DatePicker; import org.droiddraw.widget.DigitalClock; import org.droiddraw.widget.EditView; import org.droiddraw.widget.FrameLayout; import org.droiddraw.widget.Gallery; import org.droiddraw.widget.GridView; import org.droiddraw.widget.ImageButton; import org.droiddraw.widget.ImageSwitcher; import org.droiddraw.widget.ImageView; import org.droiddraw.widget.Layout; import org.droiddraw.widget.LinearLayout; import org.droiddraw.widget.ListView; import org.droiddraw.widget.ProgressBar; import org.droiddraw.widget.RadioButton; import org.droiddraw.widget.RadioGroup; import org.droiddraw.widget.RelativeLayout; import org.droiddraw.widget.ScrollView; import org.droiddraw.widget.Spinner; import org.droiddraw.widget.TableLayout; import org.droiddraw.widget.TableRow; import org.droiddraw.widget.TextView; import org.droiddraw.widget.Ticker; import org.droiddraw.widget.TimePicker; import org.droiddraw.widget.Widget; import java.awt.Component; import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.Vector; import javax.swing.JComboBox; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; public class ViewerListener implements MouseListener, MouseMotionListener, KeyListener { int off_x, off_y; int sx, sy; int grid_x = 10; int grid_y = 10; boolean select; boolean shift; int mode; private static final int NORMAL = 0; private static final int E = 1; private static final int SE = 2; private static final int S = 3; Viewer viewer; AndroidEditor app; JComboBox widgetType = new JComboBox(new String[] {"AnalogClock","AutoCompleteTextView", "Button", "CheckBox", "DigitalClock","EditText", "ImageButton", "ImageView", "ListView", "ProgressBar", "RadioButton","RadioGroup", "Spinner", "TableRow", "TextView", "TimePicker", "AbsoluteLayout", "LinearLayout", "RelativeLayout", "TableLayout", "Ticker"}); DroidDrawPanel ddp; private boolean dragging; public ViewerListener(AndroidEditor app, DroidDrawPanel ddp, Viewer viewer) { this.ddp = ddp; this.app = app; this.viewer = viewer; if (!System.getProperty("os.name").toLowerCase().contains("mac os x")) widgetType.setLightWeightPopupEnabled(false); } public Component getWidgetSelector() { return widgetType; } public Widget createWidget() { String str = (String)widgetType.getSelectedItem(); return createWidget(str); } public static Widget createWidget(String str) { if (str.equals("Button")) return new Button("Button"); else if (str.equals("CheckBox")) return new CheckBox("CheckBox"); else if (str.equals("EditText")) return new EditView("EditText"); else if (str.equals("TextView")) return new TextView("TextView"); else if (str.equals("AnalogClock")) return new AnalogClock(); else if (str.equals("DigitalClock")) return new DigitalClock(); else if (str.equals("ProgressBar")) return new ProgressBar(); else if (str.equals("LinearLayout")) return new LinearLayout(); else if (str.equals("AbsoluteLayout")) return new AbsoluteLayout(); else if (str.equals("RelativeLayout")) return new RelativeLayout(); else if (str.equals("RadioButton")) return new RadioButton("RadioButton"); else if (str.equals("RadioGroup")) return new RadioGroup(); else if (str.equals("TimePicker")) return new TimePicker(); else if (str.equals("ListView")) return new ListView(); else if (str.equals("Ticker")) return new Ticker(); else if (str.equals("Spinner")) return new Spinner(); else if (str.equals("ImageView")) return new ImageView(); else if (str.equals("ImageButton")) return new ImageButton(); else if (str.equals("AutoCompleteTextView")) return new AutoCompleteTextView("AutoComplete"); else if (str.equals("TableRow")) return new TableRow(); else if (str.equals("TableLayout")) return new TableLayout(); else if (str.equals("FrameLayout")) return new FrameLayout(); else if (str.equals("ScrollView")) return new ScrollView(); else if (str.equals("GridView")) return new GridView(); else if (str.equals("Gallery")) return new Gallery(); else if (str.equals("DatePicker")) return new DatePicker(); else if (str.equals("ImageSwitcher")) return new ImageSwitcher(); else return null; } public void mouseEntered(MouseEvent arg0) { } public void mouseExited(MouseEvent arg0) { } public void mouseClicked(MouseEvent e) { final int x = e.getX()-viewer.getOffX(); final int y = e.getY()-viewer.getOffY(); final MouseEvent ev = e; if (select) { final Vector<Widget> ws = app.findWidgets(x, y); Widget w = null; if (ws.contains(app.getSelected())) { w = app.getSelected(); } else { switch (ws.size()) { case 0: break; case 1: w = ws.get(0); break; default: if (e.isControlDown() || e.getButton() == MouseEvent.BUTTON3) { JPopupMenu menu = new JPopupMenu(); JMenuItem it = new JMenuItem("Select a widget:"); it.setEnabled(false); menu.add(it); menu.addSeparator(); for (int i=0;i<ws.size();i++) { it = new JMenuItem(ws.get(i).getTagName()); final int id = i; it.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { doSelect(ws.get(id), ev.getClickCount(), x, y); } }); menu.add(it); } menu.show(viewer, x, y); } else { w = ws.get(0); } } } doSelect(w, e.getClickCount(), x, y); } else { //Widget w = createWidget(); //addWidget(w, x, y); } } protected void doSelect(Widget w, int clickCount, int x, int y) { if (clickCount > 1) { if (w != null) { if (w != app.getSelected()) { app.select(w); } ddp.editSelected(); } } else if (mode == NORMAL ){ if (w != null) { off_x = (w.getParent()!=null?w.getParent().getScreenX():0)+w.getX()-x; off_y = (w.getParent()!=null?w.getParent().getScreenY():0)+w.getY()-y; } app.select(w); viewer.requestFocus(); viewer.repaint(); } } public void addWidget(Widget ww, int xx, int yy) { final int x = xx; final int y = yy; final Widget w = ww; final Vector<Layout> ls = app.findLayouts(x, y); Layout l = null; switch (ls.size()) { case 0: return; case 1: l = ls.get(0); break; default: JPopupMenu menu = new JPopupMenu(); JMenuItem it = new JMenuItem("Select a layout:"); it.setEnabled(false); menu.add(it); menu.addSeparator(); for (int i=0;i<ls.size();i++) { it = new JMenuItem(ls.get(i).getTagName()); final int id = i; it.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { addWidget(w, ls.get(id), x, y); } }); menu.add(it); } menu.show(viewer, x, y); } if (l != null) { addWidget(w, l, x, y); } } protected void addWidget(Widget w, Layout l, int x, int y) { boolean prefersGrid = AndroidEditor.instance().getPreferences().getSnap(); if (l instanceof AbsoluteLayout && ((shift && !prefersGrid) || (!shift && prefersGrid))) w.setPosition((x/grid_x)*grid_x-l.getScreenX(), (y/grid_y)*grid_y-l.getScreenY()); else w.setPosition(x-l.getScreenX(), y-l.getScreenY()); l.addWidget(w); AndroidEditor.instance().queueUndoRecord(new WidgetAddRecord(l, w)); l.apply(); app.select(w); select = true; viewer.requestFocus(); viewer.repaint(); } public void mouseReleased(MouseEvent e) { dragging = false; e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); Widget w = app.getSelected(); if (w != null) { int nx = w.getX(); int ny = w.getY(); if (nx != sx || ny != sy) { app.queueUndoRecord(new MoveRecord(sx, sy, nx, ny, w)); } } } public void mouseDragged(MouseEvent e) { int x = e.getX()-viewer.getOffX(); int y = e.getY()-viewer.getOffY(); if (x < 0) { x = 0; } if (y < 0) { y = 0; } if (x > app.getScreenX()) x = app.getScreenX(); if (y > app.getScreenY()) y = app.getScreenY(); Widget selected = app.getSelected(); Vector<Widget> ws = app.findWidgets(x, y); if (!dragging) { if (!ws.contains(selected)) { if (ws.size() > 0) { app.select(ws.get(0)); selected = app.getSelected(); Widget w = selected; off_x = (w.getParent()!=null?w.getParent().getScreenX():0)+w.getX()-x; off_y = (w.getParent()!=null?w.getParent().getScreenY():0)+w.getY()-y; } else { app.select(null); return; } } } dragging = true; if (selected != null) { Layout l = selected.getParent(); Vector<Layout> ls = app.findLayouts(x, y); if (ls.size() > 0) { int ix = 0; do { l = ls.get(ix++); } while (l.equals(selected) && ix < ls.size()); } else l = (selected.getParent()); if (l != selected.getParent()) { if (!(selected instanceof Layout) || !((Layout)selected).containsWidget(l)){ (selected.getParent()).removeWidget(selected); l.addWidget(selected); } else { l = selected.getParent(); } } if (mode == NORMAL) { e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); int nx = (x+off_x); int ny = (y+off_y); boolean prefersGrid = AndroidEditor.instance().getPreferences().getSnap(); if (l instanceof AbsoluteLayout && ((shift && !prefersGrid) || (!shift && prefersGrid))) { nx = nx/grid_x*grid_x; ny = ny/grid_y*grid_y; } selected.setPosition(nx-l.getScreenX(),ny-l.getScreenY()); } else if (mode == E) { Widget w = AndroidEditor.instance().getSelected(); w.setWidth(x-(l.getScreenX()+w.getX())); } else if (mode == SE) { Widget wd = AndroidEditor.instance().getSelected(); int w = x-(l.getScreenX()+wd.getX()); int h = y-(l.getScreenY()+wd.getY()); if (shift) { if (w > h) h = w; else w = h; } wd.setSize(w,h); } else if (mode == S) { Widget w = AndroidEditor.instance().getSelected(); w.setHeight(y-(l.getScreenY()+w.getY())); } l.positionWidget(selected); l.apply(); viewer.repaint(); } } public void mouseMoved(MouseEvent ev) { int ex = ev.getX(); int ey = ev.getY(); Widget selected = AndroidEditor.instance().getSelected(); mode = 0; Cursor c = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); if (selected != null) { int x = selected.getParent().getScreenX()+selected.getX()+viewer.getOffX(); int y = selected.getParent().getScreenY()+selected.getY()+viewer.getOffY(); boolean close_r = Math.abs(ex-(x+selected.getWidth())) < 5 && ey > y && ey < y+selected.getHeight(); boolean close_b = Math.abs(ey-(y+selected.getHeight())) < 5 && ex > x && ex < x+selected.getWidth(); if (close_r) { if (close_b) { c = Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR); mode = SE; } else { c = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); mode = E; } } else if (close_b) { c = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR); mode = S; } } ev.getComponent().setCursor(c); } public void keyPressed(KeyEvent ev) { switch (ev.getKeyCode()) { case KeyEvent.VK_SHIFT: shift = true; break; case KeyEvent.VK_DELETE: case KeyEvent.VK_BACK_SPACE: Widget w = app.getSelected(); if (w != null) { Layout l = w.getParent(); app.removeWidget(app.getSelected()); app.queueUndoRecord(new WidgetDeleteRecord(l, w)); viewer.repaint(); } break; } Widget w = app.getSelected(); if (w != null && w.getParent() instanceof AbsoluteLayout) { int dx = 0; int dy = 0; switch (ev.getKeyCode()) { case KeyEvent.VK_UP: dy = -1; break; case KeyEvent.VK_DOWN: dy = 1; break; case KeyEvent.VK_LEFT: dx = -1; break; case KeyEvent.VK_RIGHT: dx = 1; break; } if (dx != 0 || dy != 0) { int sx = w.getX(); int sy = w.getY(); w.move(dx, dy); app.queueUndoRecord(new MoveRecord(sx, sy, sx+dx, sy+dy, w)); } } } public void keyReleased(KeyEvent ev) { switch (ev.getKeyCode()) { case KeyEvent.VK_SHIFT: shift = false; break; } } public void keyTyped(KeyEvent ev) { } public void mousePressed(MouseEvent e) { Widget w = app.getSelected(); if (w != null) { int x = e.getX()-viewer.getOffX(); int y = e.getY()-viewer.getOffY(); sx = w.getX(); sy = w.getY(); off_x = (w.getParent()!=null?w.getParent().getScreenX():0)+w.getX()-x; off_y = (w.getParent()!=null?w.getParent().getScreenY():0)+w.getY()-y; } } }