1. Alex Mair
  2. k5

Commits

Alex Mair  committed a5820e2

UI: Added support for OS X.

  • Participants
  • Parent commits 270e2a7
  • Branches master

Comments (0)

Files changed (5)

File src/ca/usask/cs/giraffe/GiraffeOSX.java

View file
+/* Giraffe.java
+ * Copyright (C) 2012 Alex "HolyCause" Mair (holy.cause@gmail.com)
+ * Copyright (C) 2012 Ivan Vendrov (ivendrov@gmail.com)
+ * Copyright (C) 2012 Joey Eremondi (jse313@mail.usask.ca)
+ * Copyright (C) 2012 Joanne Traves (jet971@mail.usask.ca)
+ * Copyright (C) 2012 Logan Cool (coollogan88@gmail.com)
+ * 
+ * This file is a part of Giraffe.
+ * 
+ * Giraffe 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 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * Giraffe 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 Giraffe.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.usask.cs.giraffe;
+
+import ca.usask.cs.giraffe.ui.OSXManager;
+
+import com.apple.eawt.Application;
+
+/**
+ * Entryway class for OS X. Adds OS X specific features then calls Giraffe's
+ * regular main.
+ */
+public class GiraffeOSX {
+	public static void main(String[] args) {
+		Application app=Application.getApplication();
+		OSXManager handler=OSXManager.getDefaultHandler();
+		app.addAppEventListener(handler);
+		app.setAboutHandler(handler);
+		app.setOpenFileHandler(handler);
+		Giraffe.main(args);
+	}
+}

File src/ca/usask/cs/giraffe/ui/MenuBar.java

View file
 import java.util.EnumSet;
 import java.util.HashMap;
 
+import javax.swing.JFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuBar;
 import javax.swing.JMenuItem;
 import ca.usask.cs.giraffe.UIController;
 import ca.usask.cs.giraffe.core.GiraffeAction;
 import ca.usask.cs.giraffe.core.GiraffeLogger;
+import ca.usask.cs.giraffe.core.OSQualifier;
 
 /**
  * The main menu bar for the GUI
  * <li>Playback (animation/line control)</li>
  * <li>Help (documentation and other metadata)</li>
  * </ul>
- * <p>
- * TODO - platform-specific support. This current menu implementation is in
- * gross violation of OS X user-experience guidelines. (ignoring the fact that
- * this isn't even a OS X-style detached menubar!)
  * 
  * @author Joanne
  * @author Alex Mair (ajm513@mail.usask.ca)
 	protected InputTextArea terminal;
 	
 	/**
+	 * The Window we sent minimise/maximise events to.
+	 */
+	protected JFrame parentWindow;
+	
+	/**
 	 * Assembles a simple menubar.
 	 * <p>
 	 * FIXME - does there exist a simpler design between this object and the
 	 *            The terminal object we poll to ensure they don't have
 	 *            keyboard focus.
 	 */
-	public MenuBar(UIController controller, InputTextArea ita) {
+	public MenuBar(UIController controller, JFrame parentWindow, InputTextArea ita) {
 		this.controller = controller;
+		this.parentWindow=parentWindow;
 		this.terminal = ita;
 		this.listener = new MenuListener();
 		this.menuitem2id = new HashMap<JMenuItem,MenuItemID>();
 		this.actionid2menuid = new HashMap<ActionID,MenuItemID>();
 		
 		this.add(this.createFileMenu());
-		this.add(this.createAboutMenu());
+		JMenu windowMenu=this.createWindowMenu();
+		if (windowMenu!=null)
+			this.add(windowMenu);
+		this.add(this.createHelpMenu());
 		
 		// slight hack alert
 		for (JMenuItem item : this.menuitem2id.keySet())
 		
 		JMenuItem item;
 		
-		item = new JMenuItem("Open");
+		item = new JMenuItem("Open C/C++ Source File...");
 		item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit
 				.getDefaultToolkit().getMenuShortcutKeyMask()));
 		menu.add(item);
 		this.menuitem2id.put(item, MenuItemID.FILE_OPEN);
 		item.addActionListener(this.listener);
 		
