/** * Warlock, the open-source cross-platform game client * * Copyright 2008, Warlock LLC, and individual contributors as indicated * by the @authors tag. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ /* * Created on Sep 17, 2004 */ package cc.warlock.rcp.views; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Caret; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.PageBook; import cc.warlock.core.client.IWarlockClient; import cc.warlock.core.client.IWarlockClientListener; import cc.warlock.core.client.IWarlockClientViewer; import cc.warlock.core.client.PropertyListener; import cc.warlock.core.client.WarlockClientRegistry; import cc.warlock.rcp.configuration.GameViewConfiguration; import cc.warlock.rcp.ui.StreamText; import cc.warlock.rcp.ui.WarlockEntry; import cc.warlock.rcp.ui.WarlockPopupAction; import cc.warlock.rcp.ui.client.SWTWarlockClientListener; import cc.warlock.rcp.ui.client.SWTWarlockClientViewer; import cc.warlock.rcp.util.ColorUtil; import cc.warlock.rcp.util.SoundPlayer; /** * @author marshall */ public abstract class GameView extends WarlockView implements IWarlockClientViewer, IWarlockClientListener { public static final String VIEW_ID = "cc.warlock.rcp.ui.views.GameView"; protected static GameView firstInstance; protected static boolean firstInstanceIsUsed = false; protected static ArrayList<GameView> openViews = new ArrayList<GameView>(); protected static ArrayList<IGameViewFocusListener> focusListeners = new ArrayList<IGameViewFocusListener>(); protected static GameView gameInFocus; protected PageBook popupPageBook; protected Label emptyPopup; protected StreamText streamText; protected WarlockEntry entry; protected SWTWarlockClientViewer wrapper; protected Composite entryComposite; protected IWarlockClient client; protected Composite mainComposite; public GameView () { super(); if (firstInstance == null) { firstInstance = this; gameInFocus = this; } // currentCommand = ""; openViews.add(this); wrapper = new SWTWarlockClientViewer(this); WarlockClientRegistry.addWarlockClientListener(new SWTWarlockClientListener(this)); } public static void addGameViewFocusListener (IGameViewFocusListener listener) { focusListeners.add(listener); } public static void removeGameViewFocusListener (IGameViewFocusListener listener) { focusListeners.remove(listener); } public static List<GameView> getOpenGameViews () { return openViews; } public static GameView getGameViewInFocus () { return gameInFocus; } public static void initializeGameView (GameView gameView) { gameInFocus = gameView; if (ConnectionView.closeAfterConnect) { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IViewPart part = page.findView(ConnectionView.VIEW_ID); if (part != null) page.hideView(part); } } public static GameView createNext (String viewId, String secondId) { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); try { IViewPart part = page.showView(viewId, secondId, IWorkbenchPage.VIEW_ACTIVATE); // if there's an error in creating the view, we want to know about it.. don't cast unless we know it's not an errorviewpart if (part instanceof GameView) { GameView nextInstance = (GameView) part; initializeGameView(nextInstance); return nextInstance; } } catch (PartInitException e) { e.printStackTrace(); } return null; } public static GameView getGameViewForClient(IWarlockClient client) { for (GameView view: openViews) { if (view.client == client) { return view; } } // TODO: Make a GameView and return it. (Null is likely to cause problems in the long run) return null; } public void createPartControl(Composite parent) { // Create main composite mainComposite = new Composite (parent, SWT.NONE); GridLayout mainLayout = new GridLayout(1, false); mainLayout.marginHeight = 0; mainLayout.marginWidth = 0; mainLayout.horizontalSpacing = 0; mainLayout.verticalSpacing = 0; mainComposite.setLayout(mainLayout); // create a pagebook for the popups popupPageBook = new PageBook(mainComposite, SWT.NONE); GridData data = new GridData(SWT.FILL, SWT.FILL, true, false); data.exclude = true; popupPageBook.setLayoutData(data); emptyPopup = new Label(popupPageBook, SWT.NONE); popupPageBook.showPage(emptyPopup); popupPageBook.setVisible(false); streamText = new StreamText(mainComposite, IWarlockClient.DEFAULT_STREAM_NAME); streamText.setLineLimit(GameViewConfiguration.instance().getBufferLines()); streamText.getTextWidget().setLayout(new GridLayout(1, false)); streamText.setIgnoreEmptyLines(false); // create the entry entryComposite = new Composite(mainComposite, SWT.NONE); GridLayout entryLayout = new GridLayout(1, false); entryLayout.horizontalSpacing = 0; entryLayout.verticalSpacing = 0; entryLayout.marginHeight = 1; entryLayout.marginWidth = 0; entryComposite.setLayout(entryLayout); entryComposite.setLayoutData(new GridData(GridData.FILL, GridData.VERTICAL_ALIGN_END, true, false)); this.entry = new WarlockEntry(entryComposite, wrapper); // Do this BEFORE getTextForClient! initColors(); } protected void initColors() { Color background = ColorUtil.warlockColorToColor(GameViewConfiguration.instance().getDefaultBackground()); Color foreground = ColorUtil.warlockColorToColor(GameViewConfiguration.instance().getDefaultForeground()); entry.getWidget().setBackground(background); entry.getWidget().setForeground(foreground); //streamText.setBackgroundMode(SWT.INHERIT_DEFAULT); } @Override public void setFocus() { super.setFocus(); gameInFocus = this; for (IGameViewFocusListener listener : focusListeners) { listener.gameViewFocused(this); } } public void playSound(InputStream soundStream) { SoundPlayer.play(soundStream); } protected Image createCaretImage (int width, Color foreground) { PaletteData caretPalette = new PaletteData(new RGB[] { new RGB(0, 0, 0), new RGB(255, 255, 255) }); int widthOffset = width - 1; ImageData imageData = new ImageData(4 + widthOffset, entry.getWidget().getLineHeight(), 1, caretPalette); Display display = entry.getWidget().getDisplay(); Image bracketImage = new Image(display, imageData); GC gc = new GC(bracketImage); gc.setForeground(foreground); gc.setLineWidth(1); // gap between two bars of one third of the height // draw boxes using lines as drawing a line of a certain width produces // rounded corners. for (int i = 0; i < width; i++) { gc.drawLine(i, 0, i, imageData.height - 1); } gc.dispose(); return bracketImage; } protected Caret createCaret (int width, Color foreground) { Caret caret = new Caret(entry.getWidget(), SWT.NULL); Image image = createCaretImage(width, foreground); if (image != null) caret.setImage(image); else caret.setSize(width, entry.getWidget().getLineHeight()); caret.setFont(entry.getWidget().getFont()); return caret; } public String getCurrentCommand () { return entry.getText(); } public void setCurrentCommand(String command) { if(command == null) { command = ""; } GameView.this.entry.setText(command); GameView.this.entry.setSelection(command.length()); } public void append(char c) { entry.append(c); } public void nextCommand() { entry.nextCommand(); } public void prevCommand() { entry.prevCommand(); } public void searchHistory() { entry.searchHistory(); } public void submit() { entry.submit(); } public void repeatLastCommand() { entry.repeatLastCommand(); } public void repeatSecondToLastCommand() { entry.repeatSecondToLastCommand(); } public void copy() { streamText.copy(); } public void paste() { entry.getWidget().paste(); } public IWarlockClient getWarlockClient() { return client; } public WarlockEntry getWarlockEntry() { return entry; } public WarlockPopupAction createPopup () { WarlockPopupAction popup = new WarlockPopupAction(popupPageBook, SWT.NONE); // popup.moveAbove(book); // popup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); // popup.setVisible(false); return popup; } public void showPopup (WarlockPopupAction popup) { boolean atBottom = streamText.isAtBottom(); popupPageBook.showPage(popup); popupPageBook.setVisible(true); ((GridData)popupPageBook.getLayoutData()).exclude = false; mainComposite.layout(); if(atBottom) streamText.scrollToEnd(); } public void hidePopup (WarlockPopupAction popup) { boolean atBottom = streamText.isAtBottom(); popupPageBook.showPage(emptyPopup); popupPageBook.setVisible(false); ((GridData)popupPageBook.getLayoutData()).exclude = true; mainComposite.layout(); if(atBottom) streamText.scrollToEnd(); } @Override public void dispose() { if (client != null) { // All done with client, dispose of it so it can do whatever it needs to to be done. client.dispose(); } openViews.remove(this); if (gameInFocus == this) { gameInFocus = null; } if (firstInstance == this) { if (openViews.isEmpty()) { firstInstance = null; // Show connections page since we're getting rid of the main window IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); //IViewPart part = page.findView(ConnectionView.VIEW_ID); try { if (page != null) page.showView(ConnectionView.VIEW_ID); } catch (PartInitException e) { e.printStackTrace(); } } else firstInstance = openViews.get(0); } streamText.dispose(); super.dispose(); } public void pageDown() { streamText.pageDown(); } public void pageUp() { streamText.pageUp(); } public void setClient(IWarlockClient client) { if (this.client != null) { // All done with client, dispose of it so it can do whatever it needs to to be done. this.client.dispose(); } this.client = client; client.setViewer(wrapper); streamText.getTitle().addListener(new PropertyListener<String>() { public void propertyChanged(String value) { setViewTitle(value); } }); streamText.setClient(client); } protected abstract void setViewTitle(String title); public boolean isStreamOpen(String streamName) { if(streamName == IWarlockClient.DEFAULT_STREAM_NAME) return true; for(StreamView streamView : StreamView.getOpenViews()) { if(streamView.getStreamName().equals(streamName)) return true; } return false; } }