/* Copyright (C) 2011 monte This file is part of PSP NetParty. PSP NetParty 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. This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package pspnetparty.client.swt; import java.io.IOException; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.preference.PreferenceManager; import org.eclipse.jface.preference.PreferenceNode; import org.eclipse.jface.resource.ColorRegistry; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.ShellListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swt.widgets.ToolTip; import org.eclipse.swt.widgets.Tray; import org.eclipse.swt.widgets.TrayItem; import pspnetparty.client.swt.config.AppearancePage; import pspnetparty.client.swt.config.IPreferenceNodeProvider; import pspnetparty.client.swt.config.IniAppData; import pspnetparty.client.swt.config.IniAppearance; import pspnetparty.client.swt.config.IniSettings; import pspnetparty.client.swt.config.IniUserProfile; import pspnetparty.client.swt.config.MiscSettingPage; import pspnetparty.client.swt.config.UserProfilePage; import pspnetparty.client.swt.message.ErrorLog; import pspnetparty.client.swt.message.IMessage; import pspnetparty.client.swt.message.IMessageListener; import pspnetparty.client.swt.plugin.BouyomiChanPlugin; import pspnetparty.client.swt.plugin.IPlugin; import pspnetparty.lib.ILogger; import pspnetparty.lib.IniFile; import pspnetparty.lib.IniSection; import pspnetparty.lib.Utility; import pspnetparty.lib.constants.AppConstants; import pspnetparty.lib.constants.IServerRegistry; import pspnetparty.lib.constants.IniPublicServerRegistry; import pspnetparty.lib.constants.ProtocolConstants; import pspnetparty.lib.socket.AsyncTcpClient; import pspnetparty.lib.socket.AsyncUdpClient; import pspnetparty.lib.socket.IProtocol; import pspnetparty.lib.socket.IProtocolDriver; import pspnetparty.lib.socket.ISocketConnection; import pspnetparty.lib.socket.PacketData; import pspnetparty.wlan.JnetPcapWlanDevice; import pspnetparty.wlan.NativeWlanDevice; import pspnetparty.wlan.WlanLibrary; public class PlayClient { public enum FontType { GLOBAL, LOG, CHAT, } public enum ColorType { BACKGROUND, FOREGROUND, LOG_BACKGROUND, } interface PortalQuery { public String getCommand(); public void successCallback(String message); public void failCallback(ErrorLog errorLog); } public static final String ICON_APP16 = "app.icon16"; public static final String ICON_APP32 = "app.icon32"; public static final String ICON_APP48 = "app.icon48"; public static final String ICON_APP96 = "app.icon96"; public static final String ICON_TOOLBAR_ROOM = "toolbar.room"; public static final String ICON_TOOLBAR_ARENA = "toolbar.arena"; public static final String ICON_TOOLBAR_LOG = "toolbar.log"; public static final String ICON_TOOLBAR_CONFIG = "toolbar.config"; public static final String ICON_TOOLBAR_WIKI = "toolbar.wiki"; public static final String ICON_TOOLBAR_EXIT = "toolbar.exit"; public static final String ICON_TAB_LOBBY = "tab.lobby"; public static final String ICON_TAB_LOBBY_NOTIFY = "tab.lobby_notify"; public static final String ICON_TAB_LOG = "tab.system"; public static final String ICON_TAB_LOG_NOTIFY = "tab.system_notify"; public static final String ICON_TAB_PM = "tab.pm"; public static final String ICON_TAB_PM_NOTIFY = "tab.pm_notify"; public static final String ICON_TAB_CIRCLE = "tab.circle"; public static final String ICON_TAB_CIRCLE_NOTIFY = "tab.circle_notify"; public static final String COLOR_OK = "color.ok"; public static final String COLOR_NG = "color.ng"; public static final String COLOR_APP_NUMBER = "color.appnumber"; public static final String COLOR_TAB_NOTIFY = "color.tabnotify"; private static final String INI_SETTING_FILE_NAME = "PlayClient.ini"; private static final String INI_APPDATA_FILE_NAME = "PlayClient.appdata"; private IniFile iniSettingFile; private IniFile iniAppDataFile; private IniSettings iniSettings; private IniAppearance iniAppearance; private IniUserProfile iniUserProfile; private IniAppData iniAppData; private TrayItem trayItem; private ToolTip toolTip; private Clipboard clipboard; private TextTransfer[] textTransfers = new TextTransfer[] { TextTransfer.getInstance() }; private Image[] shellImages; private ImageRegistry imageRegistry; private ColorRegistry colorRegistry; private ArrayList<Control> controls = new ArrayList<Control>(); private ArrayList<Label> labels = new ArrayList<Label>(); private ArrayList<Button> buttons = new ArrayList<Button>(); private ArrayList<StyledText> logControls = new ArrayList<StyledText>(); private ArrayList<Text> chatControls = new ArrayList<Text>(); private AsyncTcpClient tcpClient; private AsyncUdpClient udpClient; private WlanLibrary wlanLibrary; private ExecutorService executorService = Executors.newCachedThreadPool(); private IServerRegistry serverRegistry; private Iterator<String> portalServerList; private boolean isRunning = true; private ArenaWindow arenaWindow; private RoomWindow roomWindow; private ArrayList<IPlugin> pluginList = new ArrayList<IPlugin>(); private ArrayList<IPreferenceNodeProvider> preferenceNodeProviders = new ArrayList<IPreferenceNodeProvider>(); private HashSet<IMessageListener> roomMessageListeners = new HashSet<IMessageListener>(); private HashSet<IMessageListener> lobbyMessageListeners = new HashSet<IMessageListener>(); private ArrayList<Label> toolbarSsidLibraryLabels = new ArrayList<Label>(); public PlayClient() throws IOException { iniSettingFile = new IniFile(INI_SETTING_FILE_NAME); iniAppDataFile = new IniFile(INI_APPDATA_FILE_NAME); iniSettings = new IniSettings(iniSettingFile.getSection(IniSettings.SECTION), new WlanProxyLibrary(this)); iniUserProfile = new IniUserProfile(iniSettingFile.getSection(IniUserProfile.SECTION)); iniAppearance = new IniAppearance(iniSettingFile.getSection(IniAppearance.SECTION)); iniAppData = new IniAppData(iniAppDataFile.getSection(null)); ArrayList<String> pendingLogs = new ArrayList<String>(); if (JnetPcapWlanDevice.LIBRARY.isReady()) { pendingLogs.add("PcapインストールOK"); } else { pendingLogs.add("Pcapがインストールされていません"); } if (NativeWlanDevice.LIBRARY.isReady()) { pendingLogs.add("Windowsワイヤレスネットワーク機能OK"); } else { pendingLogs.add("Windowsワイヤレスネットワーク機能がインストールされていません"); } wlanLibrary = iniSettings.getWlanLibrary(); ILogger logger = new ILogger() { @Override public void log(String message) { getArenaWindow().appendToSystemLog(message, true); } }; tcpClient = new AsyncTcpClient(logger, 1000000, 0); udpClient = new AsyncUdpClient(logger); imageRegistry = new ImageRegistry(SwtUtils.DISPLAY); colorRegistry = new ColorRegistry(SwtUtils.DISPLAY); clipboard = new Clipboard(SwtUtils.DISPLAY); try { Image icon16 = new Image(SwtUtils.DISPLAY, new ImageData("icon/blue16.png")); Image icon32 = new Image(SwtUtils.DISPLAY, new ImageData("icon/blue32.png")); Image icon48 = new Image(SwtUtils.DISPLAY, new ImageData("icon/blue48.png")); Image icon96 = new Image(SwtUtils.DISPLAY, new ImageData("icon/blue96.png")); imageRegistry.put(ICON_APP16, icon16); imageRegistry.put(ICON_APP32, icon32); imageRegistry.put(ICON_APP48, icon48); imageRegistry.put(ICON_APP96, icon96); shellImages = new Image[] { icon16, icon32, icon48, icon96 }; Image toolArena = new Image(SwtUtils.DISPLAY, new ImageData("icon/toolbar/search.png")); Image toolRoom = new Image(SwtUtils.DISPLAY, new ImageData("icon/toolbar/lobby4.png")); Image toolConfig = new Image(SwtUtils.DISPLAY, new ImageData("icon/toolbar/config.png")); Image toolLog = new Image(SwtUtils.DISPLAY, new ImageData("icon/toolbar/log.png")); Image toolWiki = new Image(SwtUtils.DISPLAY, new ImageData("icon/toolbar/wiki.png")); Image toolExit = new Image(SwtUtils.DISPLAY, new ImageData("icon/toolbar/lobby3.png")); imageRegistry.put(ICON_TOOLBAR_ARENA, toolArena); imageRegistry.put(ICON_TOOLBAR_ROOM, toolRoom); imageRegistry.put(ICON_TOOLBAR_LOG, toolLog); imageRegistry.put(ICON_TOOLBAR_WIKI, toolWiki); imageRegistry.put(ICON_TOOLBAR_CONFIG, toolConfig); imageRegistry.put(ICON_TOOLBAR_EXIT, toolExit); Image tabLobby = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/lobby.png")); Image tabLobbyNotify = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/lobby2.png")); Image tabSystem = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/log.png")); Image tabSystemNotify = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/log2.png")); Image tabPm = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/pm.png")); Image tabPmNotify = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/pm2.png")); Image tabCircle = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/circle.png")); Image tabCircleNotify = new Image(SwtUtils.DISPLAY, new ImageData("icon/tab/circle2.png")); imageRegistry.put(ICON_TAB_LOBBY, tabLobby); imageRegistry.put(ICON_TAB_LOBBY_NOTIFY, tabLobbyNotify); imageRegistry.put(ICON_TAB_LOG, tabSystem); imageRegistry.put(ICON_TAB_LOG_NOTIFY, tabSystemNotify); imageRegistry.put(ICON_TAB_PM, tabPm); imageRegistry.put(ICON_TAB_PM_NOTIFY, tabPmNotify); imageRegistry.put(ICON_TAB_CIRCLE, tabCircle); imageRegistry.put(ICON_TAB_CIRCLE_NOTIFY, tabCircleNotify); } catch (SWTException e) { } colorRegistry.put(COLOR_OK, new RGB(0, 140, 0)); colorRegistry.put(COLOR_NG, new RGB(200, 0, 0)); colorRegistry.put(COLOR_APP_NUMBER, new RGB(0, 0, 220)); colorRegistry.put(COLOR_TAB_NOTIFY, new RGB(0, 0, 220)); arenaWindow = new ArenaWindow(this); try { Tray systemTray = SwtUtils.DISPLAY.getSystemTray(); if (systemTray != null) { trayItem = new TrayItem(systemTray, SWT.NONE); trayItem.setImage(imageRegistry.get(ICON_APP16)); trayItem.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { arenaWindow.show(); if (roomWindow != null) roomWindow.show(); } }); toolTip = new ToolTip(arenaWindow.getShell(), SWT.BALLOON | SWT.ICON_INFORMATION); trayItem.setToolTip(toolTip); trayItem.setToolTipText(AppConstants.APP_NAME); final Menu menu = new Menu(arenaWindow.getShell()); MenuItem itemArena = new MenuItem(menu, SWT.PUSH); itemArena.setText("アリーナ"); itemArena.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { getArenaWindow().show(); } }); MenuItem itemRoom = new MenuItem(menu, SWT.PUSH); itemRoom.setText("ルーム"); itemRoom.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { getRoomWindow().show(); } }); MenuItem itemShutdown = new MenuItem(menu, SWT.PUSH); itemShutdown.setText("アプリを終了"); itemShutdown.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { isRunning = false; } }); trayItem.addMenuDetectListener(new MenuDetectListener() { @Override public void menuDetected(MenuDetectEvent e) { menu.setVisible(true); } }); } } catch (SWTException e) { } try { serverRegistry = new IniPublicServerRegistry(); } catch (IOException e) { serverRegistry = IServerRegistry.NULL; arenaWindow.appendToSystemLog(Utility.stackTraceToString(e), true); } portalServerList = serverRegistry.getPortalRotator(); String software = String.format("%s プレイクライアント バージョン: %s", AppConstants.APP_NAME, AppConstants.VERSION); arenaWindow.appendToSystemLog(software, false); arenaWindow.appendToSystemLog("プロトコル: " + IProtocol.NUMBER, false); for (String log : pendingLogs) { arenaWindow.appendToSystemLog(log, false); } Thread cronThread = new Thread(new Runnable() { @Override public void run() { try { while (!SwtUtils.DISPLAY.isDisposed()) { arenaWindow.cronJob(); if (roomWindow != null) roomWindow.cronJob(); Thread.sleep(1000); } } catch (InterruptedException e) { } catch (SWTException e) { } } }, "CronThread"); cronThread.setDaemon(true); cronThread.start(); try { IPlugin plugin = (IPlugin) Class.forName(BouyomiChanPlugin.class.getName()).newInstance(); plugin.initPlugin(this); pluginList.add(plugin); } catch (InstantiationException e) { } catch (IllegalAccessException e) { } catch (ClassNotFoundException e) { } arenaWindow.getShell().addShellListener(new ShellListener() { @Override public void shellActivated(ShellEvent e) { } @Override public void shellIconified(ShellEvent e) { } @Override public void shellDeiconified(ShellEvent e) { } @Override public void shellDeactivated(ShellEvent e) { } @Override public void shellClosed(ShellEvent e) { if (roomWindow == null || !roomWindow.getShell().getVisible()) { checkApplicationShutdown(arenaWindow.getShell(), e); } else { e.doit = false; arenaWindow.hide(); } } }); if (Utility.isEmpty(iniUserProfile.getUserName())) { TextDialog dialog = new TextDialog(null, AppConstants.APP_NAME + " - ユーザー名が設定されていません", "ユーザー名を入力してください", null, 300, SWT.NONE); switch (dialog.open()) { case IDialogConstants.OK_ID: iniUserProfile.setUserName(dialog.getUserInput()); break; default: iniUserProfile.setUserName("未設定"); } } if (iniSettings.isStartupWindowArena()) { arenaWindow.show(); } else { getRoomWindow().show(); } } private boolean openShutdownConfirmDialog(Shell shell) { ConfirmDialog dialog = new ConfirmDialog(shell, "PSP NetPartyを終了します", "PSP NetPartyを終了します。よろしいですか?"); switch (dialog.open()) { case IDialogConstants.CANCEL_ID: return false; default: return true; } } private void checkApplicationShutdown(Shell shell, ShellEvent e) { if (!iniSettings.isNeedAppCloseConfirm()) { isRunning = false; return; } if (openShutdownConfirmDialog(shell)) { isRunning = false; } else { e.doit = false; } } public void createToolBar(final Composite parent, IAppWindow window) { GridLayout gridLayout; Composite container = new Composite(parent, SWT.NONE); gridLayout = new GridLayout(2, false); gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 0; gridLayout.marginWidth = 3; gridLayout.marginHeight = 1; container.setLayout(gridLayout); ToolBar toolBar = new ToolBar(container, SWT.FLAT | SWT.RIGHT); toolBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); IAppWindow.Type type = window.getType(); if (type != IAppWindow.Type.ARENA) { ToolItem arenaWindowItem = new ToolItem(toolBar, SWT.PUSH); arenaWindowItem.setText("アリーナ"); arenaWindowItem.setToolTipText("部屋の検索やロビーのチャット"); arenaWindowItem.setImage(imageRegistry.get(ICON_TOOLBAR_ARENA)); arenaWindowItem.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { arenaWindow.show(); } }); } if (type != IAppWindow.Type.ROOM) { ToolItem roomWindowItem = new ToolItem(toolBar, SWT.PUSH); roomWindowItem.setText("ルーム"); roomWindowItem.setToolTipText("ルーム内で通信プレイができます"); roomWindowItem.setImage(imageRegistry.get(ICON_TOOLBAR_ROOM)); roomWindowItem.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { getRoomWindow().show(); } }); } ToolItem configWindowItem = new ToolItem(toolBar, SWT.PUSH); configWindowItem.setText("設定"); configWindowItem.setToolTipText("アプリケーションの設定をします"); configWindowItem.setImage(imageRegistry.get(ICON_TOOLBAR_CONFIG)); configWindowItem.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (openConfigDialog(parent.getShell(), null)) { if (arenaWindow != null) arenaWindow.settingChanged(); if (roomWindow != null) roomWindow.settingChanged(); } } }); ToolItem wikiItem = new ToolItem(toolBar, SWT.PUSH); wikiItem.setText("Wiki"); wikiItem.setToolTipText(AppConstants.APP_NAME + "のWikiページを表示します"); wikiItem.setImage(imageRegistry.get(ICON_TOOLBAR_WIKI)); wikiItem.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { Program.launch("http://pnpwiki.monkets.org/"); } }); ToolItem exitItem = new ToolItem(toolBar, SWT.PUSH); exitItem.setText("終了"); exitItem.setToolTipText(AppConstants.APP_NAME + "を終了します"); exitItem.setImage(imageRegistry.get(ICON_TOOLBAR_EXIT)); exitItem.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (openShutdownConfirmDialog(parent.getShell())) { isRunning = false; } } }); Composite appVersionContainer = new Composite(container, SWT.NONE); appVersionContainer.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false)); RowLayout rowLayout = new RowLayout(); rowLayout.center = true; rowLayout.marginTop = 0; rowLayout.marginBottom = 0; rowLayout.marginLeft = 0; rowLayout.marginRight = 0; appVersionContainer.setLayout(rowLayout); Label statusApplicationVersionLabel = new Label(appVersionContainer, SWT.NONE); statusApplicationVersionLabel.setText("バージョン:"); initControl(statusApplicationVersionLabel); Label statusApplicationVersionNumber = new Label(appVersionContainer, SWT.NONE); statusApplicationVersionNumber.setText(AppConstants.VERSION); statusApplicationVersionNumber.setForeground(colorRegistry.get(COLOR_APP_NUMBER)); initControl(statusApplicationVersionNumber); Label statusApplicationProtocolLabel = new Label(appVersionContainer, SWT.NONE); statusApplicationProtocolLabel.setText("プロトコル:"); initControl(statusApplicationProtocolLabel); Label statusApplicationProtocolNumber = new Label(appVersionContainer, SWT.NONE); statusApplicationProtocolNumber.setText(IProtocol.NUMBER); statusApplicationProtocolNumber.setForeground(colorRegistry.get(COLOR_APP_NUMBER)); initControl(statusApplicationProtocolNumber); Label statusApplicationSsidLabel = new Label(appVersionContainer, SWT.NONE); statusApplicationSsidLabel.setText("SSID機能:"); initControl(statusApplicationSsidLabel); Label statusApplicationSsidLibrary = new Label(appVersionContainer, SWT.NONE); toolbarSsidLibraryLabels.add(statusApplicationSsidLibrary); initControl(statusApplicationSsidLibrary); updateWlanLibraryStatus(); } private void updateWlanLibraryStatus() { if (!wlanLibrary.isReady()) { for (Label ssidStatus : toolbarSsidLibraryLabels) { ssidStatus.setText("エラー"); ssidStatus.setForeground(colorRegistry.get(COLOR_NG)); ssidStatus.getParent().getParent().layout(); } } else if (wlanLibrary instanceof WlanProxyLibrary) { for (Label ssidStatus : toolbarSsidLibraryLabels) { ssidStatus.setText("プロキシ"); ssidStatus.setForeground(colorRegistry.get(COLOR_NG)); ssidStatus.getParent().getParent().layout(); } } else if (wlanLibrary.isSSIDEnabled()) { for (Label ssidStatus : toolbarSsidLibraryLabels) { ssidStatus.setText("On"); ssidStatus.setForeground(colorRegistry.get(COLOR_APP_NUMBER)); ssidStatus.getParent().getParent().layout(); } } else { for (Label ssidStatus : toolbarSsidLibraryLabels) { ssidStatus.setText("Off"); ssidStatus.setForeground(colorRegistry.get(COLOR_OK)); ssidStatus.getParent().getParent().layout(); } } } public Image[] getShellImages() { return shellImages; } public IniAppData getAppData() { return iniAppData; } public IniSettings getSettings() { return iniSettings; } public IniAppearance getAppearance() { return iniAppearance; } public IniUserProfile getUserProfile() { return iniUserProfile; } public IniSection getIniSection(String sectionName) { return iniSettingFile.getSection(sectionName); } public ImageRegistry getImageRegistry() { return imageRegistry; } public ColorRegistry getColorRegistry() { return colorRegistry; } public RoomWindow getRoomWindow() { if (roomWindow == null) { roomWindow = new RoomWindow(this); roomWindow.getShell().addShellListener(new ShellListener() { @Override public void shellIconified(ShellEvent e) { } @Override public void shellDeiconified(ShellEvent e) { } @Override public void shellDeactivated(ShellEvent e) { } @Override public void shellActivated(ShellEvent e) { } @Override public void shellClosed(ShellEvent e) { if (arenaWindow == null || !arenaWindow.getShell().getVisible()) { switch (roomWindow.confirmRoomDelete(true)) { case 0: e.doit = false; return; case 1: case -1: checkApplicationShutdown(roomWindow.getShell(), e); return; } } else { e.doit = false; roomWindow.hide(); } } }); } return roomWindow; } public ArenaWindow getArenaWindow() { return arenaWindow; } public void addConfigPageProvider(IPreferenceNodeProvider provider) { preferenceNodeProviders.add(provider); } public boolean openConfigDialog(Shell parentShell, String pageId) { PreferenceManager manager = new PreferenceManager(); PreferenceNode profile = new PreferenceNode(UserProfilePage.PAGE_ID, new UserProfilePage(iniUserProfile)); manager.addToRoot(profile); PreferenceNode setting = new PreferenceNode(MiscSettingPage.PAGE_ID, new MiscSettingPage(iniSettings)); manager.addToRoot(setting); PreferenceNode appearance = new PreferenceNode(AppearancePage.PAGE_ID, new AppearancePage(this)); manager.addToRoot(appearance); for (IPreferenceNodeProvider p : preferenceNodeProviders) manager.addToRoot(p.createPreferenceNode()); PreferenceDialog dialog = new PreferenceDialog(parentShell, manager) { @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText("設定"); newShell.setImage(imageRegistry.get(ICON_TOOLBAR_CONFIG)); } @Override protected Composite createTitleArea(Composite parent) { Composite composite = super.createTitleArea(parent); FormLayout layout = (FormLayout) composite.getLayout(); layout.marginTop = 4; return composite; } }; if (pageId != null) dialog.setSelectedNode(pageId); switch (dialog.open()) { case IDialogConstants.OK_ID: try { iniSettingFile.saveToIni(); wlanLibrary = iniSettings.getWlanLibrary(); updateWlanLibraryStatus(); return true; } catch (IOException e) { arenaWindow.appendToSystemLog(Utility.stackTraceToString(e), true); e.printStackTrace(); } } return false; } public void initControl(Control control) { control.setFont(iniAppearance.getFontGlobal()); control.setBackground(iniAppearance.getColorBackground()); control.setForeground(iniAppearance.getColorForeground()); controls.add(control); } public void initControl(Label label) { label.setFont(iniAppearance.getFontGlobal()); labels.add(label); } public void initControl(Button button) { button.setFont(iniAppearance.getFontGlobal()); buttons.add(button); } public void initLogControl(StyledText log) { log.setFont(iniAppearance.getFontLog()); log.setBackground(iniAppearance.getColorLogBackground()); log.setForeground(iniAppearance.getColorLogBackground()); logControls.add(log); } public void initChatControl(Text chat) { chat.setFont(iniAppearance.getFontChat()); chat.setBackground(iniAppearance.getColorBackground()); chat.setForeground(iniAppearance.getColorForeground()); chatControls.add(chat); } public void applyFont(FontType type, FontData data) { Font newFont = new Font(SwtUtils.DISPLAY, data); Font oldFont = null; switch (type) { case GLOBAL: { oldFont = iniAppearance.getFontGlobal(); for (Control control : controls) { if (control.isDisposed()) continue; control.setFont(newFont); } for (Label label : labels) { if (label.isDisposed()) continue; label.setFont(newFont); } for (Button button : buttons) { if (button.isDisposed()) continue; button.setFont(newFont); } iniAppearance.setFontGlobal(newFont); break; } case LOG: { oldFont = iniAppearance.getFontLog(); for (StyledText control : logControls) { if (control.isDisposed()) continue; control.setFont(newFont); } iniAppearance.setFontLog(newFont); break; } case CHAT: { oldFont = iniAppearance.getFontChat(); for (Text control : chatControls) { if (control.isDisposed()) continue; control.setFont(newFont); } iniAppearance.setFontChat(newFont); break; } } if (oldFont != null) oldFont.dispose(); } public void applyColor(ColorType type, RGB rgb) { Color newColor = new Color(SwtUtils.DISPLAY, rgb); Color oldColor = null; switch (type) { case BACKGROUND: { oldColor = iniAppearance.getColorBackground(); for (Control control : controls) { if (control.isDisposed()) continue; control.setBackground(newColor); } for (Text chat : chatControls) { if (chat.isDisposed()) continue; chat.setBackground(newColor); } iniAppearance.setColorBackground(newColor); break; } case FOREGROUND: { oldColor = iniAppearance.getColorForeground(); for (Control control : controls) { if (control.isDisposed()) continue; control.setForeground(newColor); } for (Text chat : chatControls) { if (chat.isDisposed()) continue; chat.setForeground(newColor); } iniAppearance.setColorForeground(newColor); break; } case LOG_BACKGROUND: { oldColor = iniAppearance.getColorLogBackground(); for (StyledText text : logControls) { if (text.isDisposed()) continue; text.setBackground(newColor); text.setForeground(newColor); } iniAppearance.setColorLogBackground(newColor); } } if (oldColor != null) oldColor.dispose(); } public void reflectAppearance() { arenaWindow.reflectAppearance(); if (roomWindow != null) roomWindow.reflectAppearance(); } public void putClipboard(String data) { clipboard.setContents(new Object[] { data }, textTransfers); } public String getClipboardContents() { return (String) clipboard.getContents(TextTransfer.getInstance()); } public void setTaskTrayTooltipText(String title) { if (trayItem != null) { trayItem.setToolTipText(title); } } public void balloonNotify(final Shell shell, final String message) { if (toolTip == null) return; try { if (SwtUtils.isNotUIThread()) { SwtUtils.DISPLAY.asyncExec(new Runnable() { @Override public void run() { balloonNotify(shell, message); } }); return; } toolTip.setText(shell.getText()); toolTip.setMessage(message); toolTip.setVisible(true); } catch (SWTException e) { } } public void roomMessageReceived(IMessage message) { for (IMessageListener listener : roomMessageListeners) listener.messageReceived(message); } public void addRoomMessageListener(IMessageListener listener) { roomMessageListeners.add(listener); } public void removeRoomMessageListener(IMessageListener listener) { roomMessageListeners.remove(listener); } public void lobbyMessageReceived(IMessage message) { for (IMessageListener listener : lobbyMessageListeners) listener.messageReceived(message); } public void addLobbyMessageListener(IMessageListener listener) { lobbyMessageListeners.add(listener); } public void removeLobbyMessageListener(IMessageListener listener) { lobbyMessageListeners.remove(listener); } public void execute(Runnable task) { executorService.execute(task); } public void connectTcp(InetSocketAddress address, IProtocol protocol) throws IOException { if (address == null) throw new IOException("アドレスエラー"); tcpClient.connect(address, ProtocolConstants.TIMEOUT, protocol); } public void connectUdp(InetSocketAddress address, IProtocol protocol) throws IOException { if (address == null) throw new IOException("アドレスエラー"); udpClient.connect(address, ProtocolConstants.TIMEOUT, protocol); } public IServerRegistry getServerRegistry() { return serverRegistry; } public InetSocketAddress getPortalServer() { String server; if (iniSettings.isPrivatePortalServerUse()) server = iniSettings.getPrivatePortalServerAddress(); else server = portalServerList.next(); return Utility.parseSocketAddress(server); } public void queryPortalServer(final PortalQuery query) { String server; if (iniSettings.isPrivatePortalServerUse()) server = iniSettings.getPrivatePortalServerAddress(); else server = portalServerList.next(); if (Utility.isEmpty(server)) { query.failCallback(new ErrorLog("ポータルサーバーが設定されていません")); return; } final InetSocketAddress address = Utility.parseSocketAddress(server); Runnable task = new Runnable() { @Override public void run() { try { tcpClient.connect(address, ProtocolConstants.TIMEOUT, new IProtocol() { @Override public void log(String message) { arenaWindow.appendToSystemLog(message, true); } @Override public String getProtocol() { return ProtocolConstants.PROTOCOL_PORTAL; } @Override public IProtocolDriver createDriver(final ISocketConnection connection) { connection.send(Utility.encode(query.getCommand())); return new IProtocolDriver() { private String message; @Override public void errorProtocolNumber(String number) { String error = String.format("サーバーとのプロトコルナンバーが一致しないので接続できません サーバー:%s クライアント:%s", number, IProtocol.NUMBER); arenaWindow.appendToSystemLog(error, true); } @Override public ISocketConnection getConnection() { return connection; } @Override public boolean process(PacketData data) { message = data.getMessage(); return false; } @Override public void connectionDisconnected() { if (message != null) query.successCallback(message); else query.failCallback(new ErrorLog("利用可能なサーバーが見つかりません")); } }; } }); } catch (IOException e) { query.failCallback(new ErrorLog(e)); } } }; executorService.execute(task); } private void startEventLoop() { while (isRunning) { if (!SwtUtils.DISPLAY.readAndDispatch()) { SwtUtils.DISPLAY.sleep(); } } try { SwtUtils.DISPLAY.dispose(); } catch (RuntimeException e) { } tcpClient.dispose(); udpClient.dispose(); try { executorService.shutdownNow(); } catch (RuntimeException ex) { } try { iniSettingFile.saveToIni(); } catch (IOException ex) { ex.printStackTrace(); } try { iniAppDataFile.saveToIni(); } catch (IOException ex) { ex.printStackTrace(); } } /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { try { new PlayClient().startEventLoop(); } catch (Exception e) { e.printStackTrace(); } } }