+		// Skip rest of menu in OS X - handled in About menu
+		if (OSQualifier.isOSX())
+			return menu;
+		
 		menu.addSeparator();
 		
 		item = new JMenuItem("Quit");
 	}
 	
 	/**
-	 * Helper method: assembles the About menu.
+	 * Helper method: assembles the Window menu <b>on OS X only</b>.
+	 * <p>
+	 * This also registers the relevant menu entries with {@link #menuitem2id}
+	 * @return The menu or NULL if {@code OSQualifiers#isOSX} returns true.
+	 */
+	protected JMenu createWindowMenu() {
+		if (OSQualifier.isOSX()==false)
+			return null;
+		JMenu menu=new JMenu("Window");
+		
+		JMenuItem item;
+		
+		item = new JMenuItem("Minimize");
+		item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, Toolkit
+				.getDefaultToolkit().getMenuShortcutKeyMask()));
+		menu.add(item);
+		this.menuitem2id.put(item, MenuItemID.WINDOW_MINIMISE);
+		item.addActionListener(this.listener);
+		
+		item = new JMenuItem("Zoom");
+		menu.add(item);
+		this.menuitem2id.put(item, MenuItemID.WINDOW_MAXIMISE);
+		item.addActionListener(this.listener);
+		
+		menu.addSeparator();
+		
+		item = new JMenuItem("Bring All to Front");
+		menu.add(item);
+		this.menuitem2id.put(item, MenuItemID.WINDOW_BRINGALLTOFRONT);
+		item.addActionListener(this.listener);
+		
+		return menu;
+	}
+	
+	/**
+	 * Helper method: assembles the Help menu.
 	 * <p>
 	 * This also registers the relevant menu entries with {@link #menuitem2id}
 	 */
-	protected JMenu createAboutMenu() {
-		JMenu menu = new JMenu("About");
+	protected JMenu createHelpMenu() {
+		JMenu menu = new JMenu("Help");
 		
 		JMenuItem item;
 		
-		// TODO - Crossplatform support: OS X calls this ``Help Topics'' I
-		// believe
-		item = new JMenuItem("Help Contents");
-		item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
+		if (OSQualifier.isOSX()) {
+			item = new JMenuItem("Giraffe Help");
+			item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, Toolkit
+					.getDefaultToolkit().getMenuShortcutKeyMask() | KeyEvent.VK_SHIFT));
+			
+		} else {
+			item = new JMenuItem("Help Contents");
+			item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
+		}
 		menu.add(item);
 		this.menuitem2id.put(item, MenuItemID.ABOUT_HELP);
 		item.addActionListener(this.listener);
 		
+		// don't have About Giraffe in help menu - App menu does that.
+		if (OSQualifier.isOSX())
+			return menu;
+		
 		menu.addSeparator();
 		
 		item = new JMenuItem("About Giraffe");
 				case PLAYBACK_DECSPEED:
 					controller.changedSpeedFactor(0);
 					break;
+				case WINDOW_MINIMISE:
+					parentWindow.setState(JFrame.ICONIFIED);
+					break;
+				case WINDOW_MAXIMISE:
+					parentWindow.setState(JFrame.MAXIMIZED_BOTH);
+					break;
+				case WINDOW_BRINGALLTOFRONT:
+					GiraffeLogger.warn("got BRINGALLTOFRONT. ignoring.");
+					break;
 				case ABOUT_HELP:
 					GiraffeLogger
 							.warn("Got ABOUT_HELP - not implemented yet. Ignoring.");
 	
 	/**
 	 * A discrete set of menu item IDs.
+	 * <p>
+	 * The {@code WINDOW_} entries are for OS X only.
 	 * 
 	 * @author Alex Mair (ajm513@mail.usask.ca)
 	 */
 		PLAYBACK_STEPFORWARDS,
 		PLAYBACK_INCSPEED,
 		PLAYBACK_DECSPEED,
+		WINDOW_MINIMISE,
+		WINDOW_MAXIMISE,
+		WINDOW_BRINGALLTOFRONT,
 		ABOUT_HELP,
 		ABOUT_ABOUT;
 	}

File src/ca/usask/cs/giraffe/ui/OSXManager.java

