/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fib.editor.controller;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import org.openflexo.fib.FIBLibrary;
import org.openflexo.fib.controller.FIBController;
import org.openflexo.fib.controller.FIBViewFactory;
import org.openflexo.fib.editor.FIBAbstractEditor;
import org.openflexo.fib.editor.FIBGenericEditor;
import org.openflexo.fib.editor.notifications.FocusedObjectChange;
import org.openflexo.fib.editor.notifications.SelectedObjectChange;
import org.openflexo.fib.editor.view.FIBEditableView;
import org.openflexo.fib.editor.view.FIBEditableViewDelegate;
import org.openflexo.fib.editor.view.PlaceHolder;
import org.openflexo.fib.editor.view.container.FIBEditablePanelView;
import org.openflexo.fib.editor.view.container.FIBEditableSplitPanelView;
import org.openflexo.fib.editor.view.container.FIBEditableTabPanelView;
import org.openflexo.fib.editor.view.container.FIBEditableTabView;
import org.openflexo.fib.editor.view.widget.FIBEditableBrowserWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableButtonWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableCheckboxListWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableCheckboxWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableColorWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableCustomWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableDropDownWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableEditorPaneWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableFileWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableFontWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableHtmlEditorWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableImageWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableLabelWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableListWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableNumberWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableRadioButtonListWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableTableWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableTextAreaWidget;
import org.openflexo.fib.editor.view.widget.FIBEditableTextFieldWidget;
import org.openflexo.fib.model.FIBBrowser;
import org.openflexo.fib.model.FIBButton;
import org.openflexo.fib.model.FIBCheckBox;
import org.openflexo.fib.model.FIBCheckboxList;
import org.openflexo.fib.model.FIBColor;
import org.openflexo.fib.model.FIBComponent;
import org.openflexo.fib.model.FIBContainer;
import org.openflexo.fib.model.FIBCustom;
import org.openflexo.fib.model.FIBDropDown;
import org.openflexo.fib.model.FIBEditorPane;
import org.openflexo.fib.model.FIBFile;
import org.openflexo.fib.model.FIBFont;
import org.openflexo.fib.model.FIBHtmlEditor;
import org.openflexo.fib.model.FIBImage;
import org.openflexo.fib.model.FIBLabel;
import org.openflexo.fib.model.FIBList;
import org.openflexo.fib.model.FIBNumber;
import org.openflexo.fib.model.FIBPanel;
import org.openflexo.fib.model.FIBRadioButtonList;
import org.openflexo.fib.model.FIBSplitPanel;
import org.openflexo.fib.model.FIBTab;
import org.openflexo.fib.model.FIBTabPanel;
import org.openflexo.fib.model.FIBTable;
import org.openflexo.fib.model.FIBTextArea;
import org.openflexo.fib.model.FIBTextField;
import org.openflexo.fib.model.FIBTextPane;
import org.openflexo.fib.model.FIBWidget;
import org.openflexo.fib.view.FIBView;
import org.openflexo.fib.view.FIBWidgetView;
import org.openflexo.localization.Language;
import org.openflexo.logging.FlexoLogger;
import org.openflexo.swing.NoInsetsBorder;
import org.openflexo.toolbox.FileResource;
public class FIBEditorController /*extends FIBController*/extends Observable {
private static final Logger logger = FlexoLogger.getLogger(FIBEditorController.class.getPackage().getName());
private final FIBController controller;
public static File BROWSER_FIB = new FileResource("Fib/Browser.fib");
private final JPanel editorPanel;
private final FIBView<?, ?> fibPanel;
private final FIBGenericEditor editor;
private FIBComponent selectedObject = null;
private FIBComponent focusedObject = null;
private ContextualMenu contextualMenu;
private FIBBrowserController browserController;
private static final Border FOCUSED_BORDER = new NoInsetsBorder(BorderFactory.createLineBorder(Color.RED));
private static final Border SELECTED_BORDER = new NoInsetsBorder(BorderFactory.createLineBorder(Color.BLUE));
private Map<FIBComponent, FIBEditableViewDelegate<?, ?>> viewDelegates;
private class FibWrappingPanel extends JPanel {
public FibWrappingPanel(JComponent wrappedFib) {
super(new BorderLayout());
add(wrappedFib);
}
@Override
public void paint(Graphics g) {
super.paint(g);
paintFocusedAndSelected(g);
}
private void paintFocusedAndSelected(Graphics g) {
FIBEditableViewDelegate<?, ?> focused = viewDelegates.get(getFocusedObject());
FIBEditableViewDelegate<?, ?> selected = viewDelegates.get(getSelectedObject());
if (focused != null && focused != selected) {
Point origin = SwingUtilities.convertPoint(focused.getJComponent(), new Point(), this);
Graphics componentGraphics = g.create(origin.x, origin.y, focused.getJComponent().getWidth(), focused.getJComponent()
.getHeight());
FOCUSED_BORDER.paintBorder(focused.getJComponent(), componentGraphics, 0, 0, focused.getJComponent().getWidth(), focused
.getJComponent().getHeight());
componentGraphics.dispose();
}
if (selected != null) {
Point origin = SwingUtilities.convertPoint(selected.getJComponent(), new Point(), this);
Graphics componentGraphics = g.create(origin.x, origin.y, selected.getJComponent().getWidth(), selected.getJComponent()
.getHeight());
SELECTED_BORDER.paintBorder(selected.getJComponent(), componentGraphics, 0, 0, selected.getJComponent().getWidth(),
selected.getJComponent().getHeight());
componentGraphics.dispose();
}
}
}
public FIBEditorController(FIBComponent fibComponent, FIBGenericEditor editor) {
this(fibComponent, editor, null);
// Class testClass = null;
boolean instantiable = fibComponent.getDataClass() != null && !Modifier.isAbstract(fibComponent.getDataClass().getModifiers());
if (instantiable) {
try {
instantiable = fibComponent.getDataClass().getConstructor(new Class[0]) != null;
} catch (SecurityException e) {
instantiable = false;
} catch (NoSuchMethodException e) {
instantiable = false;
}
}
if (instantiable) {
try {
// testClass = Class.forName(fibComponent.getDataClassName());
Object testData = fibComponent.getDataClass().newInstance();
fibPanel.getController().setDataObject(testData);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
fibPanel.getController().updateWithoutDataObject();
}
}
public FIBEditorController(FIBComponent fibComponent, FIBGenericEditor editor, Object dataObject) {
this(fibComponent, editor, dataObject, FIBController.instanciateController(fibComponent, FIBAbstractEditor.LOCALIZATION));
}
public FIBEditorController(FIBComponent fibComponent, FIBGenericEditor editor, Object dataObject, FIBController controller) {
this.controller = controller;
viewDelegates = new HashMap<FIBComponent, FIBEditableViewDelegate<?, ?>>();
controller.setViewFactory(new EditorFIBViewFactory());
this.editor = editor;
contextualMenu = new ContextualMenu(this);
addObserver(editor.getInspector());
editorPanel = new JPanel(new BorderLayout());
FIBComponent browserComponent = FIBLibrary.instance().retrieveFIBComponent(BROWSER_FIB, false);
browserController = new FIBBrowserController(browserComponent, this);
FIBView<?, ?> view = FIBController.makeView(browserComponent, browserController);
view.getController().setDataObject(fibComponent);
fibPanel = controller.buildView();
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, view.getResultingJComponent(), new FibWrappingPanel(
fibPanel.getResultingJComponent())/*new JScrollPane(fibPanel.getJComponent())*/);
editorPanel.add(splitPane, BorderLayout.CENTER);
if (dataObject != null) {
fibPanel.getController().setDataObject(dataObject, true);
} else {
fibPanel.getController().updateWithoutDataObject();
}
}
public Object getDataObject() {
return controller.getDataObject();
}
public void setDataObject(Object anObject) {
controller.setDataObject(anObject);
}
public FIBController getController() {
return controller;
}
public FIBGenericEditor getEditor() {
return editor;
}
public JPanel getEditorPanel() {
return editorPanel;
}
public ContextualMenu getContextualMenu() {
return contextualMenu;
}
public FIBEditorPalette getPalette() {
return editor.getPalette();
}
public FIBView<?, ?> getFibPanel() {
return fibPanel;
}
public FIBComponent getFocusedObject() {
return focusedObject;
}
public void setFocusedObject(FIBComponent aComponent) {
if (aComponent != focusedObject) {
// System.out.println("setFocusedObject with "+aComponent);
FocusedObjectChange change = new FocusedObjectChange(focusedObject, aComponent);
focusedObject = aComponent;
setChanged();
notifyObservers(change);
editorPanel.repaint();
}
}
public FIBComponent getSelectedObject() {
return selectedObject;
}
public void setSelectedObject(FIBComponent aComponent) {
// logger.info("setSelectedObject "+aComponent);
if (aComponent != selectedObject) {
SelectedObjectChange change = new SelectedObjectChange(selectedObject, aComponent);
selectedObject = aComponent;
setChanged();
notifyObservers(change);
editorPanel.repaint();
}
// System.out.println("set selected: "+selectedObject);
/*if (selectedObject != null) {
fibPanel.getController().viewForComponent(selectedObject).getJComponent().setBorder(oldBorder);
}
if (aComponent != null) {
selectedObject = aComponent;
oldBorder = fibPanel.getController().viewForComponent(aComponent).getJComponent().getBorder();
fibPanel.getController().viewForComponent(aComponent).getJComponent().setBorder(BorderFactory.createLineBorder(Color.BLUE));
editor.getInspector().inspectObject(aComponent);
}
else {
editor.getInspector().inspectObject(null);
}*/
}
public void notifyFocusedAndSelectedObject() {
FocusedObjectChange change1 = new FocusedObjectChange(focusedObject, focusedObject);
setChanged();
notifyObservers(change1);
SelectedObjectChange change2 = new SelectedObjectChange(selectedObject, selectedObject);
setChanged();
notifyObservers(change2);
}
public FIBView<?, ?> viewForComponent(FIBComponent component) {
return controller.viewForComponent(component);
}
/*public void keyTyped(KeyEvent e)
{
logger.fine("keyTyped() "+e);
if (e.getKeyChar() == KeyEvent.VK_DELETE || e.getKeyChar() == KeyEvent.VK_BACK_SPACE) {
if (getSelectedObject() != null) {
boolean deleteIt = JOptionPane.showConfirmDialog(editor.getFrame(),
getSelectedObject()+": really delete this component (undoable operation) ?", "information",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.YES_OPTION;
if (deleteIt) {
logger.info("Removing object "+getSelectedObject());
getSelectedObject().delete();
}
}
}
}*/
public void switchToLanguage(Language language) {
controller.switchToLanguage(language);
}
public void registerViewDelegate(FIBEditableViewDelegate<?, ?> delegate) {
viewDelegates.put(delegate.getFIBComponent(), delegate);
}
public void unregisterViewDelegate(FIBEditableViewDelegate<?, ?> delegate) {
if (viewDelegates.get(delegate.getFIBComponent()) == delegate) {
viewDelegates.remove(delegate.getFIBComponent());
}
}
protected class EditorFIBViewFactory implements FIBViewFactory {
@Override
public FIBView<?, ?> makeContainer(FIBContainer fibContainer) {
if (fibContainer instanceof FIBTab) {
return new FIBEditableTabView((FIBTab) fibContainer, FIBEditorController.this);
} else if (fibContainer instanceof FIBPanel) {
return new FIBEditablePanelView((FIBPanel) fibContainer, FIBEditorController.this);
} else if (fibContainer instanceof FIBTabPanel) {
return new FIBEditableTabPanelView((FIBTabPanel) fibContainer, FIBEditorController.this);
} else if (fibContainer instanceof FIBSplitPanel) {
return new FIBEditableSplitPanelView((FIBSplitPanel) fibContainer, FIBEditorController.this);
}
return null;
}
@Override
public FIBWidgetView<?, ?, ?> makeWidget(FIBWidget fibWidget) {
if (fibWidget instanceof FIBTextField) {
return new FIBEditableTextFieldWidget((FIBTextField) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBTextArea) {
return new FIBEditableTextAreaWidget((FIBTextArea) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBHtmlEditor) {
return new FIBEditableHtmlEditorWidget((FIBHtmlEditor) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBLabel) {
return new FIBEditableLabelWidget((FIBLabel) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBImage) {
return new FIBEditableImageWidget((FIBImage) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBCheckBox) {
return new FIBEditableCheckboxWidget((FIBCheckBox) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBTable) {
return new FIBEditableTableWidget((FIBTable) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBBrowser) {
return new FIBEditableBrowserWidget((FIBBrowser) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBDropDown) {
return new FIBEditableDropDownWidget((FIBDropDown) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBRadioButtonList) {
return new FIBEditableRadioButtonListWidget((FIBRadioButtonList) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBCheckboxList) {
return new FIBEditableCheckboxListWidget((FIBCheckboxList) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBList) {
return new FIBEditableListWidget((FIBList) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBNumber) {
FIBNumber w = (FIBNumber) fibWidget;
switch (w.getNumberType()) {
case ByteType:
return new FIBEditableNumberWidget.FIBEditableByteWidget(w, FIBEditorController.this);
case ShortType:
return new FIBEditableNumberWidget.FIBEditableShortWidget(w, FIBEditorController.this);
case IntegerType:
return new FIBEditableNumberWidget.FIBEditableIntegerWidget(w, FIBEditorController.this);
case LongType:
return new FIBEditableNumberWidget.FIBEditableLongWidget(w, FIBEditorController.this);
case FloatType:
return new FIBEditableNumberWidget.FIBEditableFloatWidget(w, FIBEditorController.this);
case DoubleType:
return new FIBEditableNumberWidget.FIBEditableDoubleWidget(w, FIBEditorController.this);
default:
break;
}
}
if (fibWidget instanceof FIBColor) {
return new FIBEditableColorWidget((FIBColor) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBFont) {
return new FIBEditableFontWidget((FIBFont) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBFile) {
return new FIBEditableFileWidget((FIBFile) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBButton) {
return new FIBEditableButtonWidget((FIBButton) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBCustom) {
return new FIBEditableCustomWidget((FIBCustom) fibWidget, FIBEditorController.this);
}
if (fibWidget instanceof FIBTextPane) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Can't handle editable FIBTextPane!");
}
}
if (fibWidget instanceof FIBEditorPane) {
return new FIBEditableEditorPaneWidget((FIBEditorPane) fibWidget, FIBEditorController.this);
}
return null;
}
}
public DropListener buildPaletteDropListener(FIBEditableView<?, ?> editableView, PlaceHolder placeHolder) {
return new DropListener(editableView, placeHolder);
}
}