package org.concord.otrunk.overlay; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.io.File; import java.util.HashMap; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTabbedPane; import org.concord.framework.otrunk.OTObject; import org.concord.framework.otrunk.OTrunk; import org.concord.otrunk.OTObjectServiceImpl; import org.concord.otrunk.OTrunkImpl; import org.concord.otrunk.user.OTUserObject; import org.concord.otrunk.view.AbstractOTJComponentContainerView; import org.concord.swing.MostRecentFileDialog; public class OTOverlaySwitcherAuthorView extends AbstractOTJComponentContainerView { private Logger logger = Logger.getLogger(this.getClass().getName()); private static final int SAVE = 0; private static final int OPEN = 1; private OTOverlaySwitcher otSwitcher; private OTObject activityRoot; private HashMap<String, OTUserObject> overlayToUserObjectMap = new HashMap<String, OTUserObject>(); private JTabbedPane tabbedPane; private OTrunkImpl otrunk; private OTObjectServiceImpl rootObjectService; private JPanel mainPanel; private OTUserOverlayManager overlayManager; public JComponent getComponent(OTObject otObject) { otSwitcher = (OTOverlaySwitcher) otObject; activityRoot = otSwitcher.getActivityRoot(); rootObjectService = (OTObjectServiceImpl) otSwitcher.getOTObjectService(); otrunk = (OTrunkImpl) rootObjectService.getOTrunkService(OTrunk.class); overlayManager = viewContext.getViewService(OTUserOverlayManager.class); if (overlayManager == null) { overlayManager = new OTUserSingleOverlayManager(otrunk); viewContext.addViewService(OTUserOverlayManager.class, overlayManager); } // create a tabbed pane, one tab per overlay plus a main tab for the root authored content tabbedPane = new JTabbedPane(); tabbedPane.addTab("Root", createOverlaySubView(null)); mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); // mainPanel.add(menubar, BorderLayout.NORTH); mainPanel.add(tabbedPane, BorderLayout.CENTER); // set up menu items to add, remove and save overlays mainPanel.addComponentListener(new ComponentListener() { boolean hasRun = false; public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } public void componentResized(ComponentEvent e) { if (! hasRun) { createMenuBar(); hasRun = true; } } }); return mainPanel; } private void registerOverlay(String title, OTUserObject userObj) { overlayToUserObjectMap.put(title, userObj); } private JComponent createOverlaySubView(OTUserObject user) { try { // get overlay version of the authoredRoot object OTObject overlayObject = overlayManager.getOTObject(user, activityRoot); // get subview component JComponent subComponent = createSubViewComponent(overlayObject); return subComponent; } catch (Exception e) { e.printStackTrace(); } return null; } private OTUserObject getCurrentUserObject() { String title = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex()); return overlayToUserObjectMap.get(title); } private void removeCurrentOverlay() { tabbedPane.remove(tabbedPane.getSelectedComponent()); } private String askForName() { String name = JOptionPane.showInputDialog(mainPanel, "Please enter a name for this overlay:", "Name your overlay", JOptionPane.QUESTION_MESSAGE); name = verifyNameAvailability(name); return name; } private void addOverlay(File f) throws Exception { String name = askForName(); if (name == null || name.length() == 0) { name = verifyNameAvailability("Untitled"); } OTUserObject userObj = rootObjectService.createObject(OTUserObject.class); overlayManager.addWriteable(f.toURI().toURL(), userObj, false); userObj.setName(name); Component comp = createOverlaySubView(userObj); tabbedPane.addTab(name, comp); tabbedPane.setSelectedComponent(comp); registerOverlay(name, userObj); } private String verifyNameAvailability(String name) { String origName = name; int i = 1; while (overlayToUserObjectMap.containsKey(name)) { name = origName + " (" + i++ + ")"; } return name; } private void newOverlay() { logger.info("New overlay"); try { File f = askForFile(SAVE); if (f != null) { addOverlay(f); } } catch (Exception e) { e.printStackTrace(); } } private void openOverlay() { try { File f = askForFile(OPEN); if (f != null) { addOverlay(f); } } catch (Exception e) { e.printStackTrace(); } } private void saveCurrentOverlay() { OTUserObject currentUser = getCurrentUserObject(); if (currentUser == null) { return; } logger.info("Save overlay"); try { overlayManager.remoteSave(currentUser, activityRoot); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private File askForFile(int style) { MostRecentFileDialog mrfd = new MostRecentFileDialog("org.concord.otviewer.openotml"); mrfd.setFilenameFilter("otml"); int retval = MostRecentFileDialog.CANCEL_OPTION; if (style == OPEN) { retval = mrfd.showOpenDialog(mainPanel); } else if (style == SAVE) { retval = mrfd.showSaveDialog(mainPanel); } else { return null; } if (retval == MostRecentFileDialog.APPROVE_OPTION) { try { // set the context url File f = mrfd.getSelectedFile(); if (! f.getName().endsWith(".otml")) { f = new File(f.getCanonicalPath() + ".otml"); } return f; } catch (Exception e) { e.printStackTrace(); } } return null; } private void createMenuBar() { // JMenuBar menuBar = new JMenuBar(); JMenuBar menuBar = mainPanel.getRootPane().getJMenuBar(); JMenu overlayMenu = new JMenu("Overlays"); menuBar.add(overlayMenu); Action newMenuItem = new AbstractAction("New Overlay") { public void actionPerformed(ActionEvent e) { newOverlay(); } }; Action openMenuItem = new AbstractAction("Open Existing Overlay") { public void actionPerformed(ActionEvent e) { openOverlay(); } }; Action saveMenuItem = new AbstractAction("Save Current Overlay") { public void actionPerformed(ActionEvent e) { saveCurrentOverlay(); } }; Action deleteMenuItem = new AbstractAction("Delete Current Overlay") { public void actionPerformed(ActionEvent e) { removeCurrentOverlay(); } }; overlayMenu.add(newMenuItem); overlayMenu.add(openMenuItem); overlayMenu.add(saveMenuItem); overlayMenu.add(deleteMenuItem); } }