/** * */ package org.korsakow.ide.ui.interfacebuilder; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.border.Border; import javax.swing.border.LineBorder; import javax.swing.event.MouseInputAdapter; import org.korsakow.domain.interf.IImage; import org.korsakow.ide.resources.media.MediaFactory; import org.korsakow.ide.resources.widget.WidgetComponent; import org.korsakow.ide.resources.widget.WidgetModel; import org.korsakow.ide.util.UIUtil; public class WidgetCanvas extends JPanel { private JPanel contentPanel; private GridPanel gridPanel; private JComponent dragLayer; private JPanel backgroundLayer; private JPanel stageLayer; private JLayeredPane widgetLayer; private Border myDefaultBorder; private WidgetCanvasModel model; public WidgetCanvas() { setModel(new WidgetCanvasModel()); initUI(); initListeners(); } public void setModel(final WidgetCanvasModel model) { this.model = model; model.addListener(new WidgetCanvasModelAdapter() { @Override public void widgetAdded(WidgetModel widget) { add(widget.getComponent()); } @Override public void widgetRemoved(WidgetModel widget) { remove(widget.getComponent()); } @Override public void widgetsDepthChanged() { widgetLayer.removeAll(); int i = 0; for (WidgetModel widgetModel : model.getWidgets()) { final int index = ++i; widgetLayer.add(widgetModel.getComponent(), new Integer(index)); } repaint(); } @Override public void selectionChanged(Collection<WidgetModel> oldSelection, Collection<WidgetModel> newSelection) { } }); } public WidgetCanvasModel getModel() { return model; } public WidgetCanvasModel getSelectionModel() { return model; } /** * Overridden because we have some components placed outside our bounds. */ @Override public Dimension getPreferredSize() { if (isPreferredSizeSet()) { return super.getPreferredSize(); } return new Dimension(model.getStageWidth(), model.getStageHeight()); } public void add(WidgetComponent widget) { widgetLayer.add(widget, new Integer(widgetLayer.highestLayer()+1)); widget.setBorder(myDefaultBorder); // setLocation(widget, widget.getLocation()); repaint(); widget.repaint(); widget.revalidate(); //widget.addMouseListener(new WidgetDragger(widget, this)); } public void remove(WidgetComponent widget) { widgetLayer.remove(widget); repaint(); } public List<WidgetComponent> getWidgetComponents() { List<WidgetComponent> widgetComponents = new ArrayList<WidgetComponent>(); for (WidgetModel widget : getModel().getWidgets()) widgetComponents.add(widget.getComponent()); return widgetComponents; } public JComponent getDragLayer() { return dragLayer; } @Override public void doLayout() { super.doLayout(); contentPanel.setSize(model.getStageWidth(), model.getStageHeight()); contentPanel.setLocation(0, 0); gridPanel.setSize(model.getStageWidth(), model.getStageHeight()); gridPanel.setOffset( model.getGridWidth()!=0?(model.getMovieOffsetX() % model.getGridWidth()):0, model.getGridHeight()!=0?(model.getMovieOffsetY() % model.getGridHeight()):0 ); //model.getMovieOffsetX(), // model.getMovieOffsetY()); //model.getGridWidth()!=0?(model.getMovieOffsetX() % model.getGridWidth()):0 widgetLayer.setSize(model.getStageWidth(), model.getStageHeight()); widgetLayer.setLocation( 0, 0 // model.getGridWidth()!=0?(model.getMovieOffsetX() % model.getGridWidth()):0, // model.getGridHeight()!=0?(model.getMovieOffsetY() % model.getGridHeight()):0 ); dragLayer.setSize(model.getStageWidth(), model.getStageHeight()); stageLayer.setLocation( model.getMovieOffsetX(), model.getMovieOffsetY()); stageLayer.setSize(model.getMovieWidth(), model.getMovieHeight()); backgroundLayer.setSize(stageLayer.getWidth(), stageLayer.getHeight()); backgroundLayer.setLocation(model.getMovieOffsetX(), model.getMovieOffsetY()); } public Collection<WidgetComponent> getSelectedWidgetComponents() { List<WidgetComponent> selectedWidgets = new ArrayList<WidgetComponent>(); for (WidgetModel widget : getSelectionModel().getSelectedWidgets()) selectedWidgets.add(widget.getComponent()); return selectedWidgets; } private void initUI() { contentPanel = new JPanel(null); // setFocusable(true); contentPanel.setLayout(null); contentPanel.setOpaque(true); contentPanel.setBackground(Color.LIGHT_GRAY); add(contentPanel); myDefaultBorder = new LineBorder(Color.black, 1); backgroundLayer = new JPanel(); backgroundLayer.setOpaque(true); backgroundLayer.setBackground(null); contentPanel.add(backgroundLayer, 0); stageLayer = new JPanel(); stageLayer.setOpaque(false); stageLayer.setBorder(BorderFactory.createLineBorder(Color.GRAY, 2)); contentPanel.add(stageLayer, 0); gridPanel = new GridPanel(); gridPanel.setGridSize(20, 20); gridPanel.setOpaque(false); gridPanel.setBackground(null); contentPanel.add(gridPanel, 0); widgetLayer = new JLayeredPane(); // widgetLayer.setFocusable(true); widgetLayer.setOpaque(false); widgetLayer.setBackground(null); widgetLayer.setCursor(Cursor.getDefaultCursor()); // resize border doesn't properly release cursor. widgetLayer.addMouseListener(new ClearSelectionMouseListener()); contentPanel.add(widgetLayer, 0); dragLayer = new JPanel(null); dragLayer.setVisible(false); dragLayer.setOpaque(false); dragLayer.setBackground(null); contentPanel.add(dragLayer, 0); } private void initListeners() { addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent event) { requestFocus(); } }); } public void setGridSize(int width, int height) { gridPanel.setGridSize(width, height); gridPanel.revalidate(); repaint(); } public void setShowBackground(boolean show) { backgroundLayer.setVisible(show); } public void setBackgroundColor(Color c) { backgroundLayer.setBackground(c); backgroundLayer.validate(); // the image may not appear without this; // we call validate instead of revalidate because of timing issues (there are already plenty) with the subsequent repaint UIUtil.runUITaskLater(new Runnable() { // doesn't work if we don't wait until "later" public void run() { repaint(); // the image may, strangely, appear in front of other UI elements without this } }); } public void setBackgroundImage(IImage image) { backgroundLayer.removeAll(); if (image != null) backgroundLayer.add(MediaFactory.getMediaNoThrow(image).getComponent()); backgroundLayer.validate(); // the image may not appear without this; // we call validate instead of revalidate because of timing issues (there are already plenty) with the subsequent repaint UIUtil.runUITaskLater(new Runnable() { // doesn't work if we don't wait until "later" public void run() { repaint(); // the image may, strangely, appear in front of other UI elements without this } }); } private class ClearSelectionMouseListener extends MouseInputAdapter { @Override public void mouseClicked(MouseEvent me) { getModel().clearSelection(); } } public Border getDefaultBorder() { return myDefaultBorder; } }