View file
+/* Giraffe.java
+ * Copyright (C) 2012 Alex "HolyCause" Mair (holy.cause@gmail.com)
+ * 
+ * This file is a part of Giraffe.
+ * 
+ * Giraffe 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 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * Giraffe 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 Giraffe.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.usask.cs.giraffe.ui;
+
+import ca.usask.cs.giraffe.core.GiraffeLogger;
+
+import com.apple.eawt.AboutHandler;
+import com.apple.eawt.AppEvent.AboutEvent;
+import com.apple.eawt.AppEvent.AppReOpenedEvent;
+import com.apple.eawt.AppEvent.OpenFilesEvent;
+import com.apple.eawt.AppEvent.PreferencesEvent;
+import com.apple.eawt.AppReOpenedListener;
+import com.apple.eawt.OpenFilesHandler;
+import com.apple.eawt.PreferencesHandler;
+
+public class OSXManager implements OpenFilesHandler, AboutHandler, PreferencesHandler, AppReOpenedListener {
+
+	private OSXManager() {
+		System.setProperty("apple.laf.useScreenMenuBar", "true");
+		System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Giraffe");
+	}
+	
+	private static OSXManager handler;
+	
+	public static synchronized OSXManager getDefaultHandler() {
+		if (handler==null)
+			handler=new OSXManager();
+		return handler;
+	}
+	
+	@Override
+	public void openFiles(OpenFilesEvent event) {
+		if (event.getFiles().size()==0) {
+			GiraffeLogger.error("Sent 0 length file list!");
+			return;
+		}
+		if (event.getFiles().size()>1)
+			GiraffeLogger.warn("Sent multiple files to open; ignoring all but first.");
+		
+		GiraffeLogger.info("Asked to open file at: "+event.getFiles().get(0).getAbsolutePath());		
+	}
+
+	@Override
+	public void handleAbout(AboutEvent event) {
+		About.showAboutWindow();
+	}
+
+	@Override
+	public void handlePreferences(PreferencesEvent event) {
+		GiraffeLogger.warn("No configurable preferences for GIRAFFE.");
+	}
+
+	@Override
+	public void appReOpened(AppReOpenedEvent event) {
+		GiraffeLogger.info("AppReOpened");
+	}
+}

File src/ca/usask/cs/giraffe/ui/StaticGUI.java

View file
 		c.fill = GridBagConstraints.BOTH;
 		innerPanel.add(animationPanel, c);
 		
-		this.setJMenuBar(new MenuBar(controller,
+		this.setJMenuBar(new MenuBar(controller,this,
 				this.programPanel.inputTerminalText));
 		
 		this.add(innerPanel);

File src/ca/usask/cs/giraffe/ui/ToolBar.java

View file
 import java.util.EnumSet;
 import java.util.Hashtable;
 
+import javax.swing.Box;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
 import javax.swing.JLabel;
 import ca.usask.cs.giraffe.core.AnimTimer;
 import ca.usask.cs.giraffe.core.GiraffeAction;
 import ca.usask.cs.giraffe.core.GiraffeLogger;
-import ca.usask.cs.giraffe.core.GiraffeAction.ActionID;
+import ca.usask.cs.giraffe.core.OSQualifier;
 
 /**
  * The tool bar to be added to the StaticGUI Contains all the main buttons for
 		slider.setToolTipText("Adjust automatic step forward speed");
 		slider.setFocusable(false);
 		
-		slider.setUI(new BasicSliderUI(slider));
+		// fix the slider UI on Linux, but not OS X and Windows
+		double sliderWidthFactor=1.5;
+		if (OSQualifier.isLinux()) {
+			slider.setUI(new BasicSliderUI(slider));
+			sliderWidthFactor=2.0;
+		}
 		Dimension sliderD = slider.getPreferredSize();
-		slider.setPreferredSize((new Dimension((int)sliderD.getWidth() * 2,
+		slider.setPreferredSize((new Dimension((int)(sliderD.getWidth() * sliderWidthFactor),
 				(int)sliderD.getHeight())));
 		
 		Hashtable<Integer,JLabel> labels = new Hashtable<Integer,JLabel>();