From f6a09b58a4c07f9df98410fa0e82641e444c43e5 Mon Sep 17 00:00:00 2001 From: BetaSteward Date: Sat, 20 Mar 2010 03:50:27 +0000 Subject: [PATCH] Initial --- Mage.Client/build-before-profiler.xml | 74 ++ Mage.Client/build.xml | 109 +++ Mage.Client/manifest.mf | 3 + Mage.Client/nbproject/build-impl.xml | 708 ++++++++++++++++++ Mage.Client/nbproject/genfiles.properties | 11 + Mage.Client/nbproject/profiler-build-impl.xml | 131 ++++ Mage.Client/nbproject/project.properties | 75 ++ Mage.Client/nbproject/project.xml | 41 + Mage.Client/release/config/config.properties | 6 + .../sample-decks/ALA Block Constructed.dck | Bin 0 -> 1034 bytes Mage.Client/release/sample-decks/Jund.dck | Bin 0 -> 1136 bytes .../release/sample-decks/NayaLightsaber.dck | Bin 0 -> 1013 bytes .../release/sample-decks/WhiteTokens.dck | Bin 0 -> 992 bytes Mage.Client/release/startClient.bat | 1 + Mage.Client/release/test.dck | Bin 0 -> 992 bytes Mage.Client/src/mage/client/MageFrame.form | 186 +++++ Mage.Client/src/mage/client/MageFrame.java | 365 +++++++++ Mage.Client/src/mage/client/MagePane.form | 36 + Mage.Client/src/mage/client/MagePane.java | 92 +++ .../src/mage/client/NewPlayerPanel.form | 79 ++ .../src/mage/client/NewPlayerPanel.java | 178 +++++ Mage.Client/src/mage/client/TablesPane.form | 35 + Mage.Client/src/mage/client/TablesPane.java | 93 +++ Mage.Client/src/mage/client/TablesPanel.form | 127 ++++ Mage.Client/src/mage/client/TablesPanel.java | 384 ++++++++++ .../src/mage/client/cards/BigCard.form | 61 ++ .../src/mage/client/cards/BigCard.java | 129 ++++ Mage.Client/src/mage/client/cards/Card.form | 67 ++ Mage.Client/src/mage/client/cards/Card.java | 365 +++++++++ .../mage/client/cards/CardEventSource.java | 59 ++ Mage.Client/src/mage/client/cards/Cards.form | 49 ++ Mage.Client/src/mage/client/cards/Cards.java | 98 +++ .../src/mage/client/cards/CardsList.form | 42 ++ .../src/mage/client/cards/CardsList.java | 146 ++++ .../src/mage/client/cards/Permanent.form | 20 + .../src/mage/client/cards/Permanent.java | 198 +++++ .../src/mage/client/chat/ChatClientImpl.java | 85 +++ .../src/mage/client/chat/ChatPanel.form | 61 ++ .../src/mage/client/chat/ChatPanel.java | 135 ++++ .../mage/client/deckeditor/CardSelector.form | 118 +++ .../mage/client/deckeditor/CardSelector.java | 255 +++++++ .../src/mage/client/deckeditor/DeckArea.form | 53 ++ .../src/mage/client/deckeditor/DeckArea.java | 95 +++ .../client/deckeditor/DeckEditorPane.form | 35 + .../client/deckeditor/DeckEditorPane.java | 86 +++ .../client/deckeditor/DeckEditorPanel.form | 163 ++++ .../client/deckeditor/DeckEditorPanel.java | 308 ++++++++ .../src/mage/client/dialog/AboutDialog.form | 98 +++ .../src/mage/client/dialog/AboutDialog.java | 140 ++++ .../src/mage/client/dialog/CombatDialog.form | 42 ++ .../src/mage/client/dialog/CombatDialog.java | 115 +++ .../src/mage/client/dialog/ConnectDialog.form | 133 ++++ .../src/mage/client/dialog/ConnectDialog.java | 203 +++++ .../mage/client/dialog/ExileZoneDialog.form | 38 + .../mage/client/dialog/ExileZoneDialog.java | 105 +++ .../mage/client/dialog/JoinTableDialog.form | 66 ++ .../mage/client/dialog/JoinTableDialog.java | 159 ++++ .../src/mage/client/dialog/MageDialog.form | 31 + .../src/mage/client/dialog/MageDialog.java | 178 +++++ .../mage/client/dialog/NewTableDialog.form | 144 ++++ .../mage/client/dialog/NewTableDialog.java | 272 +++++++ .../mage/client/dialog/PickChoiceDialog.form | 100 +++ .../mage/client/dialog/PickChoiceDialog.java | 150 ++++ .../mage/client/dialog/PickNumberDialog.form | 76 ++ .../mage/client/dialog/PickNumberDialog.java | 144 ++++ .../mage/client/dialog/QuestionDialog.form | 75 ++ .../mage/client/dialog/QuestionDialog.java | 137 ++++ .../mage/client/dialog/ShowCardsDialog.form | 42 ++ .../mage/client/dialog/ShowCardsDialog.java | 148 ++++ .../client/dialog/TableWaitingDialog.form | 119 +++ .../client/dialog/TableWaitingDialog.java | 311 ++++++++ .../src/mage/client/game/AbilityPicker.java | 85 +++ .../mage/client/game/BattlefieldPanel.form | 20 + .../mage/client/game/BattlefieldPanel.java | 207 +++++ .../src/mage/client/game/CombatGroup.form | 48 ++ .../src/mage/client/game/CombatGroup.java | 115 +++ .../src/mage/client/game/FeedbackPanel.form | 96 +++ .../src/mage/client/game/FeedbackPanel.java | 253 +++++++ .../src/mage/client/game/GamePane.form | 41 + .../src/mage/client/game/GamePane.java | 97 +++ .../src/mage/client/game/GamePanel.form | 430 +++++++++++ .../src/mage/client/game/GamePanel.java | 597 +++++++++++++++ .../src/mage/client/game/ManaPool.form | 174 +++++ .../src/mage/client/game/ManaPool.java | 189 +++++ .../src/mage/client/game/PlayAreaPanel.form | 90 +++ .../src/mage/client/game/PlayAreaPanel.java | 142 ++++ .../src/mage/client/game/PlayerPanel.form | 156 ++++ .../src/mage/client/game/PlayerPanel.java | 208 +++++ .../src/mage/client/remote/ClientImpl.java | 97 +++ .../mage/client/remote/GameClientImpl.java | 151 ++++ .../client/remote/GameReplayClientImpl.java | 87 +++ .../client/remote/MageRemoteException.java | 37 + .../src/mage/client/remote/Session.java | 491 ++++++++++++ .../src/mage/client/util/ButtonColumn.java | 132 ++++ Mage.Client/src/mage/client/util/Config.java | 87 +++ .../src/mage/client/util/Constants.java | 88 +++ Mage.Client/src/mage/client/util/Event.java | 53 ++ .../src/mage/client/util/EventDispatcher.java | 62 ++ .../src/mage/client/util/EventSource.java | 42 ++ Mage.Client/src/mage/client/util/Frames.java | 60 ++ .../src/mage/client/util/ImageHelper.java | 200 +++++ .../src/mage/client/util/Listener.java | 39 + Mage.Client/src/mage/client/util/Symbols.java | 96 +++ .../client/util/resources/config.properties | 6 + .../resources/images/cards/frame/8 black.png | Bin 0 -> 26072 bytes .../resources/images/cards/frame/8 blue.png | Bin 0 -> 24813 bytes .../resources/images/cards/frame/8 gold.png | Bin 0 -> 26658 bytes .../resources/images/cards/frame/8 green.png | Bin 0 -> 24540 bytes .../resources/images/cards/frame/8 grey.png | Bin 0 -> 20449 bytes .../images/cards/frame/8 land mana black.png | Bin 0 -> 31103 bytes .../images/cards/frame/8 land mana blue.png | Bin 0 -> 31175 bytes .../images/cards/frame/8 land mana green.png | Bin 0 -> 31241 bytes .../images/cards/frame/8 land mana red.png | Bin 0 -> 31169 bytes .../images/cards/frame/8 land mana white.png | Bin 0 -> 31253 bytes .../resources/images/cards/frame/8 red.png | Bin 0 -> 27010 bytes .../resources/images/cards/frame/8 white.png | Bin 0 -> 25700 bytes .../powerbox/graphic_card_powerbox_a_left.png | Bin 0 -> 418 bytes .../graphic_card_powerbox_a_middle.png | Bin 0 -> 1299 bytes .../graphic_card_powerbox_a_right.png | Bin 0 -> 429 bytes .../resources/images/symbols/black_green.png | Bin 0 -> 983 bytes .../resources/images/symbols/black_red.png | Bin 0 -> 956 bytes .../resources/images/symbols/blue_black.png | Bin 0 -> 972 bytes .../resources/images/symbols/blue_red.png | Bin 0 -> 1008 bytes .../resources/images/symbols/colorless_0.png | Bin 0 -> 1355 bytes .../resources/images/symbols/colorless_1.png | Bin 0 -> 952 bytes .../resources/images/symbols/colorless_10.png | Bin 0 -> 1289 bytes .../resources/images/symbols/colorless_11.png | Bin 0 -> 961 bytes .../resources/images/symbols/colorless_12.png | Bin 0 -> 1240 bytes .../resources/images/symbols/colorless_13.png | Bin 0 -> 1287 bytes .../resources/images/symbols/colorless_14.png | Bin 0 -> 1097 bytes .../resources/images/symbols/colorless_15.png | Bin 0 -> 1154 bytes .../resources/images/symbols/colorless_16.png | Bin 0 -> 1307 bytes .../resources/images/symbols/colorless_2.png | Bin 0 -> 1290 bytes .../resources/images/symbols/colorless_3.png | Bin 0 -> 1351 bytes .../resources/images/symbols/colorless_4.png | Bin 0 -> 1109 bytes .../resources/images/symbols/colorless_5.png | Bin 0 -> 1180 bytes .../resources/images/symbols/colorless_6.png | Bin 0 -> 1388 bytes .../resources/images/symbols/colorless_7.png | Bin 0 -> 1151 bytes .../resources/images/symbols/colorless_8.png | Bin 0 -> 1464 bytes .../resources/images/symbols/colorless_9.png | Bin 0 -> 1397 bytes .../resources/images/symbols/colorless_x.png | Bin 0 -> 1316 bytes .../resources/images/symbols/green_blue.png | Bin 0 -> 999 bytes .../resources/images/symbols/green_white.png | Bin 0 -> 1036 bytes .../resources/images/symbols/mana_black.png | Bin 0 -> 770 bytes .../resources/images/symbols/mana_blue.png | Bin 0 -> 810 bytes .../resources/images/symbols/mana_green.png | Bin 0 -> 800 bytes .../resources/images/symbols/mana_red.png | Bin 0 -> 784 bytes .../resources/images/symbols/mana_white.png | Bin 0 -> 828 bytes .../resources/images/symbols/red_green.png | Bin 0 -> 1007 bytes .../resources/images/symbols/red_white.png | Bin 0 -> 1032 bytes .../resources/images/symbols/two_black.png | Bin 0 -> 1243 bytes .../resources/images/symbols/two_blue.png | Bin 0 -> 1233 bytes .../resources/images/symbols/two_green.png | Bin 0 -> 1231 bytes .../util/resources/images/symbols/two_red.png | Bin 0 -> 1220 bytes .../resources/images/symbols/two_white.png | Bin 0 -> 1211 bytes .../resources/images/symbols/white_black.png | Bin 0 -> 1001 bytes .../resources/images/symbols/white_blue.png | Bin 0 -> 1020 bytes 157 files changed, 13064 insertions(+) create mode 100644 Mage.Client/build-before-profiler.xml create mode 100644 Mage.Client/build.xml create mode 100644 Mage.Client/manifest.mf create mode 100644 Mage.Client/nbproject/build-impl.xml create mode 100644 Mage.Client/nbproject/genfiles.properties create mode 100644 Mage.Client/nbproject/profiler-build-impl.xml create mode 100644 Mage.Client/nbproject/project.properties create mode 100644 Mage.Client/nbproject/project.xml create mode 100644 Mage.Client/release/config/config.properties create mode 100644 Mage.Client/release/sample-decks/ALA Block Constructed.dck create mode 100644 Mage.Client/release/sample-decks/Jund.dck create mode 100644 Mage.Client/release/sample-decks/NayaLightsaber.dck create mode 100644 Mage.Client/release/sample-decks/WhiteTokens.dck create mode 100644 Mage.Client/release/startClient.bat create mode 100644 Mage.Client/release/test.dck create mode 100644 Mage.Client/src/mage/client/MageFrame.form create mode 100644 Mage.Client/src/mage/client/MageFrame.java create mode 100644 Mage.Client/src/mage/client/MagePane.form create mode 100644 Mage.Client/src/mage/client/MagePane.java create mode 100644 Mage.Client/src/mage/client/NewPlayerPanel.form create mode 100644 Mage.Client/src/mage/client/NewPlayerPanel.java create mode 100644 Mage.Client/src/mage/client/TablesPane.form create mode 100644 Mage.Client/src/mage/client/TablesPane.java create mode 100644 Mage.Client/src/mage/client/TablesPanel.form create mode 100644 Mage.Client/src/mage/client/TablesPanel.java create mode 100644 Mage.Client/src/mage/client/cards/BigCard.form create mode 100644 Mage.Client/src/mage/client/cards/BigCard.java create mode 100644 Mage.Client/src/mage/client/cards/Card.form create mode 100644 Mage.Client/src/mage/client/cards/Card.java create mode 100644 Mage.Client/src/mage/client/cards/CardEventSource.java create mode 100644 Mage.Client/src/mage/client/cards/Cards.form create mode 100644 Mage.Client/src/mage/client/cards/Cards.java create mode 100644 Mage.Client/src/mage/client/cards/CardsList.form create mode 100644 Mage.Client/src/mage/client/cards/CardsList.java create mode 100644 Mage.Client/src/mage/client/cards/Permanent.form create mode 100644 Mage.Client/src/mage/client/cards/Permanent.java create mode 100644 Mage.Client/src/mage/client/chat/ChatClientImpl.java create mode 100644 Mage.Client/src/mage/client/chat/ChatPanel.form create mode 100644 Mage.Client/src/mage/client/chat/ChatPanel.java create mode 100644 Mage.Client/src/mage/client/deckeditor/CardSelector.form create mode 100644 Mage.Client/src/mage/client/deckeditor/CardSelector.java create mode 100644 Mage.Client/src/mage/client/deckeditor/DeckArea.form create mode 100644 Mage.Client/src/mage/client/deckeditor/DeckArea.java create mode 100644 Mage.Client/src/mage/client/deckeditor/DeckEditorPane.form create mode 100644 Mage.Client/src/mage/client/deckeditor/DeckEditorPane.java create mode 100644 Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.form create mode 100644 Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.java create mode 100644 Mage.Client/src/mage/client/dialog/AboutDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/AboutDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/CombatDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/CombatDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/ConnectDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/ConnectDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/ExileZoneDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/ExileZoneDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/JoinTableDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/JoinTableDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/MageDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/MageDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/NewTableDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/NewTableDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/PickChoiceDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/PickChoiceDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/PickNumberDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/PickNumberDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/QuestionDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/QuestionDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/ShowCardsDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/ShowCardsDialog.java create mode 100644 Mage.Client/src/mage/client/dialog/TableWaitingDialog.form create mode 100644 Mage.Client/src/mage/client/dialog/TableWaitingDialog.java create mode 100644 Mage.Client/src/mage/client/game/AbilityPicker.java create mode 100644 Mage.Client/src/mage/client/game/BattlefieldPanel.form create mode 100644 Mage.Client/src/mage/client/game/BattlefieldPanel.java create mode 100644 Mage.Client/src/mage/client/game/CombatGroup.form create mode 100644 Mage.Client/src/mage/client/game/CombatGroup.java create mode 100644 Mage.Client/src/mage/client/game/FeedbackPanel.form create mode 100644 Mage.Client/src/mage/client/game/FeedbackPanel.java create mode 100644 Mage.Client/src/mage/client/game/GamePane.form create mode 100644 Mage.Client/src/mage/client/game/GamePane.java create mode 100644 Mage.Client/src/mage/client/game/GamePanel.form create mode 100644 Mage.Client/src/mage/client/game/GamePanel.java create mode 100644 Mage.Client/src/mage/client/game/ManaPool.form create mode 100644 Mage.Client/src/mage/client/game/ManaPool.java create mode 100644 Mage.Client/src/mage/client/game/PlayAreaPanel.form create mode 100644 Mage.Client/src/mage/client/game/PlayAreaPanel.java create mode 100644 Mage.Client/src/mage/client/game/PlayerPanel.form create mode 100644 Mage.Client/src/mage/client/game/PlayerPanel.java create mode 100644 Mage.Client/src/mage/client/remote/ClientImpl.java create mode 100644 Mage.Client/src/mage/client/remote/GameClientImpl.java create mode 100644 Mage.Client/src/mage/client/remote/GameReplayClientImpl.java create mode 100644 Mage.Client/src/mage/client/remote/MageRemoteException.java create mode 100644 Mage.Client/src/mage/client/remote/Session.java create mode 100644 Mage.Client/src/mage/client/util/ButtonColumn.java create mode 100644 Mage.Client/src/mage/client/util/Config.java create mode 100644 Mage.Client/src/mage/client/util/Constants.java create mode 100644 Mage.Client/src/mage/client/util/Event.java create mode 100644 Mage.Client/src/mage/client/util/EventDispatcher.java create mode 100644 Mage.Client/src/mage/client/util/EventSource.java create mode 100644 Mage.Client/src/mage/client/util/Frames.java create mode 100644 Mage.Client/src/mage/client/util/ImageHelper.java create mode 100644 Mage.Client/src/mage/client/util/Listener.java create mode 100644 Mage.Client/src/mage/client/util/Symbols.java create mode 100644 Mage.Client/src/mage/client/util/resources/config.properties create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 black.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 blue.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 gold.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 green.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 grey.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana black.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana blue.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana green.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana red.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana white.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 red.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/frame/8 white.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/powerbox/graphic_card_powerbox_a_left.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/powerbox/graphic_card_powerbox_a_middle.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/cards/powerbox/graphic_card_powerbox_a_right.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/black_green.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/black_red.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/blue_black.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/blue_red.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_0.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_1.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_10.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_11.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_12.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_13.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_14.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_15.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_16.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_2.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_3.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_4.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_5.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_6.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_7.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_8.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_9.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/colorless_x.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/green_blue.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/green_white.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/mana_black.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/mana_blue.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/mana_green.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/mana_red.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/mana_white.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/red_green.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/red_white.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/two_black.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/two_blue.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/two_green.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/two_red.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/two_white.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/white_black.png create mode 100644 Mage.Client/src/mage/client/util/resources/images/symbols/white_blue.png diff --git a/Mage.Client/build-before-profiler.xml b/Mage.Client/build-before-profiler.xml new file mode 100644 index 00000000000..b40b33eb728 --- /dev/null +++ b/Mage.Client/build-before-profiler.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + Builds, tests, and runs the project Mage.Client. + + + diff --git a/Mage.Client/build.xml b/Mage.Client/build.xml new file mode 100644 index 00000000000..a4e5ae988f6 --- /dev/null +++ b/Mage.Client/build.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + Builds, tests, and runs the project Mage.Client. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/manifest.mf b/Mage.Client/manifest.mf new file mode 100644 index 00000000000..1574df4a2de --- /dev/null +++ b/Mage.Client/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/Mage.Client/nbproject/build-impl.xml b/Mage.Client/nbproject/build-impl.xml new file mode 100644 index 00000000000..ee131412af5 --- /dev/null +++ b/Mage.Client/nbproject/build-impl.xml @@ -0,0 +1,708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/nbproject/genfiles.properties b/Mage.Client/nbproject/genfiles.properties new file mode 100644 index 00000000000..6a0c7889ca2 --- /dev/null +++ b/Mage.Client/nbproject/genfiles.properties @@ -0,0 +1,11 @@ +build.xml.data.CRC32=661539d5 +build.xml.script.CRC32=a8618a63 +build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=ab5db5cf +nbproject/build-impl.xml.script.CRC32=268965d9 +nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45 +nbproject/profiler-build-impl.xml.data.CRC32=661539d5 +nbproject/profiler-build-impl.xml.script.CRC32=abda56ed +nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf@1.6.1 diff --git a/Mage.Client/nbproject/profiler-build-impl.xml b/Mage.Client/nbproject/profiler-build-impl.xml new file mode 100644 index 00000000000..300ea407597 --- /dev/null +++ b/Mage.Client/nbproject/profiler-build-impl.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + Must select one file in the IDE or set profile.class + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/nbproject/project.properties b/Mage.Client/nbproject/project.properties new file mode 100644 index 00000000000..f1d78945c61 --- /dev/null +++ b/Mage.Client/nbproject/project.properties @@ -0,0 +1,75 @@ +application.title=MageClient +application.vendor=BetaSteward_at_googlemail.com +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/Mage.Client.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath=\ + ${reference.Mage_Common.jar}:\ + ${reference.Mage.jar}:\ + ${reference.Mage_Sets.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.6 +javac.target=1.6 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=mage.client.MageFrame +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +project.license=bsd +project.Mage=../Mage +project.Mage_Common=../Mage.Common +project.Mage_Sets=../Mage.Sets +reference.Mage.jar=${project.Mage}/dist/Mage.jar +reference.Mage_Common.jar=${project.Mage_Common}/dist/Mage.Common.jar +reference.Mage_Sets.jar=${project.Mage_Sets}/dist/Mage.Sets.jar +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs=-Xmx512m +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test +app.version=0.1 diff --git a/Mage.Client/nbproject/project.xml b/Mage.Client/nbproject/project.xml new file mode 100644 index 00000000000..7ec054b48bc --- /dev/null +++ b/Mage.Client/nbproject/project.xml @@ -0,0 +1,41 @@ + + + org.netbeans.modules.java.j2seproject + + + Mage.Client + + + + + + + + + + Mage + jar + + jar + clean + jar + + + Mage_Common + jar + + jar + clean + jar + + + Mage_Sets + jar + + jar + clean + jar + + + + diff --git a/Mage.Client/release/config/config.properties b/Mage.Client/release/config/config.properties new file mode 100644 index 00000000000..7c8e6bc7d45 --- /dev/null +++ b/Mage.Client/release/config/config.properties @@ -0,0 +1,6 @@ +server-name=localhost +port=17171 +remote-server=mage-server +cards-resource-path=resources/images/cards/ +symbols-resource-path=resources/images/symbols/ +resource-path=resources/images/ \ No newline at end of file diff --git a/Mage.Client/release/sample-decks/ALA Block Constructed.dck b/Mage.Client/release/sample-decks/ALA Block Constructed.dck new file mode 100644 index 0000000000000000000000000000000000000000..2b9a0df7b6d460e79a3c8c2473cee9167d5f3dc4 GIT binary patch literal 1034 zcmZ{jzi!k(5XL9u0wnwk2>~JTCj<}(B%hGzpgCVa0y!w+B1A(mXV2Not#{4tI58AR zJO%}Cz{ycM1#@T)a6vVuosjXU1=$-PdXmJa4DFX6c^D`ZOHNiuQ~A-7;Xi1Kk9j{vVBzA zV2R#!GJxT7aCI4bx>k%rwJED!+JWI_koE&6ZZ0_`sIvA9Yu?m>;bJg#^(RMIR&DW9 zUe}>lyd98n(>E%LrPkThpva!cnb)5VV7L>C_dAM>vz5rSYcSW!d(H$f+z7_SwEf!M zf0huXg;$>qV7T{h%cLSHr-pD&CZ>W)&8_zw!`hwc59^agTk#FHa=!OfZ=v< zF18m7u1leGZDWa+z2kffhMnN(XT?(F1uGZkl^X%Qg;`A5Lz0$_F86C`$s0BU7_Nt; zMb`lt*P5HS*Io$t?_pk%%4t^1moycoo7q;wur*3X+wRuW`Sw^V*GHW)b$jKX6toX( Gt@#7WyH9ig literal 0 HcmV?d00001 diff --git a/Mage.Client/release/sample-decks/Jund.dck b/Mage.Client/release/sample-decks/Jund.dck new file mode 100644 index 0000000000000000000000000000000000000000..68639251c3e2ba6eadd57236b0fef82c42628715 GIT binary patch literal 1136 zcmZ`&%T5$Q6uroxfT#!tB=Hg7u6n?@(~Uj&OcMx0z>SML(=|QiR9B5vw_#*q;%B(< z5Bv}J{)ZcPuC#8AQnZoHNplO>6-JnvcU6rLIe&ciig5{_np{budGgdfS3eCe$`Va3iw)=}*XQW2oc3^OjG`wzClkZbgaf^B_zQ z6MXCn|SMbWsl_5qf|5PXh#b2ZXj=p(Y9; zte>3KNveE_9g8x5s(Q>nAA#Ur3{$TlwO&>tiSd|NbD>6$J=*Yn6n2wax+his!cT(f z^R<>9kF-_!1W`ASGs{hIkKkQs+1EfxEz4s`u_zx!urnm88dBVM9_HUH$7|?|F{r- H-`UY`bJKLC literal 0 HcmV?d00001 diff --git a/Mage.Client/release/sample-decks/NayaLightsaber.dck b/Mage.Client/release/sample-decks/NayaLightsaber.dck new file mode 100644 index 0000000000000000000000000000000000000000..22475881a2e078d266c2f7ff41d36d871352bb0e GIT binary patch literal 1013 zcmaKr%We}f6oyY}3Z-0HwOoXtTm?&~MeJaclyH$IX_Z8U4U01~&Wu~v4)#ep=>mzz zV8I*k9_)D!Htbk|?Fg)*gw3ZJ`8)sd^~-lyvIcG+VZm93Cbul-*`a069e3P+A}rY_ z$*=K`cej3?fyD%tf<~~G9N-x1BNDRit)~gp6drMc_34O2Rn&WAgeu(Fc`I_BY8Uw) zKEOgXbZs|$0`m#1VGK@uO!e{G=BKatc@Y*~L(Pg4UJU`@*>TPBEy2w&Rm;h;6RvV` zh{hF*yv;58sBSPVAIv zHISo{Wyoy zk#B^|JD4Gb#jg9rDF`0Ut6 z{sI4kp8r8ZM+LigQBIbeistD~`{wPNd9&Yt!HTnRe~c-K7;WN2Lh;CnR~}pbKa!5! zv*_>i_s4sGF2HgGD3R)ws$Tyzq|$rUOW@v^b9|Q2ON&$TowgN?eGH}J^~Kbd(MJ=q#=4%O zBrS8_2+|dtvny|nHhviXir&PQHJhQPg1Js(qlaoz2){HeQMJq@XLz)5VBJF{r_$(s x|1yHwtr8Zh^^miHX&16u)Z2ksLBX)m@$Q}+hm;=<%!srr2M`_#l+R_Y_y>G5I^+NV literal 0 HcmV?d00001 diff --git a/Mage.Client/release/startClient.bat b/Mage.Client/release/startClient.bat new file mode 100644 index 00000000000..afadd24cca2 --- /dev/null +++ b/Mage.Client/release/startClient.bat @@ -0,0 +1 @@ +start javaw -jar .\MageClient.jar \ No newline at end of file diff --git a/Mage.Client/release/test.dck b/Mage.Client/release/test.dck new file mode 100644 index 0000000000000000000000000000000000000000..1a0bc8e5104a69fb902b3a0667be2896ad22bdb0 GIT binary patch literal 992 zcmbtTJ#Q015S6 z{sI4kp8r8ZM+LigQBIbeistD~`{wPNd9&Yt!HTnRe~c-K7;WN2Lh;CnR~}pbKa!5! zv*_>i_s4sGF2HgGD3R)ws$Tyzq|$rUOW@v^b9|Q2ON&$TowgN?eGH}J^~Kbd(MJ=q#=4%O zBrS8_2+|dtvny|nHhviXir&PQHJhQPg1Js(qlaoz2){HeQMJq@XLz)5VBJF{r_$(s x|1yHwtr8Zh^^miHX&16u)Z2ksLBX)m@$Q}+hm;=<%!srr2M`_#l+R_Y_y>G5I^+NV literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/MageFrame.form b/Mage.Client/src/mage/client/MageFrame.form new file mode 100644 index 00000000000..372679d87c5 --- /dev/null +++ b/Mage.Client/src/mage/client/MageFrame.form @@ -0,0 +1,186 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/MageFrame.java b/Mage.Client/src/mage/client/MageFrame.java new file mode 100644 index 00000000000..98acc6fde12 --- /dev/null +++ b/Mage.Client/src/mage/client/MageFrame.java @@ -0,0 +1,365 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * MageFrame.java + * + * Created on 15-Dec-2009, 9:11:37 PM + */ + +package mage.client; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JDesktopPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import mage.cards.decks.Deck; +import mage.client.dialog.AboutDialog; +import mage.client.dialog.ConnectDialog; +import mage.client.remote.Session; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class MageFrame extends javax.swing.JFrame { + + private final static Logger logger = Logging.getLogger(MageFrame.class.getName()); + + private static Session session; + private ConnectDialog connectDialog; + + /** + * @return the session + */ + public static Session getSession() { + return session; + } + + public static JDesktopPane getDesktop() { + return desktopPane; + } + + /** Creates new form MageFrame */ + public MageFrame() { + + addWindowListener(new WindowAdapter() + { + @Override + public void windowClosing(WindowEvent e) + { + exitApp(); + } + }); + + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } + + + initComponents(); + + session = new Session(this); + connectDialog = new ConnectDialog(session); + desktopPane.add(connectDialog); + disableButtons(); + } + + public void showGame(UUID gameId, UUID playerId) { + logger.info("showing game"); + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.gamePane.setVisible(true); + this.gamePane.showGame(gameId, playerId); + } + + public void watchGame(UUID gameId) { + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.gamePane.setVisible(true); + this.gamePane.watchGame(gameId); + } + + public void replayGame(UUID gameId) { + this.tablesPane.hideTables(); + this.tablesPane.setVisible(false); + this.gamePane.setVisible(true); + this.gamePane.replayGame(gameId); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + desktopPane = new javax.swing.JDesktopPane(); + tablesPane = new mage.client.TablesPane(); + gamePane = new mage.client.game.GamePane(); + deckEditorPane = new mage.client.deckeditor.DeckEditorPane(); + mageToolbar = new javax.swing.JToolBar(); + btnConnect = new javax.swing.JButton(); + jSeparator4 = new javax.swing.JToolBar.Separator(); + btnGames = new javax.swing.JButton(); + jSeparator3 = new javax.swing.JToolBar.Separator(); + btnDeckEditor = new javax.swing.JButton(); + jSeparator2 = new javax.swing.JToolBar.Separator(); + btnAbout = new javax.swing.JButton(); + jSeparator1 = new javax.swing.JToolBar.Separator(); + btnExit = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + setMinimumSize(new java.awt.Dimension(1024, 768)); + + desktopPane.setBackground(new java.awt.Color(204, 204, 204)); + tablesPane.setBounds(20, 10, 560, 440); + desktopPane.add(tablesPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + tablesPane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + gamePane.setBounds(20, 30, -1, -1); + desktopPane.add(gamePane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + gamePane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + deckEditorPane.setBounds(140, 50, -1, -1); + desktopPane.add(deckEditorPane, javax.swing.JLayeredPane.DEFAULT_LAYER); + try { + deckEditorPane.setMaximum(true); + } catch (java.beans.PropertyVetoException e1) { + e1.printStackTrace(); + } + + mageToolbar.setFloatable(false); + mageToolbar.setRollover(true); + + btnConnect.setText("Connect"); + btnConnect.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnConnect.setFocusable(false); + btnConnect.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnConnect.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnConnect.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnConnectActionPerformed(evt); + } + }); + mageToolbar.add(btnConnect); + mageToolbar.add(jSeparator4); + + btnGames.setText("Tables"); + btnGames.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnGames.setFocusable(false); + btnGames.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnGames.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnGames.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnGamesActionPerformed(evt); + } + }); + mageToolbar.add(btnGames); + mageToolbar.add(jSeparator3); + + btnDeckEditor.setText("Deck Editor"); + btnDeckEditor.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnDeckEditor.setFocusable(false); + btnDeckEditor.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnDeckEditor.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnDeckEditor.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnDeckEditorActionPerformed(evt); + } + }); + mageToolbar.add(btnDeckEditor); + mageToolbar.add(jSeparator2); + + btnAbout.setText("About"); + btnAbout.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnAbout.setFocusable(false); + btnAbout.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnAbout.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnAbout.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnAboutActionPerformed(evt); + } + }); + mageToolbar.add(btnAbout); + mageToolbar.add(jSeparator1); + + btnExit.setText("Exit"); + btnExit.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); + btnExit.setFocusable(false); + btnExit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + btnExit.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + btnExit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnExitActionPerformed(evt); + } + }); + mageToolbar.add(btnExit); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(mageToolbar, javax.swing.GroupLayout.DEFAULT_SIZE, 1106, Short.MAX_VALUE) + .addComponent(desktopPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1106, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(mageToolbar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(desktopPane, javax.swing.GroupLayout.DEFAULT_SIZE, 840, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnDeckEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDeckEditorActionPerformed + this.gamePane.setVisible(false); + this.tablesPane.setVisible(false); + this.deckEditorPane.setVisible(true); + this.deckEditorPane.showTables(); + }//GEN-LAST:event_btnDeckEditorActionPerformed + + private void btnGamesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGamesActionPerformed + this.gamePane.setVisible(false); + this.deckEditorPane.setVisible(false); + this.tablesPane.setVisible(true); + this.tablesPane.showTables(); + }//GEN-LAST:event_btnGamesActionPerformed + + private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExitActionPerformed + exitApp(); + }//GEN-LAST:event_btnExitActionPerformed + + private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed + connectDialog.showDialog(); + }//GEN-LAST:event_btnConnectActionPerformed + + private void btnAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAboutActionPerformed + AboutDialog aboutDialog = new AboutDialog(); + desktopPane.add(aboutDialog); + aboutDialog.showDialog(); + }//GEN-LAST:event_btnAboutActionPerformed + + private void exitApp() { + session.disconnect(); + dispose(); + System.exit(0); + } + + public void enableButtons() { + btnConnect.setEnabled(false); + btnGames.setEnabled(true); + btnDeckEditor.setEnabled(true); + } + + public void disableButtons() { + btnConnect.setEnabled(true); + btnGames.setEnabled(false); + btnDeckEditor.setEnabled(true); + this.tablesPane.setVisible(false); + this.gamePane.setVisible(false); + this.deckEditorPane.setVisible(false); + } + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + logger.log(Level.SEVERE, null, e); + } + }); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new MageFrame().setVisible(true); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnAbout; + private javax.swing.JButton btnConnect; + private javax.swing.JButton btnDeckEditor; + private javax.swing.JButton btnExit; + private javax.swing.JButton btnGames; + private mage.client.deckeditor.DeckEditorPane deckEditorPane; + private static javax.swing.JDesktopPane desktopPane; + private mage.client.game.GamePane gamePane; + private javax.swing.JToolBar.Separator jSeparator1; + private javax.swing.JToolBar.Separator jSeparator2; + private javax.swing.JToolBar.Separator jSeparator3; + private javax.swing.JToolBar.Separator jSeparator4; + private javax.swing.JToolBar mageToolbar; + private mage.client.TablesPane tablesPane; + // End of variables declaration//GEN-END:variables + + private void createDeck() { + Deck deck = new Deck(); + deck.getCards().add(new mage.sets.shardsofalara.BroodmateDragon(null)); + deck.getCards().add(new mage.sets.shardsofalara.BroodmateDragon(null)); + deck.getCards().add(new mage.sets.alarareborn.BloodbraidElf(null)); + deck.getCards().add(new mage.sets.alarareborn.BloodbraidElf(null)); + deck.getCards().add(new mage.sets.shardsofalara.JundPanorama(null)); + deck.getCards().add(new mage.sets.shardsofalara.JundPanorama(null)); + deck.getCards().add(new mage.sets.alarareborn.VengefulRebirth(null)); + deck.getCards().add(new mage.sets.alarareborn.VengefulRebirth(null)); + deck.getCards().add(new mage.sets.shardsofalara.SproutingThrinax(null)); + deck.getCards().add(new mage.sets.shardsofalara.SproutingThrinax(null)); + deck.getCards().add(new mage.sets.shardsofalara.SarkhanVol(null)); + deck.getCards().add(new mage.sets.shardsofalara.SarkhanVol(null)); + deck.getCards().add(new mage.sets.alarareborn.MaelstromPulse(null)); + deck.getCards().add(new mage.sets.alarareborn.MaelstromPulse(null)); + try { + deck.getDeckCardLists().save("test.dck"); + } catch (FileNotFoundException ex) { + logger.log(Level.SEVERE, null, ex); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } +} diff --git a/Mage.Client/src/mage/client/MagePane.form b/Mage.Client/src/mage/client/MagePane.form new file mode 100644 index 00000000000..725f5d510d5 --- /dev/null +++ b/Mage.Client/src/mage/client/MagePane.form @@ -0,0 +1,36 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/MagePane.java b/Mage.Client/src/mage/client/MagePane.java new file mode 100644 index 00000000000..5e18f881138 --- /dev/null +++ b/Mage.Client/src/mage/client/MagePane.java @@ -0,0 +1,92 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * MagePane.java + * + * Created on 15-Dec-2009, 9:34:25 PM + */ + +package mage.client; + +import javax.swing.plaf.basic.BasicInternalFrameUI; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class MagePane extends javax.swing.JInternalFrame { + + /** Creates new form MagePane */ + public MagePane() { + initComponents(); + hideTitle(); + } + + private void hideTitle() { + if (ui instanceof BasicInternalFrameUI) + ((BasicInternalFrameUI) ui).setNorthPane(null); + } + + @Override + public void updateUI() { + super.updateUI(); + hideTitle(); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setBorder(null); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 765, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 476, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/NewPlayerPanel.form b/Mage.Client/src/mage/client/NewPlayerPanel.form new file mode 100644 index 00000000000..836e8fbe281 --- /dev/null +++ b/Mage.Client/src/mage/client/NewPlayerPanel.form @@ -0,0 +1,79 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/NewPlayerPanel.java b/Mage.Client/src/mage/client/NewPlayerPanel.java new file mode 100644 index 00000000000..e737e69f029 --- /dev/null +++ b/Mage.Client/src/mage/client/NewPlayerPanel.java @@ -0,0 +1,178 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * NewPlayerPanel.java + * + * Created on 15-Dec-2009, 10:09:46 PM + */ + +package mage.client; + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class NewPlayerPanel extends javax.swing.JPanel { + + private JFileChooser fcSelectDeck; + + /** Creates new form NewPlayerPanel */ + public NewPlayerPanel() { + initComponents(); + fcSelectDeck = new JFileChooser(); + fcSelectDeck.setAcceptAllFileFilterUsed(false); + fcSelectDeck.addChoosableFileFilter(new DeckFilter()); + } + + public void playerLoadDeck() { + int ret = fcSelectDeck.showDialog(this, "Select Deck"); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = fcSelectDeck.getSelectedFile(); + this.txtPlayerDeck.setText(file.getPath()); + } + fcSelectDeck.setSelectedFile(null); + } + + public String getPlayerName() { + return this.txtPlayerName.getText(); + } + + public String getDeckFile() { + return this.txtPlayerDeck.getText(); + } + + public void setPlayerName(String playerName) { + this.txtPlayerName.setText(playerName); + } + + public void setDeckFile(String deckFile) { + this.txtPlayerDeck.setText(deckFile); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblPlayer2Name = new javax.swing.JLabel(); + txtPlayerName = new javax.swing.JTextField(); + lblPlayerDeck = new javax.swing.JLabel(); + txtPlayerDeck = new javax.swing.JTextField(); + btnPlayerDeck = new javax.swing.JButton(); + + lblPlayer2Name.setText("Player Name:"); + + lblPlayerDeck.setText("Player Deck:"); + + btnPlayerDeck.setText("..."); + btnPlayerDeck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPlayerDeckActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblPlayerDeck) + .addComponent(lblPlayer2Name)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtPlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE) + .addComponent(txtPlayerDeck, javax.swing.GroupLayout.DEFAULT_SIZE, 314, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblPlayer2Name) + .addComponent(txtPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblPlayerDeck) + .addComponent(txtPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnPlayerDeck, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void btnPlayerDeckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlayerDeckActionPerformed + playerLoadDeck(); + }//GEN-LAST:event_btnPlayerDeckActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnPlayerDeck; + private javax.swing.JLabel lblPlayer2Name; + private javax.swing.JLabel lblPlayerDeck; + private javax.swing.JTextField txtPlayerDeck; + private javax.swing.JTextField txtPlayerName; + // End of variables declaration//GEN-END:variables + +} + +class DeckFilter extends FileFilter { + + @Override + public boolean accept(File f) { + if (f.isDirectory()) + return true; + + String ext = null; + String s = f.getName(); + int i = s.lastIndexOf('.'); + + if (i > 0 && i < s.length() - 1) { + ext = s.substring(i+1).toLowerCase(); + } + return (ext==null)?false:ext.equals("dck"); + } + + @Override + public String getDescription() { + return "Deck Files"; + } + +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/TablesPane.form b/Mage.Client/src/mage/client/TablesPane.form new file mode 100644 index 00000000000..0eafeec3e87 --- /dev/null +++ b/Mage.Client/src/mage/client/TablesPane.form @@ -0,0 +1,35 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/TablesPane.java b/Mage.Client/src/mage/client/TablesPane.java new file mode 100644 index 00000000000..c5f466e0f13 --- /dev/null +++ b/Mage.Client/src/mage/client/TablesPane.java @@ -0,0 +1,93 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * TablesPane.java + * + * Created on Dec 17, 2009, 9:21:42 AM + */ + +package mage.client; + +import java.util.UUID; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TablesPane extends MagePane { + + /** Creates new form TablesPane */ + public TablesPane() { + initComponents(); + } + + public void showTables() { + UUID roomId = MageFrame.getSession().getMainRoomId(); + if (roomId != null) { + tablesPanel.showTables(roomId); + this.repaint(); + } + } + + public void hideTables() { + tablesPanel.hideTables(); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + tablesPanel = new mage.client.TablesPanel(); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tablesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 541, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(tablesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 471, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.TablesPanel tablesPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/TablesPanel.form b/Mage.Client/src/mage/client/TablesPanel.form new file mode 100644 index 00000000000..a8da09d5bda --- /dev/null +++ b/Mage.Client/src/mage/client/TablesPanel.form @@ -0,0 +1,127 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/TablesPanel.java b/Mage.Client/src/mage/client/TablesPanel.java new file mode 100644 index 00000000000..a228337b646 --- /dev/null +++ b/Mage.Client/src/mage/client/TablesPanel.java @@ -0,0 +1,384 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * TablesPanel.java + * + * Created on 15-Dec-2009, 10:54:01 PM + */ + +package mage.client; + +import mage.client.dialog.NewTableDialog; +import mage.client.dialog.JoinTableDialog; +import mage.client.dialog.TableWaitingDialog; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Observable; +import java.util.Observer; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JOptionPane; +import javax.swing.Timer; +import javax.swing.table.AbstractTableModel; +import mage.Constants; +import mage.cards.decks.DeckCardLists; +import mage.client.remote.MageRemoteException; +import mage.client.remote.Session; +import mage.client.util.ButtonColumn; +import mage.util.Logging; +import mage.view.TableView; + + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TablesPanel extends javax.swing.JPanel implements Observer { + + private final static Logger logger = Logging.getLogger(TablesPanel.class.getName()); + + private TableTableModel tableModel; + private UUID roomId; + private TablesWatchdog tablesWatchdog = new TablesWatchdog(); + private JoinTableDialog joinTableDialog; + private NewTableDialog newTableDialog; + private TableWaitingDialog tableWaitingDialog; + private Session session; + + /** Creates new form TablesPanel */ + public TablesPanel() { + + tableModel = new TableTableModel(); + + initComponents(); + + tableTables.createDefaultColumnsFromModel(); + + Action join = new AbstractAction() + { + public void actionPerformed(ActionEvent e) + { + int modelRow = Integer.valueOf( e.getActionCommand() ); + UUID tableId = UUID.fromString((String)tableModel.getValueAt(modelRow, 0)); + String state = (String)tableModel.getValueAt(modelRow, 4); + + if (state.equals("Join")) { + logger.info("Joining table " + tableId); + + joinTableDialog.showDialog(roomId, tableId); + if (joinTableDialog.isJoined()) + tableWaitingDialog.showDialog(roomId, tableId); + } else if (state.equals("Watch")) { + logger.info("Watching table " + tableId); + if (!session.watchTable(roomId, tableId)) + hideTables(); + } else if (state.equals("Replay")) { + logger.info("Replaying table " + tableId); + if (!session.replayTable(roomId, tableId)) + hideTables(); + } + } + }; + + ButtonColumn buttonColumn = new ButtonColumn(tableTables, join, 4); + + } + + public void update(Observable arg0, Object arg1) { + try { + tableModel.loadData(roomId); + this.tableTables.repaint(); + } catch (MageRemoteException ex) { + hideTables(); + } + } + + public void showTables(UUID roomId) { + + this.roomId = roomId; + session = MageFrame.getSession(); + if (newTableDialog == null) { + newTableDialog = new NewTableDialog(); + MageFrame.getDesktop().add(newTableDialog); + } + if (joinTableDialog == null) { + joinTableDialog = new JoinTableDialog(); + MageFrame.getDesktop().add(joinTableDialog); + } + if (tableWaitingDialog == null) { + tableWaitingDialog = new TableWaitingDialog(); + MageFrame.getDesktop().add(tableWaitingDialog); + } + UUID chatRoomId = session.getRoomChatId(roomId); + if (chatRoomId != null) { + this.chatPanel.connect(session.getRoomChatId(roomId)); + tablesWatchdog.addObserver(this); + this.setVisible(true); + this.repaint(); + } + else { + hideTables(); + } + } + + public void hideTables() { + if (tableWaitingDialog.isVisible()) { + tableWaitingDialog.closeDialog(); + } + tablesWatchdog.deleteObservers(); + this.chatPanel.disconnect(); + this.setVisible(false); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + btnNewTable = new javax.swing.JButton(); + btnQuickStart = new javax.swing.JButton(); + jSplitPane1 = new javax.swing.JSplitPane(); + chatPanel = new mage.client.chat.ChatPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + tableTables = new javax.swing.JTable(); + + btnNewTable.setText("New Table"); + btnNewTable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNewTableActionPerformed(evt); + } + }); + + btnQuickStart.setText("Quick Start"); + btnQuickStart.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnQuickStartActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnNewTable) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnQuickStart) + .addContainerGap(537, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnNewTable) + .addComponent(btnQuickStart)) + .addContainerGap(16, Short.MAX_VALUE)) + ); + + jSplitPane1.setDividerSize(3); + jSplitPane1.setResizeWeight(1.0); + + chatPanel.setMinimumSize(new java.awt.Dimension(100, 43)); + jSplitPane1.setRightComponent(chatPanel); + + tableTables.setModel(this.tableModel); + jScrollPane1.setViewportView(tableTables); + + jSplitPane1.setLeftComponent(jScrollPane1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 721, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 518, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void btnNewTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewTableActionPerformed + newTableDialog.showDialog(roomId); + if (newTableDialog.getTable() != null) { + tableWaitingDialog.showDialog(roomId, newTableDialog.getTable().getTableId()); + } +}//GEN-LAST:event_btnNewTableActionPerformed + + private void btnQuickStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartActionPerformed + TableView table; + try { + List playerTypes = new ArrayList(); + playerTypes.add("Human"); + playerTypes.add("Computer - default"); + table = session.createTable( + roomId, + "Two Player Duel", + Constants.DeckType.CONSTRUCTED_EXTENDED, + playerTypes + ); + session.joinTable( + roomId, + table.getTableId(), + 0, + "Human", + DeckCardLists.load("test.dck") + ); + session.joinTable( + roomId, + table.getTableId(), + 1, + "Computer", + DeckCardLists.load("test.dck") + ); + hideTables(); + session.startGame(roomId, table.getTableId()); + } catch (Exception ex) { + handleError(ex); + } + }//GEN-LAST:event_btnQuickStartActionPerformed + + private void handleError(Exception ex) { + logger.log(Level.SEVERE, "Error loading deck", ex); + JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error loading deck.", "Error", JOptionPane.ERROR_MESSAGE); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnNewTable; + private javax.swing.JButton btnQuickStart; + private mage.client.chat.ChatPanel chatPanel; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JTable tableTables; + // End of variables declaration//GEN-END:variables + +} + +class TableTableModel extends AbstractTableModel { + private String[] columnNames = new String[]{"Game Id", "Game Type", "Deck Type", "Status", "Action"}; + private TableView[] tables = new TableView[0]; + + + public void loadData(UUID roomId) throws MageRemoteException { + tables = MageFrame.getSession().getTables(roomId).toArray(new TableView[0]); + this.fireTableDataChanged(); + } + + @Override + public int getRowCount() { + return tables.length; + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int arg0, int arg1) { + switch (arg1) { + case 0: + return tables[arg0].getTableId().toString(); + case 1: + return tables[arg0].getGameType().toString(); + case 2: + return tables[arg0].getDeckType().toString(); + case 3: + return tables[arg0].getTableState().toString(); + case 4: + switch (tables[arg0].getTableState()) { + case WAITING: + return "Join"; + case DUELING: + return "Watch"; + case FINISHED: + return "Replay"; + default: + return ""; + } + } + return ""; + } + + @Override + public String getColumnName(int columnIndex) { + String colName = ""; + + if (columnIndex <= getColumnCount()) + colName = columnNames[columnIndex]; + + return colName; + } + + @Override + public Class getColumnClass(int columnIndex){ + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + if (columnIndex != 4) + return false; + return true; + } + +} + +class TablesWatchdog extends Observable implements ActionListener { + + Timer t = new Timer(1000, this); // check every second + + public TablesWatchdog() { + t.start(); + } + + public void actionPerformed(ActionEvent arg0) { + setChanged(); + notifyObservers(); + } + +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/cards/BigCard.form b/Mage.Client/src/mage/client/cards/BigCard.form new file mode 100644 index 00000000000..b80ecd45115 --- /dev/null +++ b/Mage.Client/src/mage/client/cards/BigCard.form @@ -0,0 +1,61 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/cards/BigCard.java b/Mage.Client/src/mage/client/cards/BigCard.java new file mode 100644 index 00000000000..5e02fdef07e --- /dev/null +++ b/Mage.Client/src/mage/client/cards/BigCard.java @@ -0,0 +1,129 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * BigCard.java + * + * Created on Jan 18, 2010, 3:21:33 PM + */ + +package mage.client.cards; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.util.List; +import java.util.UUID; +import javax.swing.text.BadLocationException; +import javax.swing.text.StyledDocument; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class BigCard extends javax.swing.JPanel { + + protected Image bigImage; + protected UUID cardId; + + public BigCard() { + initComponents(); + } + + public void setCard(UUID cardId, Image image, List strings) { + if (this.cardId == null || !this.cardId.equals(cardId)) { + this.cardId = cardId; + bigImage = image; + this.repaint(); + drawText(strings); + } + } + + private void drawText(java.util.List strings) { + text.setText(""); + StyledDocument doc = text.getStyledDocument(); + + try { + for (String line: strings) { + doc.insertString(doc.getLength(), line + "\n", doc.getStyle("regular")); + } + } catch (BadLocationException ble) { + System.err.println("Couldn't insert initial text into text pane."); + } + text.setCaretPosition(0); + } + + @Override + public void paintComponent(Graphics graphics) { + if (bigImage != null) + graphics.drawImage(bigImage, 0, 0, this); + super.paintComponent(graphics); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + scrollPane = new javax.swing.JScrollPane(); + text = new javax.swing.JTextPane(); + + setFocusable(false); + setMinimumSize(new Dimension(FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT)); + setOpaque(false); + setPreferredSize(getMinimumSize()); + setLayout(null); + + scrollPane.setBorder(null); + scrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setOpaque(false); + + text.setEditable(false); + text.setFocusable(false); + text.setOpaque(false); + scrollPane.setViewportView(text); + + add(scrollPane); + scrollPane.setBounds(20, 230, 210, 120); + scrollPane.setBounds(new Rectangle(CONTENT_MAX_XOFFSET, TEXT_MAX_YOFFSET, TEXT_MAX_WIDTH, TEXT_MAX_HEIGHT)); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane scrollPane; + private javax.swing.JTextPane text; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/cards/Card.form b/Mage.Client/src/mage/client/cards/Card.form new file mode 100644 index 00000000000..9b3fb336bf3 --- /dev/null +++ b/Mage.Client/src/mage/client/cards/Card.form @@ -0,0 +1,67 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/mage/client/cards/Card.java b/Mage.Client/src/mage/client/cards/Card.java new file mode 100644 index 00000000000..92b11074e0d --- /dev/null +++ b/Mage.Client/src/mage/client/cards/Card.java @@ -0,0 +1,365 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * Card.java + * + * Created on 17-Dec-2009, 9:20:50 PM + */ + +package mage.client.cards; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; +import java.util.UUID; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.Popup; +import javax.swing.PopupFactory; +import javax.swing.text.BadLocationException; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.StyledDocument; +import mage.Constants.CardType; +import mage.client.MageFrame; +import mage.client.remote.Session; +import mage.client.util.ImageHelper; +import mage.view.CardView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Card extends javax.swing.JPanel implements MouseMotionListener, MouseListener, FocusListener { + + protected static Session session = MageFrame.getSession(); + + protected Point p; + + protected UUID gameId; + protected BigCard bigCard; + protected CardView card; + protected Popup popup; + + protected TextPopup popupText = new TextPopup(); + protected BufferedImage background; + protected BufferedImage image = new BufferedImage(FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT, BufferedImage.TYPE_INT_RGB); + protected BufferedImage small = new BufferedImage(FRAME_WIDTH, FRAME_HEIGHT, BufferedImage.TYPE_INT_RGB); + + /** Creates new form Card */ + public Card(CardView card, BigCard bigCard, UUID gameId) { + initComponents(); + + this.gameId = gameId; + this.card = card; + this.bigCard = bigCard; + background = ImageHelper.getBackground(card); + + StyledDocument doc = text.getStyledDocument(); + Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE); + Style regular = doc.addStyle("regular", def); + StyleConstants.setFontFamily(def, "arial"); + Style s = doc.addStyle("small", regular); + StyleConstants.setFontSize(s, 9); + + addMouseListener(this); + text.addMouseListener(this); + addFocusListener(this); + addMouseMotionListener(this); + text.addMouseMotionListener(this); + } + + public UUID getCardId() { + return card.getId(); + } + + public void update(CardView card) { + this.card = card; + Graphics2D gImage = image.createGraphics(); + Graphics2D gSmall = small.createGraphics(); + String cardType = getType(card); + + popupText.setText(getText(cardType)); + + gImage.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + gImage.setColor(Color.BLACK); + gImage.drawImage(background, 0, 0, this); + + if (card.getManaCost().size() > 0) + ImageHelper.DrawCosts(card.getManaCost(), gImage, FRAME_MAX_WIDTH - SYMBOL_MAX_XOFFSET, SYMBOL_MAX_YOFFSET, this); + + gSmall.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + gSmall.setColor(Color.BLACK); + gSmall.drawImage(ImageHelper.ScaleImage(image, FRAME_WIDTH, FRAME_HEIGHT), 0, 0, this); + + gImage.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_MAX_SIZE)); + gImage.drawString(card.getName(), CONTENT_MAX_XOFFSET, NAME_MAX_YOFFSET); + if (card.getCardTypes().contains(CardType.CREATURE)) { + gImage.drawString(card.getPower() + "/" + card.getToughness(), POWBOX_MAX_LEFT + 10, POWBOX_MAX_TOP + 15); + } + else if (card.getCardTypes().contains(CardType.PLANESWALKER)) { + gImage.drawString(card.getLoyalty(), POWBOX_MAX_LEFT + 10, POWBOX_MAX_TOP + 15); + } + + if (card.getCardTypes().size() > 0) + gImage.drawString(cardType, CONTENT_MAX_XOFFSET, TYPE_MAX_YOFFSET); + + gImage.dispose(); + + gSmall.setFont(new Font("Arial", Font.PLAIN, NAME_FONT_SIZE)); + gSmall.drawString(card.getName(), CONTENT_XOFFSET, NAME_YOFFSET+1); + if (card.getCardTypes().contains(CardType.CREATURE)) { + gSmall.drawString(card.getPower() + "/" + card.getToughness(), POWBOX_LEFT + 5, POWBOX_TOP + 8); + } + else if (card.getCardTypes().contains(CardType.PLANESWALKER)) { + gSmall.drawString(card.getLoyalty(), POWBOX_LEFT + 5, POWBOX_TOP + 8); + } + + if (card.getCardTypes().size() > 0) + gSmall.drawString(cardType, CONTENT_XOFFSET, TYPE_YOFFSET); + drawText(); + + gSmall.dispose(); + } + + private String getText(String cardType) { + StringBuilder sb = new StringBuilder(); + sb.append(card.getName()); + sb.append("\n"); + if (card.getManaCost().size() > 0) { + sb.append(card.getManaCost()); + sb.append("\n"); + } + sb.append(cardType); + sb.append("\n"); + sb.append(card.getColor().toString()); + sb.append("\n"); + for (String rule: card.getRules()) { + sb.append(rule); + sb.append("\n"); + } + if (card.getCardTypes().contains(CardType.CREATURE)) { + sb.append(card.getPower()); + sb.append("/"); + sb.append(card.getToughness()); + } + else if (card.getCardTypes().contains(CardType.PLANESWALKER)) { + sb.append(card.getLoyalty()); + } + return sb.toString(); + } + + private void drawText() { + text.setText(""); + StyledDocument doc = text.getStyledDocument(); + + try { + for (String rule: card.getRules()) + doc.insertString(doc.getLength(), rule + "\n", doc.getStyle("small")); + } catch (BadLocationException e) { + System.err.println("Couldn't insert initial text into text pane."); + } + + text.setCaretPosition(0); + } + + protected String getType(CardView card) { + StringBuilder sbType = new StringBuilder(); + + for (String superType: card.getSuperTypes()) { + sbType.append(superType); + sbType.append(" "); + } + + for (mage.Constants.CardType cardType: card.getCardTypes()) { + sbType.append(cardType.toString()); + sbType.append(" "); + } + + if (card.getSubTypes().size() > 0) { + sbType.append("- "); + for (String subType: card.getSubTypes()) { + sbType.append(subType); + sbType.append(" "); + } + } + + return sbType.toString(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + text = new javax.swing.JTextPane(); + + setMinimumSize(getPreferredSize()); + setOpaque(false); + setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT)); + setLayout(null); + + jScrollPane1.setBorder(null); + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane1.setFocusable(false); + jScrollPane1.setOpaque(false); + + text.setBorder(null); + text.setEditable(false); + text.setFont(new java.awt.Font("Arial", 0, 9)); + text.setFocusable(false); + text.setOpaque(false); + jScrollPane1.setViewportView(text); + + add(jScrollPane1); + jScrollPane1.setBounds(20, 110, 130, 100); + jScrollPane1.setBounds(new Rectangle(CONTENT_XOFFSET, TEXT_YOFFSET, TEXT_WIDTH, TEXT_HEIGHT)); + }// //GEN-END:initComponents + + @Override + public void paintComponent(Graphics graphics) { + Graphics2D g2 = (Graphics2D) graphics; + g2.drawImage(small, 0, 0, this); + + //Add a border, red if card currently has focus + if (isFocusOwner()) { + g2.setColor(Color.RED); + } else { + g2.setColor(Color.BLACK); + } + g2.drawRect(0, 0, FRAME_WIDTH - 1, FRAME_HEIGHT - 1); + } + + @Override + public void mouseDragged(MouseEvent arg0) { + } + + @Override + public void mouseMoved(MouseEvent arg0) { + this.bigCard.setCard(card.getId(), image, card.getRules()); + } + + @Override + public void mouseClicked(MouseEvent arg0) { + requestFocusInWindow(); + if (gameId != null) + session.sendPlayerUUID(gameId, card.getId()); + } + + @Override + public void mousePressed(MouseEvent arg0) { + } + + @Override + public void mouseReleased(MouseEvent arg0) { + } + + @Override + public void mouseEntered(MouseEvent arg0) { + if (popup != null) + popup.hide(); + PopupFactory factory = PopupFactory.getSharedInstance(); + popup = factory.getPopup(this, popupText, (int) this.getLocationOnScreen().getX() + FRAME_WIDTH, (int) this.getLocationOnScreen().getY() + 40); + popup.show(); + //hack to get popup to resize to fit text + popup.hide(); + popup = factory.getPopup(this, popupText, (int) this.getLocationOnScreen().getX() + FRAME_WIDTH, (int) this.getLocationOnScreen().getY() + 40); + popup.show(); + } + + @Override + public void mouseExited(MouseEvent arg0) { + if (popup != null) + popup.hide(); + } + + @Override + public void focusGained(FocusEvent arg0) { + this.repaint(); + } + + @Override + public void focusLost(FocusEvent arg0) { + if (popup != null) + popup.hide(); + this.repaint(); + } + + protected JScrollPane getText() { + return jScrollPane1; + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextPane text; + // End of variables declaration//GEN-END:variables + +} + +class TextPopup extends JPanel { + + JTextArea txt; + + public TextPopup() { + super(new BorderLayout()); + this.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1)); + txt = new JTextArea(1, 20); + txt.setLineWrap(true); + txt.setWrapStyleWord(true); + txt.setEditable(false); + txt.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + txt.setBackground(Color.lightGray); + this.add(txt); + } + + public void setText(String text) { + txt.setText(text); + } +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/cards/CardEventSource.java b/Mage.Client/src/mage/client/cards/CardEventSource.java new file mode 100644 index 00000000000..fed1bc0035c --- /dev/null +++ b/Mage.Client/src/mage/client/cards/CardEventSource.java @@ -0,0 +1,59 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.cards; + +import java.io.Serializable; +import java.util.UUID; +import mage.client.util.Event; +import mage.client.util.EventDispatcher; +import mage.client.util.EventSource; +import mage.client.util.Listener; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CardEventSource implements EventSource, Serializable { + + protected final EventDispatcher dispatcher = new EventDispatcher() {}; + + @Override + public void addListener(Listener listener) { + dispatcher.addListener(listener); + } + + public void doubleClick(UUID cardId, String message) { + dispatcher.fireEvent(new Event(cardId, message)); + } + + public void clearListeners() { + dispatcher.clearListeners(); + } + +} diff --git a/Mage.Client/src/mage/client/cards/Cards.form b/Mage.Client/src/mage/client/cards/Cards.form new file mode 100644 index 00000000000..9471ecf6a80 --- /dev/null +++ b/Mage.Client/src/mage/client/cards/Cards.form @@ -0,0 +1,49 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/mage/client/cards/Cards.java b/Mage.Client/src/mage/client/cards/Cards.java new file mode 100644 index 00000000000..66727ed99ae --- /dev/null +++ b/Mage.Client/src/mage/client/cards/Cards.java @@ -0,0 +1,98 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * Cards.java + * + * Created on Dec 18, 2009, 10:40:12 AM + */ + +package mage.client.cards; + +import java.awt.Dimension; +import java.util.UUID; +import mage.view.CardView; +import mage.view.CardsView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Cards extends javax.swing.JPanel { + + /** Creates new form Cards */ + public Cards() { + initComponents(); + cardArea.setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT)); + } + + public void loadCards(CardsView cards, BigCard bigCard, UUID gameId) { + cardArea.removeAll(); + for (CardView card: cards) { + Card cardImg = new Card(card, bigCard, gameId); + cardArea.add(cardImg); + cardImg.update(card); + } + cardArea.setPreferredSize(new Dimension(cards.size() * FRAME_WIDTH, FRAME_HEIGHT)); + cardArea.revalidate(); + cardArea.repaint(); + this.revalidate(); + this.repaint(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + cardArea = new javax.swing.JPanel(); + + setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + setLayout(new java.awt.BorderLayout()); + + jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + + cardArea.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0)); + jScrollPane1.setViewportView(cardArea); + + add(jScrollPane1, java.awt.BorderLayout.CENTER); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel cardArea; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/cards/CardsList.form b/Mage.Client/src/mage/client/cards/CardsList.form new file mode 100644 index 00000000000..4b0169ba1c2 --- /dev/null +++ b/Mage.Client/src/mage/client/cards/CardsList.form @@ -0,0 +1,42 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/mage/client/cards/CardsList.java b/Mage.Client/src/mage/client/cards/CardsList.java new file mode 100644 index 00000000000..8a2f98264a3 --- /dev/null +++ b/Mage.Client/src/mage/client/cards/CardsList.java @@ -0,0 +1,146 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * CardsList.java + * + * Created on Dec 18, 2009, 10:40:12 AM + */ + +package mage.client.cards; + +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import mage.client.util.Event; +import mage.client.util.Listener; +import mage.view.CardView; +import mage.view.CardsView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CardsList extends javax.swing.JPanel implements MouseListener { + + protected CardEventSource cardEventSource = new CardEventSource(); + + /** Creates new form Cards */ + public CardsList() { + initComponents(); + cardArea.setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT)); + } + + public void loadCards(CardsView showCards, BigCard bigCard, UUID gameId) { + cardArea.removeAll(); + if (showCards != null && showCards.size() > 0) { + Rectangle rectangle = new Rectangle(FRAME_WIDTH, FRAME_HEIGHT); + int count = 0; + for (CardView card: showCards) { + Card cardImg = new Card(card, bigCard, gameId); + cardImg.setBounds(rectangle); + cardArea.add(cardImg); + cardArea.moveToFront(cardImg); + cardImg.update(card); + cardImg.addMouseListener(this); + if (count >= 10) { + rectangle.translate(FRAME_WIDTH, -200); + count = 0; + } else { + rectangle.translate(0, 20); + count++; + } + } + } + cardArea.setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT + 200)); + cardArea.revalidate(); + this.revalidate(); + this.repaint(); + this.setVisible(true); + } + + + public void addCardEventListener(Listener listener) { + cardEventSource.addListener(listener); + } + + public void clearCardEventListeners() { + cardEventSource.clearListeners(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + cardArea = new javax.swing.JLayeredPane(); + + setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + setLayout(new java.awt.BorderLayout()); + + jScrollPane1.setViewportView(cardArea); + + add(jScrollPane1, java.awt.BorderLayout.CENTER); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLayeredPane cardArea; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables + + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2 && !e.isConsumed()) { + e.consume(); + cardEventSource.doubleClick(((Card)e.getSource()).getCardId(), "double-click"); + } + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + +} diff --git a/Mage.Client/src/mage/client/cards/Permanent.form b/Mage.Client/src/mage/client/cards/Permanent.form new file mode 100644 index 00000000000..dac4a517ffa --- /dev/null +++ b/Mage.Client/src/mage/client/cards/Permanent.form @@ -0,0 +1,20 @@ + + +
+ + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/cards/Permanent.java b/Mage.Client/src/mage/client/cards/Permanent.java new file mode 100644 index 00000000000..791848b3c7d --- /dev/null +++ b/Mage.Client/src/mage/client/cards/Permanent.java @@ -0,0 +1,198 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * Permanent.java + * + * Created on Dec 22, 2009, 3:25:49 PM + */ + +package mage.client.cards; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import mage.client.util.ImageHelper; +import mage.view.PermanentView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Permanent extends Card { + + protected PermanentView permanent; + + protected List links = new ArrayList(); + protected boolean linked; + protected BufferedImage tappedImage = new BufferedImage(FRAME_HEIGHT, FRAME_WIDTH, BufferedImage.TYPE_INT_RGB); + protected BufferedImage flippedImage; + + /** Creates new form Permanent */ + public Permanent(PermanentView permanent, BigCard bigCard, UUID gameId) { + super(permanent, bigCard, gameId); + this.setSize(this.getPreferredSize()); + this.permanent = permanent; + } + + public UUID getPermanentId() { + return permanent.getId(); + } + + public List getLinks() { + return links; + } + + public boolean isLinked() { + return linked; + } + + public void setLinked(boolean linked) { + this.linked = linked; + } + + @Override + public void mousePressed(MouseEvent e) { + p = e.getPoint(); + e.consume(); + } + + @Override + public void mouseDragged(MouseEvent e) { + if (!linked) { + int dx = e.getX() - p.x; + int dy = e.getY() - p.y; + Rectangle r = this.getBounds(); + r.x += dx; + r.y += dy; + if (r.x < 0) r.x = 0; + if (r.y < 0) r.y = 0; + this.setBounds(r); + this.repaint(); + for (Permanent perm: links) { + r.x += 20; + r.y += 20; + perm.setBounds(r); + } + } + } + + @Override + public void paintComponent(Graphics graphics) { + Graphics2D g2 = (Graphics2D) graphics; + this.setSize(this.getPreferredSize()); + if (permanent.isTapped()) { + this.getText().setVisible(false); + g2.drawImage(tappedImage, 0, 0, this); + } + else { + this.getText().setVisible(true); + g2.drawImage(small, 0, 0, this); + } + + //Add a border, red if card currently has focus + if (isFocusOwner()) { + g2.setColor(Color.RED); + } else { + g2.setColor(Color.BLACK); + } + if (permanent.isTapped()) { + g2.drawRect(0, 0, FRAME_HEIGHT - 1, FRAME_WIDTH - 1); + } + else { + g2.drawRect(0, 0, FRAME_WIDTH - 1, FRAME_HEIGHT - 1); + } + + } + + protected void generateTappedImage() { + Graphics2D g = (Graphics2D) tappedImage.getGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g.drawImage(this.createImage(ImageHelper.rotate(small)), 0, 0, this); + + g.dispose(); + } + + public void update(PermanentView permanent) { + this.permanent = permanent; + super.update(permanent); + if (permanent.getDamage() > 0) { + Graphics2D g = image.createGraphics(); + g.setColor(Color.RED); + g.drawString(Integer.toString(permanent.getDamage()), DAMAGE_MAX_LEFT, POWBOX_MAX_TOP + 15); + g.dispose(); + } + generateTappedImage(); + } + + @Override + public Dimension getPreferredSize() { + if (permanent != null && permanent.isTapped()) { + return new Dimension(FRAME_HEIGHT, FRAME_WIDTH); + } + else { + return new Dimension(FRAME_WIDTH, FRAME_HEIGHT); + } + } + + @Override + public Dimension getMinimumSize() { + return this.getPreferredSize(); + } + + public boolean overlaps(Rectangle r1) { + return this.getBounds().intersects(r1); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(null); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/chat/ChatClientImpl.java b/Mage.Client/src/mage/client/chat/ChatClientImpl.java new file mode 100644 index 00000000000..3c79aa3b928 --- /dev/null +++ b/Mage.Client/src/mage/client/chat/ChatClientImpl.java @@ -0,0 +1,85 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.chat; + +import java.io.Serializable; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JTextArea; +import mage.interfaces.ChatClient; +import mage.util.Logging; + + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ChatClientImpl implements ChatClient, Serializable { + + private final static Logger logger = Logging.getLogger(ChatClientImpl.class.getName()); + + private JTextArea textArea; + private String userName; + private UUID clientId; + + public ChatClientImpl(String userName, JTextArea textArea) { + this.clientId = UUID.randomUUID(); + this.textArea = textArea; + try { + this.userName = userName; + UnicastRemoteObject.exportObject(this, 0); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + @Override + public void receiveMessage(String message) throws RemoteException { + this.textArea.append(message + "\n"); + textArea.setCaretPosition(textArea.getText().length() - 1); + } + + @Override + public String getName() throws RemoteException { + return userName; + } + + @Override + public UUID getId() throws RemoteException { + return clientId; + } + + public UUID getIdLocal() { + return clientId; + } + +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/chat/ChatPanel.form b/Mage.Client/src/mage/client/chat/ChatPanel.form new file mode 100644 index 00000000000..9a980c0d2c1 --- /dev/null +++ b/Mage.Client/src/mage/client/chat/ChatPanel.form @@ -0,0 +1,61 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/mage/client/chat/ChatPanel.java b/Mage.Client/src/mage/client/chat/ChatPanel.java new file mode 100644 index 00000000000..4a14495ddbb --- /dev/null +++ b/Mage.Client/src/mage/client/chat/ChatPanel.java @@ -0,0 +1,135 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * ChatPanel.java + * + * Created on 15-Dec-2009, 11:04:31 PM + */ + +package mage.client.chat; + +import java.awt.event.KeyEvent; +import java.util.UUID; +import java.util.logging.Logger; +import mage.client.MageFrame; +import mage.client.remote.Session; +import mage.interfaces.ChatClient; +import mage.util.Logging; +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ChatPanel extends javax.swing.JPanel { + + private final static Logger logger = Logging.getLogger(ChatPanel.class.getName()); + + private UUID chatId; + private UUID clientId; + private ChatClient client; + private Session session; + + + /** Creates new form ChatPanel */ + public ChatPanel() { + initComponents(); + } + + public void connect(UUID chatId) { + session = MageFrame.getSession(); + this.chatId = chatId; + client = new ChatClientImpl(session.getUserName(), this.txtConversation); + clientId = ((ChatClientImpl)client).getIdLocal(); + session.joinChat(chatId, client); + } + + public void disconnect() { + if (session.isConnected()) + session.leaveChat(chatId, clientId); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + txtConversation = new javax.swing.JTextArea(); + txtMessage = new javax.swing.JTextField(); + + txtConversation.setColumns(20); + txtConversation.setEditable(false); + txtConversation.setFont(new java.awt.Font("Arial", 0, 10)); // NOI18N + txtConversation.setLineWrap(true); + txtConversation.setRows(5); + txtConversation.setWrapStyleWord(true); + jScrollPane1.setViewportView(txtConversation); + + txtMessage.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + txtMessageKeyTyped(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE) + .addComponent(txtMessage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 179, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 305, Short.MAX_VALUE) + .addGap(0, 0, 0) + .addComponent(txtMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + + private void txtMessageKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtMessageKeyTyped + if (evt.getKeyChar() == KeyEvent.VK_ENTER) { + session.sendChatMessage(chatId, this.txtMessage.getText()); + this.txtMessage.setText(""); + this.txtMessage.repaint(); + } +}//GEN-LAST:event_txtMessageKeyTyped + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea txtConversation; + private javax.swing.JTextField txtMessage; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/deckeditor/CardSelector.form b/Mage.Client/src/mage/client/deckeditor/CardSelector.form new file mode 100644 index 00000000000..bdd19d1dd1f --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/CardSelector.form @@ -0,0 +1,118 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/deckeditor/CardSelector.java b/Mage.Client/src/mage/client/deckeditor/CardSelector.java new file mode 100644 index 00000000000..db01019ff1a --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/CardSelector.java @@ -0,0 +1,255 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * CardSelector.java + * + * Created on Feb 18, 2010, 2:49:03 PM + */ + +package mage.client.deckeditor; + +import mage.Constants.Zone; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.client.cards.BigCard; +import mage.client.cards.CardsList; +import mage.filter.Filter.ComparisonScope; +import mage.filter.FilterCard; +import mage.sets.AlaraReborn; +import mage.sets.Conflux; +import mage.sets.Magic2010; +import mage.sets.Planechase; +import mage.sets.ShardsOfAlara; +import mage.sets.Tenth; +import mage.sets.Worldwake; +import mage.sets.Zendikar; +import mage.view.CardsView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CardSelector extends javax.swing.JPanel { + + private Cards cards = new CardsImpl(Zone.OUTSIDE); + private FilterCard filter = new FilterCard(); + private BigCard bigCard; + + /** Creates new form CardSelector */ + public CardSelector() { + initComponents(); + } + + public void loadCards(BigCard bigCard) { + this.bigCard = bigCard; + this.cards.clear(); + cards.addAll(AlaraReborn.getInstance().createCards()); + cards.addAll(Conflux.getInstance().createCards()); + cards.addAll(Magic2010.getInstance().createCards()); + cards.addAll(Planechase.getInstance().createCards()); + cards.addAll(ShardsOfAlara.getInstance().createCards()); + cards.addAll(Tenth.getInstance().createCards()); + cards.addAll(Worldwake.getInstance().createCards()); + cards.addAll(Zendikar.getInstance().createCards()); + filter.setUseColor(true); + filter.getColor().setBlack(true); + filter.getColor().setBlue(true); + filter.getColor().setGreen(true); + filter.getColor().setWhite(true); + filter.getColor().setRed(true); + filter.setColorless(true); + filter.setUseColorless(true); + filter.setNotColor(false); + filter.setScopeColor(ComparisonScope.Any); + filterCards(); + } + + private void filterCards() { + this.cardsList1.loadCards(new CardsView(cards.getCards(filter)), bigCard, null); + } + + public CardsList getCardsList() { + return this.cardsList1; + } + + public Cards getCards() { + return cards; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jToolBar1 = new javax.swing.JToolBar(); + rdoRed = new javax.swing.JRadioButton(); + rdoGreen = new javax.swing.JRadioButton(); + rdoBlue = new javax.swing.JRadioButton(); + rdoBlack = new javax.swing.JRadioButton(); + rdoWhite = new javax.swing.JRadioButton(); + rdoColorless = new javax.swing.JRadioButton(); + cardsList1 = new mage.client.cards.CardsList(); + + jToolBar1.setRollover(true); + + rdoRed.setSelected(true); + rdoRed.setText("Red "); + rdoRed.setFocusable(false); + rdoRed.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + rdoRed.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + rdoRed.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdoRedActionPerformed(evt); + } + }); + jToolBar1.add(rdoRed); + + rdoGreen.setSelected(true); + rdoGreen.setText("Green "); + rdoGreen.setFocusable(false); + rdoGreen.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + rdoGreen.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + rdoGreen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdoGreenActionPerformed(evt); + } + }); + jToolBar1.add(rdoGreen); + + rdoBlue.setSelected(true); + rdoBlue.setText("Blue "); + rdoBlue.setFocusable(false); + rdoBlue.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + rdoBlue.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + rdoBlue.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdoBlueActionPerformed(evt); + } + }); + jToolBar1.add(rdoBlue); + + rdoBlack.setSelected(true); + rdoBlack.setText("Black "); + rdoBlack.setFocusable(false); + rdoBlack.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + rdoBlack.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + rdoBlack.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdoBlackActionPerformed(evt); + } + }); + jToolBar1.add(rdoBlack); + + rdoWhite.setSelected(true); + rdoWhite.setText("White "); + rdoWhite.setFocusable(false); + rdoWhite.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + rdoWhite.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + rdoWhite.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdoWhiteActionPerformed(evt); + } + }); + jToolBar1.add(rdoWhite); + + rdoColorless.setSelected(true); + rdoColorless.setText("Colorless"); + rdoColorless.setFocusable(false); + rdoColorless.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); + rdoColorless.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + rdoColorless.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + rdoColorlessActionPerformed(evt); + } + }); + jToolBar1.add(rdoColorless); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 825, Short.MAX_VALUE) + .addComponent(cardsList1, javax.swing.GroupLayout.DEFAULT_SIZE, 825, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(cardsList1, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void rdoGreenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoGreenActionPerformed + filter.getColor().setGreen(this.rdoGreen.isSelected()); + filterCards(); + }//GEN-LAST:event_rdoGreenActionPerformed + + private void rdoBlackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoBlackActionPerformed + filter.getColor().setBlack(this.rdoBlack.isSelected()); + filterCards(); + }//GEN-LAST:event_rdoBlackActionPerformed + + private void rdoWhiteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoWhiteActionPerformed + filter.getColor().setWhite(this.rdoWhite.isSelected()); + filterCards(); + }//GEN-LAST:event_rdoWhiteActionPerformed + + private void rdoRedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoRedActionPerformed + filter.getColor().setRed(this.rdoRed.isSelected()); + filterCards(); + }//GEN-LAST:event_rdoRedActionPerformed + + private void rdoBlueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoBlueActionPerformed + filter.getColor().setBlue(this.rdoBlue.isSelected()); + filterCards(); + }//GEN-LAST:event_rdoBlueActionPerformed + + private void rdoColorlessActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoColorlessActionPerformed + filter.setColorless(this.rdoColorless.isSelected()); + filterCards(); + }//GEN-LAST:event_rdoColorlessActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.cards.CardsList cardsList1; + private javax.swing.JToolBar jToolBar1; + private javax.swing.JRadioButton rdoBlack; + private javax.swing.JRadioButton rdoBlue; + private javax.swing.JRadioButton rdoColorless; + private javax.swing.JRadioButton rdoGreen; + private javax.swing.JRadioButton rdoRed; + private javax.swing.JRadioButton rdoWhite; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/deckeditor/DeckArea.form b/Mage.Client/src/mage/client/deckeditor/DeckArea.form new file mode 100644 index 00000000000..5eaace8c59d --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/DeckArea.form @@ -0,0 +1,53 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/deckeditor/DeckArea.java b/Mage.Client/src/mage/client/deckeditor/DeckArea.java new file mode 100644 index 00000000000..085c01b57a1 --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/DeckArea.java @@ -0,0 +1,95 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + + +/* + * DeckArea.java + * + * Created on Feb 18, 2010, 3:10:39 PM + */ + +package mage.client.deckeditor; + +import mage.client.cards.CardsList; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DeckArea extends javax.swing.JPanel { + + /** Creates new form DeckArea */ + public DeckArea() { + initComponents(); + } + + public CardsList getDeckList() { + return deckList; + } + + public CardsList getSideboardList() { + return sideboardList; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jSplitPane1 = new javax.swing.JSplitPane(); + deckList = new mage.client.cards.CardsList(); + sideboardList = new mage.client.cards.CardsList(); + + jSplitPane1.setResizeWeight(0.8); + jSplitPane1.setLeftComponent(deckList); + jSplitPane1.setRightComponent(sideboardList); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 568, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.cards.CardsList deckList; + private javax.swing.JSplitPane jSplitPane1; + private mage.client.cards.CardsList sideboardList; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/deckeditor/DeckEditorPane.form b/Mage.Client/src/mage/client/deckeditor/DeckEditorPane.form new file mode 100644 index 00000000000..69dff9f90b4 --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/DeckEditorPane.form @@ -0,0 +1,35 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/deckeditor/DeckEditorPane.java b/Mage.Client/src/mage/client/deckeditor/DeckEditorPane.java new file mode 100644 index 00000000000..e4bce886d38 --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/DeckEditorPane.java @@ -0,0 +1,86 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * DeckEditorPane.java + * + * Created on Dec 17, 2009, 9:21:42 AM + */ + +package mage.client.deckeditor; + +import mage.client.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DeckEditorPane extends MagePane { + + /** Creates new form TablesPane */ + public DeckEditorPane() { + initComponents(); + } + + public void showTables() { + this.deckEditorPanel1.showDeckEditor(); + this.repaint(); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + deckEditorPanel1 = new mage.client.deckeditor.DeckEditorPanel(); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(deckEditorPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 885, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(deckEditorPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 626, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.deckeditor.DeckEditorPanel deckEditorPanel1; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.form b/Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.form new file mode 100644 index 00000000000..c662e1f64be --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.form @@ -0,0 +1,163 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.java new file mode 100644 index 00000000000..8f78b67b81e --- /dev/null +++ b/Mage.Client/src/mage/client/deckeditor/DeckEditorPanel.java @@ -0,0 +1,308 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * DeckEditorPanel.java + * + * Created on Feb 18, 2010, 2:47:04 PM + */ + +package mage.client.deckeditor; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import mage.cards.Card; +import mage.cards.decks.Deck; +import mage.cards.decks.DeckCardLists; +import mage.client.util.Event; +import mage.client.util.Listener; +import mage.view.CardsView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DeckEditorPanel extends javax.swing.JPanel { + + private JFileChooser fcSelectDeck; + private Deck deck = new Deck();; + + /** Creates new form DeckEditorPanel */ + public DeckEditorPanel() { + initComponents(); + fcSelectDeck = new JFileChooser(); + fcSelectDeck.setAcceptAllFileFilterUsed(false); + fcSelectDeck.addChoosableFileFilter(new DeckFilter()); + } + + public void showDeckEditor() { + this.cardSelector.loadCards(this.bigCard); + this.cardSelector.setVisible(true); + this.jPanel1.setVisible(true); + this.cardSelector.getCardsList().clearCardEventListeners(); + this.cardSelector.getCardsList().addCardEventListener( + new Listener () { + @Override + public void event(Event event) { + if (event.getEventName().equals("double-click")) { + deck.getCards().add(createCard(cardSelector.getCards().get((UUID)event.getSource()).getClass())); + refreshDeck(); + } + } + } + ); + this.deckArea.getDeckList().clearCardEventListeners(); + this.deckArea.getDeckList().addCardEventListener( + new Listener () { + @Override + public void event(Event event) { + if (event.getEventName().equals("double-click")) { + deck.getCards().remove((UUID)event.getSource()); + refreshDeck(); + } + } + } + ); + + this.setVisible(true); + this.repaint(); + } + + private void refreshDeck() { + this.txtDeckName.setText(deck.getName()); + deckArea.getDeckList().loadCards(new CardsView(deck.getCards()), bigCard, null); + deckArea.getSideboardList().loadCards(new CardsView(deck.getSideboard()), bigCard, null); + } + + private Card createCard(Class clazz) { + try { + Constructor con = clazz.getConstructor(new Class[]{UUID.class}); + return (Card) con.newInstance(new Object[] {null}); + } catch (Exception ex) { + Logger.getLogger(DeckEditorPanel.class.getName()).log(Level.SEVERE, null, ex); + return null; + } + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jSplitPane1 = new javax.swing.JSplitPane(); + cardSelector = new mage.client.deckeditor.CardSelector(); + deckArea = new mage.client.deckeditor.DeckArea(); + jPanel1 = new javax.swing.JPanel(); + bigCard = new mage.client.cards.BigCard(); + txtDeckName = new javax.swing.JTextField(); + lblDeckName = new javax.swing.JLabel(); + btnSave = new javax.swing.JButton(); + btnLoad = new javax.swing.JButton(); + btnNew = new javax.swing.JButton(); + btnExit = new javax.swing.JButton(); + + jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); + jSplitPane1.setResizeWeight(0.5); + jSplitPane1.setTopComponent(cardSelector); + jSplitPane1.setRightComponent(deckArea); + + bigCard.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + + lblDeckName.setLabelFor(txtDeckName); + lblDeckName.setText("Deck Name:"); + + btnSave.setText("Save"); + btnSave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnSaveActionPerformed(evt); + } + }); + + btnLoad.setText("Load"); + btnLoad.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnLoadActionPerformed(evt); + } + }); + + btnNew.setText("New"); + btnNew.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNewActionPerformed(evt); + } + }); + + btnExit.setText("Exit"); + btnExit.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnExitActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(lblDeckName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE)) + .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnSave) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnLoad) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnNew) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnExit))) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblDeckName)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnSave) + .addComponent(btnLoad) + .addComponent(btnNew) + .addComponent(btnExit)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 188, Short.MAX_VALUE) + .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 604, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void btnLoadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLoadActionPerformed + int ret = fcSelectDeck.showOpenDialog(this); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = fcSelectDeck.getSelectedFile(); + try { + deck = Deck.load(DeckCardLists.load(file.getPath())); + } catch (Exception ex) { + Logger.getLogger(DeckEditorPanel.class.getName()).log(Level.SEVERE, null, ex); + } + refreshDeck(); + } + fcSelectDeck.setSelectedFile(null); + }//GEN-LAST:event_btnLoadActionPerformed + + private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed + deck.setName(this.txtDeckName.getText()); + int ret = fcSelectDeck.showSaveDialog(this); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = fcSelectDeck.getSelectedFile(); + try { + deck.getDeckCardLists().save(file.getPath()); + } catch (Exception ex) { + Logger.getLogger(DeckEditorPanel.class.getName()).log(Level.SEVERE, null, ex); + } + } + }//GEN-LAST:event_btnSaveActionPerformed + + private void btnNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewActionPerformed + deck = new Deck(); + refreshDeck(); + }//GEN-LAST:event_btnNewActionPerformed + + private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExitActionPerformed + this.setVisible(false); + }//GEN-LAST:event_btnExitActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.cards.BigCard bigCard; + private javax.swing.JButton btnExit; + private javax.swing.JButton btnLoad; + private javax.swing.JButton btnNew; + private javax.swing.JButton btnSave; + private mage.client.deckeditor.CardSelector cardSelector; + private mage.client.deckeditor.DeckArea deckArea; + private javax.swing.JPanel jPanel1; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JLabel lblDeckName; + private javax.swing.JTextField txtDeckName; + // End of variables declaration//GEN-END:variables + +} + +class DeckFilter extends FileFilter { + + @Override + public boolean accept(File f) { + if (f.isDirectory()) + return true; + + String ext = null; + String s = f.getName(); + int i = s.lastIndexOf('.'); + + if (i > 0 && i < s.length() - 1) { + ext = s.substring(i+1).toLowerCase(); + } + return (ext==null)?false:ext.equals("dck"); + } + + @Override + public String getDescription() { + return "Deck Files"; + } +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/dialog/AboutDialog.form b/Mage.Client/src/mage/client/dialog/AboutDialog.form new file mode 100644 index 00000000000..44a286f0f37 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/AboutDialog.form @@ -0,0 +1,98 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/AboutDialog.java b/Mage.Client/src/mage/client/dialog/AboutDialog.java new file mode 100644 index 00000000000..efb969dc64b --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/AboutDialog.java @@ -0,0 +1,140 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +/* + * AboutDialog.java + * + * Created on Mar 10, 2010, 8:19:41 AM + */ + +package mage.client.dialog; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class AboutDialog extends MageDialog { + + /** Creates new form AboutDialog */ + public AboutDialog() { + initComponents(); + this.modal = false; + } + + public void showDialog() { + this.lblVersion.setText(MageDialog.class.getPackage().getImplementationVersion()); + this.setVisible(true); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnOk = new javax.swing.JButton(); + jLabel1 = new javax.swing.JLabel(); + lblVersion = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + btnOk.setText("OK"); + btnOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnOkActionPerformed(evt); + } + }); + + jLabel1.setText("MAGE client"); + + lblVersion.setText("version"); + + jLabel2.setText("Courtesy: ForgottenBeta@gmail.com"); + + jLabel3.setText("Thanks: KLo, Cosmo & Fritz"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(154, Short.MAX_VALUE) + .addComponent(btnOk) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblVersion) + .addContainerGap(104, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addContainerGap(23, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel3) + .addContainerGap(70, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(lblVersion)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) + .addComponent(btnOk) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed + this.setVisible(false); + }//GEN-LAST:event_btnOkActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnOk; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel lblVersion; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/CombatDialog.form b/Mage.Client/src/mage/client/dialog/CombatDialog.form new file mode 100644 index 00000000000..4f40ab660c1 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/CombatDialog.form @@ -0,0 +1,42 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/mage/client/dialog/CombatDialog.java b/Mage.Client/src/mage/client/dialog/CombatDialog.java new file mode 100644 index 00000000000..e56f8bf82c1 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/CombatDialog.java @@ -0,0 +1,115 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * CombatDialog.java + * + * Created on Feb 10, 2010, 3:35:02 PM + */ + +package mage.client.dialog; + +import java.awt.Dimension; +import java.util.List; +import java.util.UUID; +import javax.swing.JLayeredPane; +import mage.client.cards.BigCard; +import mage.client.game.CombatGroup; +import mage.view.CombatGroupView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CombatDialog extends MageDialog { + + private UUID gameId; + private BigCard bigCard; + + /** Creates new form CombatDialog */ + public CombatDialog() { + initComponents(); + this.setModal(false); + } + + public void init(UUID gameId, BigCard bigCard) { + this.gameId = gameId; + this.bigCard = bigCard; + } + + public void showDialog(List combat) { + combatArea.removeAll(); + for (CombatGroupView group: combat) { + CombatGroup combatGroup = new CombatGroup(); + combatGroup.init(gameId, bigCard); + combatGroup.update(group); + combatGroup.setVisible(true); +// combatGroup.setPreferredSize(new Dimension(140, 440)); + combatArea.add(combatGroup); + combatGroup.revalidate(); + } +// combatArea.setPreferredSize(new Dimension(140, 440)); + pack(); + this.revalidate(); + this.repaint(); + this.setVisible(true); + } + + public void hideDialog() { + this.setVisible(false); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + combatArea = new javax.swing.JPanel(); + + setResizable(true); + setVisible(true); + getContentPane().setLayout(new java.awt.BorderLayout()); + + jScrollPane1.setViewportView(combatArea); + + getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER); + + pack(); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel combatArea; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/ConnectDialog.form b/Mage.Client/src/mage/client/dialog/ConnectDialog.form new file mode 100644 index 00000000000..c62be0b92ea --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/ConnectDialog.form @@ -0,0 +1,133 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/mage/client/dialog/ConnectDialog.java new file mode 100644 index 00000000000..05ad14da293 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/ConnectDialog.java @@ -0,0 +1,203 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * ConnectDialog.java + * + * Created on 20-Jan-2010, 9:37:07 PM + */ + +package mage.client.dialog; + +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JOptionPane; +import mage.client.remote.Session; +import mage.client.util.Config; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ConnectDialog extends MageDialog { + + private final static Logger logger = Logging.getLogger(ConnectDialog.class.getName()); + private Session session; + + /** Creates new form ConnectDialog */ + public ConnectDialog(Session session) { + this.session = session; + initComponents(); + } + + public void showDialog() { + this.txtServer.setText(Config.serverName); + this.txtPort.setText(Integer.toString(Config.port)); + this.setModal(true); + this.setVisible(true); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + txtServer = new javax.swing.JTextField(); + lblServer = new javax.swing.JLabel(); + lblPort = new javax.swing.JLabel(); + txtPort = new javax.swing.JTextField(); + txtUserName = new javax.swing.JTextField(); + lblUserName = new javax.swing.JLabel(); + btnConnect = new javax.swing.JButton(); + btnCancel = new javax.swing.JButton(); + + lblServer.setLabelFor(txtServer); + lblServer.setText("Server:"); + + lblPort.setLabelFor(txtPort); + lblPort.setText("Port:"); + + txtPort.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyTyped(java.awt.event.KeyEvent evt) { + ConnectDialog.this.keyTyped(evt); + } + }); + + txtUserName.setText("me"); + + lblUserName.setLabelFor(txtUserName); + lblUserName.setText("User Name:"); + + btnConnect.setText("Connect"); + btnConnect.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnConnectActionPerformed(evt); + } + }); + + btnCancel.setText("Cancel"); + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(btnConnect) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblPort) + .addComponent(lblServer) + .addComponent(lblUserName)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(131, 131, 131)) + .addComponent(txtServer, javax.swing.GroupLayout.DEFAULT_SIZE, 268, Short.MAX_VALUE) + .addComponent(txtUserName, javax.swing.GroupLayout.DEFAULT_SIZE, 268, Short.MAX_VALUE)))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblServer) + .addComponent(txtServer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblPort)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblUserName)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 35, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnCancel) + .addComponent(btnConnect)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + this.setVisible(false); + }//GEN-LAST:event_btnCancelActionPerformed + + private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConnectActionPerformed + + try { + session.connect(txtUserName.getText(), txtServer.getText(), Integer.valueOf(txtPort.getText())); + this.setVisible(false); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, "Unable to connect to server", ex); + JOptionPane.showMessageDialog(rootPane, "Unable to connect to server"); + } catch (NotBoundException ex) { + logger.log(Level.SEVERE, "Unable to connect to server", ex); + JOptionPane.showMessageDialog(rootPane, "Unable to connect to server"); + } + }//GEN-LAST:event_btnConnectActionPerformed + + private void keyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_keyTyped + char c = evt.getKeyChar(); + if (!Character.isDigit(c)) + evt.consume(); + }//GEN-LAST:event_keyTyped + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton btnConnect; + private javax.swing.JLabel lblPort; + private javax.swing.JLabel lblServer; + private javax.swing.JLabel lblUserName; + private javax.swing.JTextField txtPort; + private javax.swing.JTextField txtServer; + private javax.swing.JTextField txtUserName; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/ExileZoneDialog.form b/Mage.Client/src/mage/client/dialog/ExileZoneDialog.form new file mode 100644 index 00000000000..cabd4e2962e --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/ExileZoneDialog.form @@ -0,0 +1,38 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/ExileZoneDialog.java b/Mage.Client/src/mage/client/dialog/ExileZoneDialog.java new file mode 100644 index 00000000000..a6f342d27da --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/ExileZoneDialog.java @@ -0,0 +1,105 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * ExileZoneDialog.java + * + * Created on Feb 1, 2010, 3:00:35 PM + */ + +package mage.client.dialog; + +import java.beans.PropertyVetoException; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JLayeredPane; +import mage.client.MageFrame; +import mage.client.cards.BigCard; +import mage.view.ExileView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ExileZoneDialog extends MageDialog { + + /** Creates new form ExileZoneDialog */ + public ExileZoneDialog() { + initComponents(); + this.setModal(false); + } + + public void loadCards(ExileView exile, BigCard bigCard, UUID gameId) { + this.title = exile.getName(); + if (exile.size() > 0) { + cards.loadCards(exile, bigCard, gameId); + if (getParent() != MageFrame.getDesktop() || this.isClosed) + MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); + try { + this.setIcon(false); + } catch (PropertyVetoException ex) { + Logger.getLogger(ShowCardsDialog.class.getName()).log(Level.SEVERE, null, ex); + } + } + this.setVisible(exile.size() > 0); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + cards = new mage.client.cards.Cards(); + + setIconifiable(true); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(cards, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 418, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(cards, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.cards.Cards cards; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/JoinTableDialog.form b/Mage.Client/src/mage/client/dialog/JoinTableDialog.form new file mode 100644 index 00000000000..7a276799fd2 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/JoinTableDialog.form @@ -0,0 +1,66 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/JoinTableDialog.java b/Mage.Client/src/mage/client/dialog/JoinTableDialog.java new file mode 100644 index 00000000000..85e3db7c777 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/JoinTableDialog.java @@ -0,0 +1,159 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + + +/* + * JoinTableDialog.java + * + * Created on 15-Dec-2009, 11:18:48 PM + */ + +package mage.client.dialog; + +import mage.client.*; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JOptionPane; +import mage.cards.decks.DeckCardLists; +import mage.client.remote.Session; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class JoinTableDialog extends MageDialog { + + private final static Logger logger = Logging.getLogger(JoinTableDialog.class.getName()); + + private UUID tableId; + private UUID roomId; + private boolean joined = false; + + /** Creates new form JoinTableDialog */ + public JoinTableDialog() { + initComponents(); + } + + public void showDialog(UUID roomId, UUID tableId) { + this.roomId = roomId; + this.tableId = tableId; + this.setModal(true); + this.setVisible(true); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnCancel = new javax.swing.JButton(); + btnOK = new javax.swing.JButton(); + newPlayerPanel = new mage.client.NewPlayerPanel(); + + btnCancel.setText("Cancel"); + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + btnOK.setText("OK"); + btnOK.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnOKActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(310, Short.MAX_VALUE) + .addComponent(btnOK) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel) + .addContainerGap()) + .addComponent(newPlayerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(newPlayerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 14, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnCancel) + .addComponent(btnOK)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + this.joined = false; + this.setVisible(false); + }//GEN-LAST:event_btnCancelActionPerformed + + private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed + Session session = MageFrame.getSession(); + try { + joined = session.joinTable(roomId, tableId, 1, this.newPlayerPanel.getPlayerName(), DeckCardLists.load(this.newPlayerPanel.getDeckFile())); + } catch (Exception ex) { + handleError(ex); + } + this.setVisible(false); + }//GEN-LAST:event_btnOKActionPerformed + + /** + * @return the joined + */ + public boolean isJoined() { + return joined; + } + + private void handleError(Exception ex) { + logger.log(Level.SEVERE, "Error loading deck", ex); + JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error loading deck.", "Error", JOptionPane.ERROR_MESSAGE); + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton btnOK; + private mage.client.NewPlayerPanel newPlayerPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/MageDialog.form b/Mage.Client/src/mage/client/dialog/MageDialog.form new file mode 100644 index 00000000000..ee50ddc2d76 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/MageDialog.form @@ -0,0 +1,31 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/MageDialog.java b/Mage.Client/src/mage/client/dialog/MageDialog.java new file mode 100644 index 00000000000..801a2836523 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/MageDialog.java @@ -0,0 +1,178 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * MageDialog.java + * + * Created on 15-Dec-2009, 10:28:27 PM + */ + +package mage.client.dialog; + +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.MenuComponent; +import java.awt.event.MouseEvent; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.SwingUtilities; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class MageDialog extends javax.swing.JInternalFrame { + + private final static Logger logger = Logging.getLogger(MageDialog.class.getName()); + + protected boolean modal = false; + + /** Creates new form MageDialog */ + public MageDialog() { + initComponents(); + } + + @Override + public void show() { + this.setLocation(200, 200); + super.show(); + if (this.modal) { + startModal(); + } + } + + @Override + public void setVisible(boolean value) { + super.setVisible(value); + if (modal) { + if (value) { + startModal(); + } else { + if (SwingUtilities.isEventDispatchThread()) { + stopModal(); + } else { + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + stopModal(); + } + }); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + } + } + + private synchronized void startModal() { + + try { + if (SwingUtilities.isEventDispatchThread()) { + EventQueue theQueue = getToolkit().getSystemEventQueue(); + while (isVisible()) { + AWTEvent event = theQueue.getNextEvent(); + Object source = event.getSource(); + boolean dispatch = true; + + if (event instanceof MouseEvent) { + MouseEvent e = (MouseEvent) event; + MouseEvent m = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, this); + if (!this.contains(m.getPoint()) && e.getID() != MouseEvent.MOUSE_DRAGGED) { + dispatch = false; + } + } + + if (dispatch) { + if (event instanceof ActiveEvent) { + ((ActiveEvent) event).dispatch(); + } else if (source instanceof Component) { + ((Component) source).dispatchEvent(event); + } else if (source instanceof MenuComponent) { + ((MenuComponent) source).dispatchEvent(event); + } else { + logger.info("Unable to dispatch: " + event); + } + } + } + } else { + while (isVisible()) { + wait(); + } + } + } catch (InterruptedException ignored) { + } + + } + + private synchronized void stopModal() { + notifyAll(); + } + + public void setModal(boolean modal) { + this.modal = modal; + } + + public boolean isModal() { + return this.modal; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 394, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 274, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/NewTableDialog.form b/Mage.Client/src/mage/client/dialog/NewTableDialog.form new file mode 100644 index 00000000000..5af2848a2f9 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/NewTableDialog.form @@ -0,0 +1,144 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/mage/client/dialog/NewTableDialog.java new file mode 100644 index 00000000000..63e7280eb65 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/NewTableDialog.java @@ -0,0 +1,272 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * NewTableDialog.java + * + * Created on 15-Dec-2009, 10:35:42 PM + */ + +package mage.client.dialog; + +import mage.client.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JOptionPane; +import mage.Constants; +import mage.cards.decks.DeckCardLists; +import mage.client.remote.Session; +import mage.util.Logging; +import mage.view.TableView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class NewTableDialog extends MageDialog { + + private final static Logger logger = Logging.getLogger(NewTableDialog.class.getName()); + + private TableView table; + private UUID playerId; + private UUID roomId; + private Session session; + + /** Creates new form NewTableDialog */ + public NewTableDialog() { + initComponents(); + this.player2Panel.setVisible(false); + //for testing only +// this.player1Panel.setPlayerName("human"); +// this.player2Panel.setPlayerName("computer"); +// //this.cbPlayer2Type.setSelectedItem(PlayerType.COMPUTER); +// this.player2Panel.setVisible(true); +// this.player1Panel.setDeckFile("test.dck"); +// this.player2Panel.setDeckFile("test.dck"); + + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblGameType = new javax.swing.JLabel(); + cbGameType = new javax.swing.JComboBox(); + lbDeckType = new javax.swing.JLabel(); + cbDeckType = new javax.swing.JComboBox(); + lbPlayer2Type = new javax.swing.JLabel(); + cbPlayer2Type = new javax.swing.JComboBox(); + btnOK = new javax.swing.JButton(); + btnCancel = new javax.swing.JButton(); + player2Panel = new mage.client.NewPlayerPanel(); + player1Panel = new mage.client.NewPlayerPanel(); + + lblGameType.setText("Game Type:"); + + lbDeckType.setText("Deck Type:"); + + cbDeckType.setModel(new DefaultComboBoxModel(Constants.DeckType.values())); + + lbPlayer2Type.setText("Player 2 Type:"); + + cbPlayer2Type.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbPlayer2TypeActionPerformed(evt); + } + }); + + btnOK.setText("OK"); + btnOK.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnOKActionPerformed(evt); + } + }); + + btnCancel.setText("Cancel"); + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(25, 25, 25) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblGameType) + .addComponent(lbDeckType)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(cbDeckType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnOK) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(lbPlayer2Type) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(cbPlayer2Type, javax.swing.GroupLayout.PREFERRED_SIZE, 241, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 468, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(player2Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 468, Short.MAX_VALUE))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblGameType)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbDeckType)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(player1Panel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(8, 8, 8) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbPlayer2Type) + .addComponent(cbPlayer2Type, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(player2Panel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(13, 13, 13) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnOK) + .addComponent(btnCancel)) + .addContainerGap(39, Short.MAX_VALUE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + this.table = null; + this.playerId = null; + this.setVisible(false); + }//GEN-LAST:event_btnCancelActionPerformed + + private void cbPlayer2TypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPlayer2TypeActionPerformed + if (!this.cbPlayer2Type.getSelectedItem().equals("Human")) { + this.player2Panel.setVisible(true); + } + else { + this.player2Panel.setVisible(false); + } + }//GEN-LAST:event_cbPlayer2TypeActionPerformed + + private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed + try { + List playerTypes = new ArrayList(); + playerTypes.add("Human"); + playerTypes.add((String) this.cbPlayer2Type.getSelectedItem()); + table = session.createTable( + roomId, + (String)this.cbGameType.getSelectedItem(), + (Constants.DeckType)this.cbDeckType.getSelectedItem(), + playerTypes + ); + session.joinTable( + roomId, + table.getTableId(), + 0, + this.player1Panel.getPlayerName(), + DeckCardLists.load(this.player1Panel.getDeckFile()) + ); + if (!this.cbPlayer2Type.getSelectedItem().equals("Human")) { + session.joinTable( + roomId, + table.getTableId(), + 1, + this.player2Panel.getPlayerName(), + DeckCardLists.load(this.player2Panel.getDeckFile()) + ); + } + } catch (Exception ex) { + handleError(ex); + } + + this.setVisible(false); + }//GEN-LAST:event_btnOKActionPerformed + + private void handleError(Exception ex) { + logger.log(Level.SEVERE, "Error loading deck", ex); + JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error loading deck.", "Error", JOptionPane.ERROR_MESSAGE); + } + + public void showDialog(UUID roomId) { + session = MageFrame.getSession(); + cbGameType.setModel(new DefaultComboBoxModel(session.getGameTypes())); + cbPlayer2Type.setModel(new DefaultComboBoxModel(session.getPlayerTypes())); + this.roomId = roomId; + this.setModal(true); + this.setVisible(true); + } + + public TableView getTable() { + return table; + } + + public UUID getPlayerId() { + return playerId; + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton btnOK; + private javax.swing.JComboBox cbDeckType; + private javax.swing.JComboBox cbGameType; + private javax.swing.JComboBox cbPlayer2Type; + private javax.swing.JLabel lbDeckType; + private javax.swing.JLabel lbPlayer2Type; + private javax.swing.JLabel lblGameType; + private mage.client.NewPlayerPanel player1Panel; + private mage.client.NewPlayerPanel player2Panel; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/PickChoiceDialog.form b/Mage.Client/src/mage/client/dialog/PickChoiceDialog.form new file mode 100644 index 00000000000..3462b894ddd --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/PickChoiceDialog.form @@ -0,0 +1,100 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/PickChoiceDialog.java b/Mage.Client/src/mage/client/dialog/PickChoiceDialog.java new file mode 100644 index 00000000000..2c9acfd4b48 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/PickChoiceDialog.java @@ -0,0 +1,150 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * PickNumberDialog.java + * + * Created on Feb 25, 2010, 12:03:39 PM + */ + +package mage.client.dialog; + +import javax.swing.JLayeredPane; +import mage.client.MageFrame; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PickChoiceDialog extends MageDialog { + + /** Creates new form PickNumberDialog */ + public PickChoiceDialog() { + initComponents(); + this.setModal(true); + } + + public void showDialog(String message, String[] choices) { + this.lblMessage.setText(message); + this.lstChoices.setListData(choices); + MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); + this.setVisible(true); + } + + public String getChoice() { + return (String)this.lstChoices.getSelectedValue(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnCancel = new javax.swing.JButton(); + btnOk = new javax.swing.JButton(); + jScrollPane1 = new javax.swing.JScrollPane(); + lstChoices = new javax.swing.JList(); + lblMessage = new javax.swing.JLabel(); + + btnCancel.setText("Cancel"); + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + btnOk.setText("OK"); + btnOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnOkActionPerformed(evt); + } + }); + + lstChoices.setModel(new javax.swing.AbstractListModel() { + String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }; + public int getSize() { return strings.length; } + public Object getElementAt(int i) { return strings[i]; } + }); + jScrollPane1.setViewportView(lstChoices); + + lblMessage.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblMessage.setText("message"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(btnOk) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel)) + .addComponent(lblMessage, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(lblMessage) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnCancel) + .addComponent(btnOk)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed + this.setVisible(false); + }//GEN-LAST:event_btnOkActionPerformed + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + this.setVisible(false); + }//GEN-LAST:event_btnCancelActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton btnOk; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel lblMessage; + private javax.swing.JList lstChoices; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/PickNumberDialog.form b/Mage.Client/src/mage/client/dialog/PickNumberDialog.form new file mode 100644 index 00000000000..eaaab5b6613 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/PickNumberDialog.form @@ -0,0 +1,76 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/PickNumberDialog.java b/Mage.Client/src/mage/client/dialog/PickNumberDialog.java new file mode 100644 index 00000000000..8eafd783c07 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/PickNumberDialog.java @@ -0,0 +1,144 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * PickNumberDialog.java + * + * Created on Feb 25, 2010, 12:03:39 PM + */ + +package mage.client.dialog; + +import javax.swing.SpinnerNumberModel; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PickNumberDialog extends MageDialog { + + private boolean cancel; + + /** Creates new form PickNumberDialog */ + public PickNumberDialog() { + initComponents(); + this.setModal(true); + } + + public void showDialog(int min, int max) { + this.spnAmount.setModel(new SpinnerNumberModel(min, min, max, 1)); + this.btnCancel.setVisible(false); + this.setVisible(true); + } + + public int getAmount() { + return ((Number)spnAmount.getValue()).intValue(); + } + + public boolean isCancel() { + return cancel; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + spnAmount = new javax.swing.JSpinner(); + btnCancel = new javax.swing.JButton(); + btnOk = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + spnAmount.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(1), null, null, Integer.valueOf(1))); + + btnCancel.setText("Cancel"); + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + btnOk.setText("OK"); + btnOk.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnOkActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnOk) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addGap(61, 61, 61) + .addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(51, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(spnAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnCancel) + .addComponent(btnOk)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed + this.cancel = false; + this.setVisible(false); + }//GEN-LAST:event_btnOkActionPerformed + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + this.cancel = true; + this.setVisible(false); + }//GEN-LAST:event_btnCancelActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton btnOk; + private javax.swing.JSpinner spnAmount; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/QuestionDialog.form b/Mage.Client/src/mage/client/dialog/QuestionDialog.form new file mode 100644 index 00000000000..aa03e839ee4 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/QuestionDialog.form @@ -0,0 +1,75 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/QuestionDialog.java b/Mage.Client/src/mage/client/dialog/QuestionDialog.java new file mode 100644 index 00000000000..89e080ab10d --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/QuestionDialog.java @@ -0,0 +1,137 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + + +/* + * QuestionDialog.java + * + * Created on Dec 23, 2009, 11:01:32 AM + */ + +package mage.client.dialog; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class QuestionDialog extends MageDialog { + + private boolean answer; + + /** Creates new form QuestionDialog */ + public QuestionDialog() { + initComponents(); + } + + public void showDialog(String question) { + this.lblQuestion.setText(question); + this.setModal(true); + this.setVisible(true); + } + + public boolean getAnswer() { + return answer; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblQuestion = new javax.swing.JLabel(); + btnNo = new javax.swing.JButton(); + btnYes = new javax.swing.JButton(); + + lblQuestion.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblQuestion.setText("question"); + + btnNo.setText("No"); + btnNo.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNoActionPerformed(evt); + } + }); + + btnYes.setText("Yes"); + btnYes.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnYesActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblQuestion, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(btnYes) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnNo))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(lblQuestion, javax.swing.GroupLayout.DEFAULT_SIZE, 35, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnNo) + .addComponent(btnYes)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnYesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnYesActionPerformed + this.answer = true; + this.setVisible(false); + }//GEN-LAST:event_btnYesActionPerformed + + private void btnNoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNoActionPerformed + this.answer = false; + this.setVisible(false); + }//GEN-LAST:event_btnNoActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnNo; + private javax.swing.JButton btnYes; + private javax.swing.JLabel lblQuestion; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/dialog/ShowCardsDialog.form b/Mage.Client/src/mage/client/dialog/ShowCardsDialog.form new file mode 100644 index 00000000000..2ad48ee4cad --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/ShowCardsDialog.form @@ -0,0 +1,42 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Client/src/mage/client/dialog/ShowCardsDialog.java b/Mage.Client/src/mage/client/dialog/ShowCardsDialog.java new file mode 100644 index 00000000000..e9009788f5f --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/ShowCardsDialog.java @@ -0,0 +1,148 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * ShowCardsDialog.java + * + * Created on 3-Feb-2010, 8:59:11 PM + */ + +package mage.client.dialog; + +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Collection; +import java.util.UUID; +import javax.swing.JLayeredPane; +import mage.client.MageFrame; +import mage.client.cards.BigCard; +import mage.client.cards.Card; +import mage.view.CardView; +import mage.view.CardsView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ShowCardsDialog extends MageDialog implements MouseListener { + + /** Creates new form ShowCardsDialog */ + public ShowCardsDialog() { + initComponents(); + this.setModal(false); + } + + public void loadCards(String name, CardsView showCards, BigCard bigCard, UUID gameId) { + this.title = name; + cardArea.removeAll(); + int columns = 1; + if (showCards != null && showCards.size() > 0) { + Rectangle rectangle = new Rectangle(FRAME_WIDTH, FRAME_HEIGHT); + int count = 0; + for (CardView card: showCards) { + Card cardImg = new Card(card, bigCard, gameId); + cardImg.setBounds(rectangle); + cardArea.add(cardImg); + cardArea.moveToFront(cardImg); + cardImg.update(card); + cardImg.addMouseListener(this); + if (count >= 20) { + rectangle.translate(FRAME_WIDTH, -400); + columns++; + count = 0; + } else { + rectangle.translate(0, 20); + count++; + } + } + } + cardArea.setPreferredSize(new Dimension(FRAME_WIDTH * columns, FRAME_HEIGHT + 400)); + cardArea.revalidate(); + if (getParent() != MageFrame.getDesktop() || this.isClosed) + MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER); + pack(); + this.revalidate(); + this.repaint(); + this.setVisible(true); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + cardArea = new javax.swing.JLayeredPane(); + + setClosable(true); + setResizable(true); + getContentPane().setLayout(new java.awt.BorderLayout()); + + jScrollPane1.setViewportView(cardArea); + + getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER); + + pack(); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLayeredPane cardArea; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables + + public void mouseClicked(MouseEvent e) { + this.setVisible(false); + } + + public void mousePressed(MouseEvent e) { + + } + + public void mouseReleased(MouseEvent e) { + + } + + public void mouseEntered(MouseEvent e) { + + } + + public void mouseExited(MouseEvent e) { + + } + + +} diff --git a/Mage.Client/src/mage/client/dialog/TableWaitingDialog.form b/Mage.Client/src/mage/client/dialog/TableWaitingDialog.form new file mode 100644 index 00000000000..e69d79a930a --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/TableWaitingDialog.form @@ -0,0 +1,119 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/dialog/TableWaitingDialog.java b/Mage.Client/src/mage/client/dialog/TableWaitingDialog.java new file mode 100644 index 00000000000..f39dc83c346 --- /dev/null +++ b/Mage.Client/src/mage/client/dialog/TableWaitingDialog.java @@ -0,0 +1,311 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * TableWaitingDialog.java + * + * Created on Dec 16, 2009, 10:27:44 AM + */ + +package mage.client.dialog; + +import mage.client.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Observable; +import java.util.Observer; +import java.util.UUID; +import java.util.logging.Logger; +import javax.swing.Timer; +import javax.swing.table.AbstractTableModel; +import mage.Constants.TableState; +import mage.client.remote.Session; +import mage.util.Logging; +import mage.view.SeatView; +import mage.view.TableView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TableWaitingDialog extends MageDialog implements Observer { + + private final static Logger logger = Logging.getLogger(TableWaitingDialog.class.getName()); + + private UUID tableId; + private UUID roomId; + private Session session; + private TableWaitModel tableWaitModel; + private SeatsWatchdog seatsWatchdog = new SeatsWatchdog(); + + /** Creates new form TableWaitingDialog */ + public TableWaitingDialog() { + + session = MageFrame.getSession(); + tableWaitModel = new TableWaitModel(); + + initComponents(); + + tableSeats.createDefaultColumnsFromModel(); + } + + public void update(Observable arg0, Object arg1) { + TableView table = session.getTable(roomId, tableId); + if (table != null) { + if (table.getTableState() == TableState.STARTING) { + this.btnStart.setEnabled(true); + } else { + this.btnStart.setEnabled(false); + } + tableWaitModel.loadData(table); + this.tableSeats.repaint(); + } + else { + closeDialog(); + } + } + + public void showDialog(UUID roomId, UUID tableId) { + this.roomId = roomId; + this.tableId = tableId; + session = MageFrame.getSession(); + if (session.isTableOwner(roomId, tableId)) { + this.btnStart.setVisible(true); + this.btnMoveDown.setVisible(true); + this.btnMoveUp.setVisible(true); + } else { + this.btnStart.setVisible(false); + this.btnMoveDown.setVisible(false); + this.btnMoveUp.setVisible(false); + } + UUID chatId = session.getTableChatId(tableId); + if (chatId != null) { + this.chatPanel.connect(chatId); + seatsWatchdog.addObserver(this); + this.setModal(true); + this.setVisible(true); + } + else { + closeDialog(); + } + } + + public void closeDialog() { + seatsWatchdog.deleteObservers(); + this.chatPanel.disconnect(); + setVisible(false); + } + + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnMoveUp = new javax.swing.JButton(); + btnMoveDown = new javax.swing.JButton(); + btnCancel = new javax.swing.JButton(); + btnStart = new javax.swing.JButton(); + jSplitPane1 = new javax.swing.JSplitPane(); + jScrollPane1 = new javax.swing.JScrollPane(); + tableSeats = new javax.swing.JTable(); + chatPanel = new mage.client.chat.ChatPanel(); + + btnMoveUp.setText("Move Up"); + + btnMoveDown.setText("Move Down"); + + btnCancel.setText("Cancel"); + btnCancel.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCancelActionPerformed(evt); + } + }); + + btnStart.setText("Start"); + btnStart.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnStartActionPerformed(evt); + } + }); + + jSplitPane1.setDividerLocation(450); + jSplitPane1.setDividerSize(3); + jSplitPane1.setResizeWeight(1.0); + + tableSeats.setModel(tableWaitModel); + jScrollPane1.setViewportView(tableSeats); + + jSplitPane1.setLeftComponent(jScrollPane1); + jSplitPane1.setRightComponent(chatPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnMoveDown) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnMoveUp) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 232, Short.MAX_VALUE) + .addComponent(btnStart) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCancel) + .addContainerGap()) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 550, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 223, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnMoveDown) + .addComponent(btnMoveUp) + .addComponent(btnCancel) + .addComponent(btnStart)) + .addContainerGap()) + ); + + pack(); + }// //GEN-END:initComponents + + private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStartActionPerformed + closeDialog(); + session.startGame(roomId, tableId); + }//GEN-LAST:event_btnStartActionPerformed + + private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed + if (session.isTableOwner(roomId, tableId)) { + session.removeTable(roomId, tableId); + } else { + session.leaveTable(roomId, tableId); + } + closeDialog(); + }//GEN-LAST:event_btnCancelActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnCancel; + private javax.swing.JButton btnMoveDown; + private javax.swing.JButton btnMoveUp; + private javax.swing.JButton btnStart; + private mage.client.chat.ChatPanel chatPanel; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JTable tableSeats; + // End of variables declaration//GEN-END:variables + +} + +class TableWaitModel extends AbstractTableModel { + private String[] columnNames = new String[]{"Seat Num", "Player Id", "Name", "Player Type"}; + private SeatView[] seats = new SeatView[0]; + + + public void loadData(TableView table) { + seats = table.getSeats().toArray(new SeatView[0]); + this.fireTableDataChanged(); + } + + @Override + public int getRowCount() { + return seats.length; + } + + @Override + public int getColumnCount() { + return columnNames.length; + } + + @Override + public Object getValueAt(int arg0, int arg1) { + if (seats[arg0].getPlayerId() == null) { + if (arg1 == 0) { + return Integer.toString(arg0 + 1); + } + } + else { + switch (arg1) { + case 0: + return Integer.toString(arg0 + 1); + case 1: + return seats[arg0].getPlayerId().toString(); + case 2: + return seats[arg0].getPlayerName(); + case 3: + return seats[arg0].getPlayerType(); + } + } + return ""; + } + + @Override + public String getColumnName(int columnIndex) { + String colName = ""; + + if (columnIndex <= getColumnCount()) + colName = columnNames[columnIndex]; + + return colName; + } + + @Override + public Class getColumnClass(int columnIndex){ + return String.class; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + if (columnIndex != 4) + return false; + return true; + } + +} + +class SeatsWatchdog extends Observable implements ActionListener { + + Timer t = new Timer(1000, this); // check every second + + public SeatsWatchdog() { + t.start(); + } + + public void actionPerformed(ActionEvent arg0) { + setChanged(); + notifyObservers(); + } + +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/game/AbilityPicker.java b/Mage.Client/src/mage/client/game/AbilityPicker.java new file mode 100644 index 00000000000..a4e3617eb60 --- /dev/null +++ b/Mage.Client/src/mage/client/game/AbilityPicker.java @@ -0,0 +1,85 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.game; + +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.util.Map.Entry; +import java.util.UUID; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JPopupMenu; +import mage.client.remote.Session; +import mage.view.AbilityPickerView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class AbilityPicker extends JPopupMenu { + + private Session session; + private UUID gameId; + + public AbilityPicker() { + } + + public void init(Session session, UUID gameId) { + this.session = session; + this.gameId = gameId; + } + + public void show(AbilityPickerView choices, Point p) { + this.removeAll(); + for (Entry choice: choices.getChoices().entrySet()) { + this.add(new AbilityPickerAction(choice.getKey(), choice.getValue())); + } + this.setLocation(p); + this.setVisible(true); + } + + private class AbilityPickerAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + private UUID id; + + public AbilityPickerAction(UUID id, String choice) { + this.id = id; + putValue(Action.NAME, choice); + } + + @Override + public void actionPerformed(ActionEvent e) { + session.sendPlayerUUID(gameId, id); + setVisible(false); + } + + } + +} diff --git a/Mage.Client/src/mage/client/game/BattlefieldPanel.form b/Mage.Client/src/mage/client/game/BattlefieldPanel.form new file mode 100644 index 00000000000..9c3d3fbde2d --- /dev/null +++ b/Mage.Client/src/mage/client/game/BattlefieldPanel.form @@ -0,0 +1,20 @@ + + +
+ + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/BattlefieldPanel.java b/Mage.Client/src/mage/client/game/BattlefieldPanel.java new file mode 100644 index 00000000000..3b309299524 --- /dev/null +++ b/Mage.Client/src/mage/client/game/BattlefieldPanel.java @@ -0,0 +1,207 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * BattlefieldPanel.java + * + * Created on 10-Jan-2010, 10:43:14 PM + */ + +package mage.client.game; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import mage.client.cards.BigCard; +import mage.client.cards.Permanent; +import mage.view.PermanentView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class BattlefieldPanel extends javax.swing.JPanel implements ComponentListener { + + private Map permanents = new HashMap(); + private UUID gameId; + private BigCard bigCard; + + /** Creates new form BattlefieldPanel */ + public BattlefieldPanel() { + initComponents(); + } + + public void init(UUID gameId, BigCard bigCard) { + this.gameId = gameId; + this.bigCard = bigCard; + } + + public void update(Map battlefield) { + for (PermanentView permanent: battlefield.values()) { + if (!permanents.containsKey(permanent.getId())) { + addPermanent(permanent); + } + else { + permanents.get(permanent.getId()).update(permanent); + } + } + for (Iterator> i = permanents.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + if (!battlefield.containsKey(entry.getKey())) { + removePermanent(entry.getKey()); + i.remove(); + } + } + for (PermanentView permanent: battlefield.values()) { + if (permanent.getAttachments() != null) { + groupAttachments(permanent); + } + } + } + + private void addPermanent(PermanentView permanent) { + Permanent perm = new Permanent(permanent, bigCard, gameId); + perm.addComponentListener(this); + perm.setBounds(findEmptySpace(new Dimension(FRAME_WIDTH, FRAME_HEIGHT))); + permanents.put(permanent.getId(), perm); + this.add(perm); + perm.update(permanent); + } + + private void groupAttachments(PermanentView permanent) { + Permanent perm = permanents.get(permanent.getId()); + perm.getLinks().clear(); + Rectangle r = perm.getBounds(); + for (UUID attachmentId: permanent.getAttachments()) { + Permanent link = permanents.get(attachmentId); + perm.getLinks().add(link); + r.translate(20, 20); + link.setBounds(r); + } + } + + private void removePermanent(UUID permanentId) { + for (Component comp: this.getComponents()) { + if (comp instanceof Permanent) { + if (((Permanent)comp).getPermanentId().equals(permanentId)) { + this.remove(comp); + } + } + } + } + + private Rectangle findEmptySpace(Dimension size) { + int battlefieldWidth = this.getWidth(); + Rectangle r = new Rectangle(size); + boolean intersects; + while (true) { + intersects = false; + for (Permanent perm: permanents.values()) { + Rectangle pr = perm.getBounds(); + if (r.intersects(pr)) { + intersects = true; + if (pr.x + pr.width + r.width > battlefieldWidth) + r.setLocation(0, pr.y + pr.height + 1); + else + r.translate(pr.x + pr.width - r.x, 0); + break; + } + } + if (!intersects) + break; + } + return r; + } + + @Override + public boolean isOptimizedDrawingEnabled () { + return false; + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + setLayout(null); + }// //GEN-END:initComponents + + public void componentResized(ComponentEvent e) { + resizeBattlefield(); + } + + public void componentMoved(ComponentEvent e) { + resizeBattlefield(); + } + + public void componentShown(ComponentEvent e) { + resizeBattlefield(); + } + + public void componentHidden(ComponentEvent e) { + resizeBattlefield(); + } + + private void resizeBattlefield() { + Dimension area = new Dimension(0, 0); + Dimension size = getPreferredSize(); + + for (Component comp: getComponents()) { + Rectangle r = comp.getBounds(); + if (r.x + r.width > area.width) { + area.width = r.x + r.width; + } + if (r.y + r.height > area.height) { + area.height = r.y + r.height; + } + } + if (size.height != area.height || size.width != area.width) { + setPreferredSize(area); + revalidate(); + repaint(); + } + + } + + + // Variables declaration - do not modify//GEN-BEGIN:variables + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/CombatGroup.form b/Mage.Client/src/mage/client/game/CombatGroup.form new file mode 100644 index 00000000000..9bd20c54257 --- /dev/null +++ b/Mage.Client/src/mage/client/game/CombatGroup.form @@ -0,0 +1,48 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/CombatGroup.java b/Mage.Client/src/mage/client/game/CombatGroup.java new file mode 100644 index 00000000000..da76b1fe7f9 --- /dev/null +++ b/Mage.Client/src/mage/client/game/CombatGroup.java @@ -0,0 +1,115 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * CombatGroup.java + * + * Created on Feb 10, 2010, 3:36:55 PM + */ + +package mage.client.game; + +import java.awt.Dimension; +import java.util.UUID; +import mage.client.cards.BigCard; +import mage.view.CombatGroupView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class CombatGroup extends javax.swing.JPanel { + + private UUID gameId; + private BigCard bigCard; + + /** Creates new form CombatGroup */ + public CombatGroup() { + initComponents(); +// setPreferredSize(new Dimension(160, 440)); + } + + public void init(UUID gameId, BigCard bigCard) { + this.gameId = gameId; + this.bigCard = bigCard; + } + + public void update(CombatGroupView combatGroup) { + this.lblDefender.setText(combatGroup.getDefenderName()); + this.attackers.loadCards(combatGroup.getAttackers(), bigCard, gameId); + attackers.setPreferredSize(new Dimension(FRAME_WIDTH + 6, FRAME_HEIGHT + 6)); + this.blockers.loadCards(combatGroup.getBlockers(), bigCard, gameId); + blockers.setPreferredSize(new Dimension(FRAME_WIDTH + 6, FRAME_HEIGHT + 6)); + this.attackers.setVisible(true); + this.blockers.setVisible(true); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + blockers = new mage.client.cards.Cards(); + attackers = new mage.client.cards.Cards(); + lblDefender = new javax.swing.JLabel(); + + lblDefender.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lblDefender.setText("jLabel1"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblDefender, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) + .addComponent(blockers, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) + .addComponent(attackers, javax.swing.GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(lblDefender) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(blockers, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(attackers, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.cards.Cards attackers; + private mage.client.cards.Cards blockers; + private javax.swing.JLabel lblDefender; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/FeedbackPanel.form b/Mage.Client/src/mage/client/game/FeedbackPanel.form new file mode 100644 index 00000000000..9f1a805b92c --- /dev/null +++ b/Mage.Client/src/mage/client/game/FeedbackPanel.form @@ -0,0 +1,96 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/FeedbackPanel.java b/Mage.Client/src/mage/client/game/FeedbackPanel.java new file mode 100644 index 00000000000..a3d2e5901ca --- /dev/null +++ b/Mage.Client/src/mage/client/game/FeedbackPanel.java @@ -0,0 +1,253 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * FeedbackPanel.java + * + * Created on 23-Dec-2009, 9:54:01 PM + */ + +package mage.client.game; + +import java.awt.AWTEvent; +import java.awt.ActiveEvent; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.MenuComponent; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.util.UUID; +import java.util.logging.Logger; +import javax.swing.SwingUtilities; +import mage.client.MageFrame; +import mage.client.remote.Session; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class FeedbackPanel extends javax.swing.JPanel { + + private final static Logger logger = Logging.getLogger(FeedbackPanel.class.getName()); + + public enum FeedbackMode { + INFORM, QUESTION, CONFIRM, CANCEL, SELECT + } + + private boolean selected = false; + private UUID gameId; + private Session session; + private FeedbackMode mode; + + /** Creates new form FeedbackPanel */ + public FeedbackPanel() { + initComponents(); + } + + public void init(UUID gameId) { + this.gameId = gameId; + session = MageFrame.getSession(); + } + + public void getFeedback(FeedbackMode mode, String message, boolean modal) { + this.lblMessage.setText(message); + this.selected = false; + this.mode = mode; + switch (this.mode) { + case INFORM: + this.btnLeft.setVisible(false); + this.btnRight.setVisible(false); + break; + case QUESTION: + this.btnLeft.setVisible(true); + this.btnLeft.setText("Yes"); + this.btnRight.setVisible(true); + this.btnRight.setText("No"); + break; + case CONFIRM: + this.btnLeft.setVisible(true); + this.btnLeft.setText("OK"); + this.btnRight.setVisible(true); + this.btnRight.setText("Cancel"); + break; + case CANCEL: + this.btnLeft.setVisible(false); + this.btnRight.setVisible(true); + this.btnRight.setText("Cancel"); + break; + case SELECT: + this.btnLeft.setVisible(false); + this.btnRight.setVisible(true); + this.btnRight.setText("Done"); + break; + } + if (modal) + startModal(); + this.revalidate(); + } + + public void clear() { + stopModal(); + this.btnLeft.setVisible(false); + this.btnRight.setVisible(false); + this.lblMessage.setText(""); + } + + private synchronized void startModal() { + + try { + if (SwingUtilities.isEventDispatchThread()) { + EventQueue theQueue = getToolkit().getSystemEventQueue(); + while (!selected) { + AWTEvent event = theQueue.getNextEvent(); + Object source = event.getSource(); + boolean dispatch = true; + + if (event instanceof MouseEvent) { + MouseEvent e = (MouseEvent) event; + MouseEvent m = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, this); + if (!this.contains(m.getPoint()) && e.getID() != MouseEvent.MOUSE_DRAGGED) { + dispatch = false; + } + } + + if (dispatch) { + if (event instanceof ActiveEvent) { + ((ActiveEvent) event).dispatch(); + } else if (source instanceof Component) { + ((Component) source).dispatchEvent(event); + } else if (source instanceof MenuComponent) { + ((MenuComponent) source).dispatchEvent(event); + } else { + logger.info("Unable to dispatch: " + event); + } + } + } + } else { + while (!selected) { + wait(); + } + } + } catch (InterruptedException ignored) { + } + + } + + private synchronized void stopModal() { + notifyAll(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnRight = new javax.swing.JButton(); + btnLeft = new javax.swing.JButton(); + jScrollPane1 = new javax.swing.JScrollPane(); + lblMessage = new javax.swing.JTextArea(); + + setBackground(new java.awt.Color(204, 204, 204)); + + btnRight.setText("Cancel"); + btnRight.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnRightActionPerformed(evt); + } + }); + + btnLeft.setText("OK"); + btnLeft.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnLeftActionPerformed(evt); + } + }); + + jScrollPane1.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + lblMessage.setBackground(new java.awt.Color(204, 204, 204)); + lblMessage.setColumns(20); + lblMessage.setEditable(false); + lblMessage.setLineWrap(true); + lblMessage.setRows(2); + lblMessage.setWrapStyleWord(true); + lblMessage.setBorder(null); + jScrollPane1.setViewportView(lblMessage); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap(106, Short.MAX_VALUE) + .addComponent(btnLeft) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnRight)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 81, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnRight) + .addComponent(btnLeft))) + ); + }// //GEN-END:initComponents + + private void btnRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRightActionPerformed + this.selected = true; + clear(); + if (mode == FeedbackMode.SELECT && (evt.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) + session.sendPlayerInteger(gameId, 0); + else + session.sendPlayerBoolean(gameId, false); + }//GEN-LAST:event_btnRightActionPerformed + + private void btnLeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLeftActionPerformed + this.selected = true; + clear(); + session.sendPlayerBoolean(gameId, true); + }//GEN-LAST:event_btnLeftActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnLeft; + private javax.swing.JButton btnRight; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextArea lblMessage; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/GamePane.form b/Mage.Client/src/mage/client/game/GamePane.form new file mode 100644 index 00000000000..f2f67e79ec2 --- /dev/null +++ b/Mage.Client/src/mage/client/game/GamePane.form @@ -0,0 +1,41 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/GamePane.java b/Mage.Client/src/mage/client/game/GamePane.java new file mode 100644 index 00000000000..bb98dfc626d --- /dev/null +++ b/Mage.Client/src/mage/client/game/GamePane.java @@ -0,0 +1,97 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * GamePane.java + * + * Created on Dec 17, 2009, 9:34:10 AM + */ + +package mage.client.game; + +import mage.client.*; +import java.util.UUID; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GamePane extends MagePane { + + /** Creates new form GamePane */ + public GamePane() { + initComponents(); + } + + public void showGame(UUID gameId, UUID playerId) { + gamePanel.showGame(gameId, playerId); + } + + public void watchGame(UUID gameId) { + gamePanel.watchGame(gameId); + } + + public void replayGame(UUID gameId) { + gamePanel.replayGame(gameId); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jScrollPane1 = new javax.swing.JScrollPane(); + gamePanel = new mage.client.game.GamePanel(); + + jScrollPane1.setViewportView(gamePanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 894, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 651, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.game.GamePanel gamePanel; + private javax.swing.JScrollPane jScrollPane1; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/GamePanel.form b/Mage.Client/src/mage/client/game/GamePanel.form new file mode 100644 index 00000000000..c2479912d30 --- /dev/null +++ b/Mage.Client/src/mage/client/game/GamePanel.form @@ -0,0 +1,430 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/GamePanel.java b/Mage.Client/src/mage/client/game/GamePanel.java new file mode 100644 index 00000000000..f1d6d1aea9e --- /dev/null +++ b/Mage.Client/src/mage/client/game/GamePanel.java @@ -0,0 +1,597 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * GamePanel.java + * + * Created on Dec 16, 2009, 9:29:58 AM + */ + +package mage.client.game; + +import java.awt.MouseInfo; +import java.util.logging.Level; +import mage.client.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Logger; +import javax.swing.JLayeredPane; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import mage.cards.decks.DeckCardLists; +import mage.client.dialog.CombatDialog; +import mage.client.dialog.ExileZoneDialog; +import mage.client.dialog.PickChoiceDialog; +import mage.client.dialog.PickNumberDialog; +import mage.client.dialog.ShowCardsDialog; +import mage.client.game.FeedbackPanel.FeedbackMode; +import mage.client.remote.GameClientImpl; +import mage.client.remote.GameReplayClientImpl; +import mage.client.remote.Session; +import mage.interfaces.GameClient; +import mage.interfaces.GameReplayClient; +import mage.util.Logging; +import mage.view.AbilityPickerView; +import mage.view.CardsView; +import mage.view.ExileView; +import mage.view.GameView; +import mage.view.PlayerView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GamePanel extends javax.swing.JPanel { + + private final static Logger logger = Logging.getLogger(GamePanel.class.getName()); + + private Map players = new HashMap(); + private Map exiles = new HashMap(); + private UUID gameId; + private GameClient gameClient; + private GameReplayClient replayClient; + private Session session; + private CombatDialog combat = new CombatDialog(); + + /** Creates new form GamePanel */ + public GamePanel() { + initComponents(); + } + + public void showGame(UUID gameId, UUID playerId) { + this.gameId = gameId; + session = MageFrame.getSession(); + gameClient = new GameClientImpl(this); + this.feedbackPanel.init(gameId); + this.feedbackPanel.clear(); + this.abilityPicker.init(session, gameId); + this.btnConcede.setVisible(true); + this.pnlReplay.setVisible(false); + this.btnStopWatching.setVisible(false); + this.setVisible(true); + this.chatPanel.connect(session.getGameChatId(gameId)); + if (!session.joinGame(gameId, gameClient)) + hideGame(); + } + + public void watchGame(UUID gameId) { + this.gameId = gameId; + gameClient = new GameClientImpl(this); + this.feedbackPanel.init(gameId); + this.feedbackPanel.clear(); + this.btnConcede.setVisible(false); + this.btnStopWatching.setVisible(true); + this.pnlReplay.setVisible(false); + this.setVisible(true); + this.chatPanel.connect(session.getGameChatId(gameId)); + if (!session.watchGame(gameId, gameClient)) + hideGame(); + } + + public void replayGame(UUID gameId) { + this.gameId = gameId; + replayClient = new GameReplayClientImpl(this); + this.feedbackPanel.clear(); + this.btnConcede.setVisible(false); + this.btnStopWatching.setVisible(false); + this.pnlReplay.setVisible(true); + this.setVisible(true); + if (!session.replayGame(gameId, replayClient)) + hideGame(); + } + + public void hideGame() { + this.chatPanel.disconnect(); + this.players.clear(); + this.pnlBattlefield.removeAll(); + + this.setVisible(false); + } + + public void init(GameView game) { + combat.init(gameId, bigCard); + MageFrame.getDesktop().add(combat, JLayeredPane.PALETTE_LAYER); + this.players.clear(); + this.pnlBattlefield.removeAll(); + for (PlayerView player: game.getPlayers()) { + PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId); + players.put(player.getPlayerId(), playerPanel); + this.pnlBattlefield.add(playerPanel); + playerPanel.setVisible(true); + } + updateGame(game); + } + + public void updateGame(GameView game) { + if (game.getHand() != null) + this.hand.loadCards(game.getHand(), bigCard, gameId); + else + this.hand.setVisible(false); + if (game.getPhase() != null) + this.txtPhase.setText(game.getPhase().toString()); + if (game.getStep() != null) + this.txtStep.setText(game.getStep().toString()); + this.txtActivePlayer.setText(game.getActivePlayerName()); + this.txtPriority.setText(game.getPriorityPlayerName()); + this.txtTurn.setText(Integer.toString(game.getTurn())); + for (PlayerView player: game.getPlayers()) { + players.get(player.getPlayerId()).update(player); + } + this.stack.loadCards(game.getStack(), bigCard, gameId); + for (ExileView exile: game.getExile()) { + if (!exiles.containsKey(exile.getId())) { + ExileZoneDialog newExile = new ExileZoneDialog(); + exiles.put(exile.getId(), newExile); + } + exiles.get(exile.getId()).loadCards(exile, bigCard, gameId); + } + if (game.getCombat().size() > 0) { + combat.showDialog(game.getCombat()); + } + else { + combat.hideDialog(); + } + this.revalidate(); + this.repaint(); + } + + public void ask(String question) { + this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, true); + } + + public void inform(String information, CardsView cardView, GameView gameView) { + updateGame(gameView); + if (cardView != null && cardView.size() > 0) { + showCards(information, cardView); + } + this.feedbackPanel.getFeedback(FeedbackMode.INFORM, information, false); + } + + public void cancel(String message, CardsView cardView, GameView gameView) { + updateGame(gameView); + if (cardView != null && cardView.size() > 0) { + showCards(message, cardView); + } + this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, false); + } + + public void modalMessage(String message) { + JOptionPane.showMessageDialog(this, message, "", JOptionPane.INFORMATION_MESSAGE); + } + + public int modalQuestion(String message, String title) { + return JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION); + } + + public JPanel getHand() { + return hand; + } + + public void select(String message, GameView gameView) { + updateGame(gameView); + this.feedbackPanel.getFeedback(FeedbackMode.SELECT, message, false); + } + + public void playMana(String message, GameView gameView) { + updateGame(gameView); + this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, false); + } + + public void playXMana(String message, GameView gameView) { + updateGame(gameView); + this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, false); + } + + public void replayMessage(String message) { + //TODO: implement this + } + + public void pickAbility(AbilityPickerView choices) { + this.abilityPicker.show(choices, MouseInfo.getPointerInfo().getLocation()); + } + + public void revealCards(String name, CardsView cards) { + ShowCardsDialog showCards = new ShowCardsDialog(); + MageFrame.getDesktop().add(showCards); + showCards.loadCards(name, cards, bigCard, gameId); + } + + private void showCards(String title, CardsView cards) { + ShowCardsDialog showCards = new ShowCardsDialog(); + showCards.loadCards(title, cards, bigCard, gameId); + } + + public void getAmount(int min, int max) { + PickNumberDialog pickNumber = new PickNumberDialog(); + pickNumber.showDialog(min, max); + if (pickNumber.isCancel()) + session.sendPlayerBoolean(gameId, false); + else + session.sendPlayerInteger(gameId, pickNumber.getAmount()); + } + + public void getChoice(String message, String[] choices) { + PickChoiceDialog pickChoice = new PickChoiceDialog(); + pickChoice.showDialog(message, choices); + session.sendPlayerString(gameId, pickChoice.getChoice()); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + abilityPicker = new mage.client.game.AbilityPicker(); + jSplitPane1 = new javax.swing.JSplitPane(); + jPanel3 = new javax.swing.JPanel(); + pnlGameInfo = new javax.swing.JPanel(); + lblPhase = new javax.swing.JLabel(); + txtPhase = new javax.swing.JLabel(); + lblStep = new javax.swing.JLabel(); + txtStep = new javax.swing.JLabel(); + lblTurn = new javax.swing.JLabel(); + txtTurn = new javax.swing.JLabel(); + txtActivePlayer = new javax.swing.JLabel(); + lblActivePlayer = new javax.swing.JLabel(); + txtPriority = new javax.swing.JLabel(); + lblPriority = new javax.swing.JLabel(); + feedbackPanel = new mage.client.game.FeedbackPanel(); + btnConcede = new javax.swing.JButton(); + btnStopWatching = new javax.swing.JButton(); + bigCard = new mage.client.cards.BigCard(); + stack = new mage.client.cards.Cards(); + btnCheat = new javax.swing.JButton(); + pnlReplay = new javax.swing.JPanel(); + btnStopReplay = new javax.swing.JButton(); + btnPreviousPlay = new javax.swing.JButton(); + btnNextPlay = new javax.swing.JButton(); + pnlHand = new javax.swing.JPanel(); + hand = new mage.client.cards.Cards(); + pnlBattlefield = new javax.swing.JPanel(); + chatPanel = new mage.client.chat.ChatPanel(); + + jSplitPane1.setDividerLocation(1000); + jSplitPane1.setDividerSize(3); + jSplitPane1.setResizeWeight(1.0); + + pnlGameInfo.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + lblPhase.setLabelFor(txtPhase); + lblPhase.setText("Phase:"); + + txtPhase.setText("Phase"); + txtPhase.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtPhase.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblStep.setLabelFor(txtStep); + lblStep.setText("Step:"); + + txtStep.setText("Step"); + txtStep.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtStep.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblTurn.setLabelFor(txtTurn); + lblTurn.setText("Turn:"); + + txtTurn.setText("Turn"); + txtTurn.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtTurn.setMinimumSize(new java.awt.Dimension(0, 16)); + + txtActivePlayer.setText("Active Player"); + txtActivePlayer.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtActivePlayer.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblActivePlayer.setLabelFor(txtActivePlayer); + lblActivePlayer.setText("Active Player:"); + + txtPriority.setText("Priority Player"); + txtPriority.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(153, 153, 153), 1, true)); + txtPriority.setMinimumSize(new java.awt.Dimension(0, 16)); + + lblPriority.setLabelFor(txtPriority); + lblPriority.setText("Priority Player:"); + + feedbackPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + feedbackPanel.setMaximumSize(new java.awt.Dimension(208, 121)); + feedbackPanel.setMinimumSize(new java.awt.Dimension(208, 121)); + + btnConcede.setText("Concede"); + btnConcede.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnConcedeActionPerformed(evt); + } + }); + + btnStopWatching.setText("Stop Watching"); + btnStopWatching.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnStopWatchingActionPerformed(evt); + } + }); + + btnCheat.setText("?"); + btnCheat.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnCheatActionPerformed(evt); + } + }); + + btnStopReplay.setText("Stop"); + btnStopReplay.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnStopReplayActionPerformed(evt); + } + }); + + btnPreviousPlay.setText("Previous"); + btnPreviousPlay.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPreviousPlayActionPerformed(evt); + } + }); + + btnNextPlay.setText("Next"); + btnNextPlay.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnNextPlayActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnlReplayLayout = new javax.swing.GroupLayout(pnlReplay); + pnlReplay.setLayout(pnlReplayLayout); + pnlReplayLayout.setHorizontalGroup( + pnlReplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlReplayLayout.createSequentialGroup() + .addComponent(btnStopReplay) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnPreviousPlay) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnNextPlay)) + ); + pnlReplayLayout.setVerticalGroup( + pnlReplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlReplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnStopReplay) + .addComponent(btnPreviousPlay) + .addComponent(btnNextPlay)) + ); + + javax.swing.GroupLayout pnlGameInfoLayout = new javax.swing.GroupLayout(pnlGameInfo); + pnlGameInfo.setLayout(pnlGameInfoLayout); + pnlGameInfoLayout.setHorizontalGroup( + pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlGameInfoLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblPriority) + .addComponent(lblPhase) + .addComponent(lblStep) + .addComponent(lblTurn) + .addComponent(lblActivePlayer)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(txtActivePlayer, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE) + .addComponent(txtPriority, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE) + .addComponent(txtTurn, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE) + .addComponent(txtStep, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE) + .addComponent(txtPhase, javax.swing.GroupLayout.DEFAULT_SIZE, 159, Short.MAX_VALUE)) + .addContainerGap()) + .addGroup(pnlGameInfoLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(btnConcede) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnStopWatching) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnCheat) + .addContainerGap(19, Short.MAX_VALUE)) + .addComponent(bigCard, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + .addComponent(feedbackPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + .addComponent(stack, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + .addGroup(pnlGameInfoLayout.createSequentialGroup() + .addContainerGap() + .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(51, Short.MAX_VALUE)) + ); + pnlGameInfoLayout.setVerticalGroup( + pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnlGameInfoLayout.createSequentialGroup() + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblPhase) + .addComponent(txtPhase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(3, 3, 3) + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblStep) + .addComponent(txtStep, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(3, 3, 3) + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblTurn) + .addComponent(txtTurn, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(3, 3, 3) + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblActivePlayer) + .addComponent(txtActivePlayer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(3, 3, 3) + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblPriority) + .addComponent(txtPriority, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(feedbackPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(stack, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnlReplay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnlGameInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnConcede) + .addComponent(btnStopWatching) + .addComponent(btnCheat))) + ); + + pnlHand.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + javax.swing.GroupLayout pnlHandLayout = new javax.swing.GroupLayout(pnlHand); + pnlHand.setLayout(pnlHandLayout); + pnlHandLayout.setHorizontalGroup( + pnlHandLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(hand, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 735, Short.MAX_VALUE) + ); + pnlHandLayout.setVerticalGroup( + pnlHandLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(hand, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 209, Short.MAX_VALUE) + ); + + pnlBattlefield.setLayout(new java.awt.GridLayout(0, 1)); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(pnlGameInfo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pnlHand, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnlBattlefield, javax.swing.GroupLayout.DEFAULT_SIZE, 739, Short.MAX_VALUE))) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() + .addComponent(pnlBattlefield, javax.swing.GroupLayout.DEFAULT_SIZE, 632, Short.MAX_VALUE) + .addGap(0, 0, 0) + .addComponent(pnlHand, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(pnlGameInfo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + + jSplitPane1.setLeftComponent(jPanel3); + jSplitPane1.setRightComponent(chatPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 1078, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 847, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void btnConcedeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnConcedeActionPerformed + if (modalQuestion("Are you sure you want to concede?", "Confirm concede") == JOptionPane.YES_OPTION) { + session.concedeGame(gameId); + } + }//GEN-LAST:event_btnConcedeActionPerformed + + private void btnStopWatchingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopWatchingActionPerformed + if (modalQuestion("Are you sure you want to stop watching?", "Stop watching") == JOptionPane.YES_OPTION) { + session.stopWatching(gameId, ((GameClientImpl)gameClient).getIdLocal()); + } + }//GEN-LAST:event_btnStopWatchingActionPerformed + + private void btnStopReplayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopReplayActionPerformed + if (modalQuestion("Are you sure you want to stop replay?", "Stop replay") == JOptionPane.YES_OPTION) { + session.stopReplay(); + } + }//GEN-LAST:event_btnStopReplayActionPerformed + + private void btnNextPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNextPlayActionPerformed + session.nextPlay(); + }//GEN-LAST:event_btnNextPlayActionPerformed + + private void btnPreviousPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPreviousPlayActionPerformed + session.previousPlay(); + }//GEN-LAST:event_btnPreviousPlayActionPerformed + + private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheatActionPerformed + try { + session.cheat(gameId, DeckCardLists.load("cheat.dck")); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } + }//GEN-LAST:event_btnCheatActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.game.AbilityPicker abilityPicker; + private mage.client.cards.BigCard bigCard; + private javax.swing.JButton btnCheat; + private javax.swing.JButton btnConcede; + private javax.swing.JButton btnNextPlay; + private javax.swing.JButton btnPreviousPlay; + private javax.swing.JButton btnStopReplay; + private javax.swing.JButton btnStopWatching; + private mage.client.chat.ChatPanel chatPanel; + private mage.client.game.FeedbackPanel feedbackPanel; + private mage.client.cards.Cards hand; + private javax.swing.JPanel jPanel3; + private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JLabel lblActivePlayer; + private javax.swing.JLabel lblPhase; + private javax.swing.JLabel lblPriority; + private javax.swing.JLabel lblStep; + private javax.swing.JLabel lblTurn; + private javax.swing.JPanel pnlBattlefield; + private javax.swing.JPanel pnlGameInfo; + private javax.swing.JPanel pnlHand; + private javax.swing.JPanel pnlReplay; + private mage.client.cards.Cards stack; + private javax.swing.JLabel txtActivePlayer; + private javax.swing.JLabel txtPhase; + private javax.swing.JLabel txtPriority; + private javax.swing.JLabel txtStep; + private javax.swing.JLabel txtTurn; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/ManaPool.form b/Mage.Client/src/mage/client/game/ManaPool.form new file mode 100644 index 00000000000..b0619238725 --- /dev/null +++ b/Mage.Client/src/mage/client/game/ManaPool.form @@ -0,0 +1,174 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/ManaPool.java b/Mage.Client/src/mage/client/game/ManaPool.java new file mode 100644 index 00000000000..309e5706c27 --- /dev/null +++ b/Mage.Client/src/mage/client/game/ManaPool.java @@ -0,0 +1,189 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * ManaPool.java + * + * Created on Dec 22, 2009, 9:52:00 AM + */ + +package mage.client.game; + +import mage.view.ManaPoolView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ManaPool extends javax.swing.JPanel { + + /** Creates new form ManaPool */ + public ManaPool() { + initComponents(); + } + + public void update(ManaPoolView pool) { + this.btnBlack.setText(Integer.toString(pool.getBlack())); + this.btnRed.setText(Integer.toString(pool.getRed())); + this.btnWhite.setText(Integer.toString(pool.getWhite())); + this.btnGreen.setText(Integer.toString(pool.getGreen())); + this.btnBlue.setText(Integer.toString(pool.getBlue())); + this.btnColorless.setText(Integer.toString(pool.getColorless())); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + lblBlack = new javax.swing.JLabel(); + btnBlack = new javax.swing.JButton(); + btnBlue = new javax.swing.JButton(); + lblBlue = new javax.swing.JLabel(); + lblGreen = new javax.swing.JLabel(); + btnGreen = new javax.swing.JButton(); + btnColorless = new javax.swing.JButton(); + lblWhite = new javax.swing.JLabel(); + lblColorless = new javax.swing.JLabel(); + btnWhite = new javax.swing.JButton(); + btnRed = new javax.swing.JButton(); + lblRed = new javax.swing.JLabel(); + + lblBlack.setLabelFor(btnBlack); + lblBlack.setText("Black"); + + btnBlack.setText("0"); + + btnBlue.setText("0"); + + lblBlue.setLabelFor(btnBlack); + lblBlue.setText("Blue"); + + lblGreen.setLabelFor(btnBlack); + lblGreen.setText("Green"); + + btnGreen.setText("0"); + + btnColorless.setText("0"); + + lblWhite.setLabelFor(btnBlack); + lblWhite.setText("White"); + + lblColorless.setLabelFor(btnBlack); + lblColorless.setText("Colorless"); + + btnWhite.setText("0"); + + btnRed.setText("0"); + + lblRed.setLabelFor(btnBlack); + lblRed.setText("Red"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(lblGreen) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(btnGreen, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblColorless) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(btnColorless, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblWhite) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 19, Short.MAX_VALUE) + .addComponent(btnWhite, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblRed) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 28, Short.MAX_VALUE) + .addComponent(btnRed, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblBlack) + .addComponent(lblBlue)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 23, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(btnBlack, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(btnBlue, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblBlack) + .addComponent(btnBlack, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(1, 1, 1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnBlue, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblBlue)) + .addGap(1, 1, 1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblGreen) + .addComponent(btnGreen, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(1, 1, 1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblRed) + .addComponent(btnRed, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(1, 1, 1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblWhite) + .addComponent(btnWhite, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(1, 1, 1) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lblColorless) + .addComponent(btnColorless, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnBlack; + private javax.swing.JButton btnBlue; + private javax.swing.JButton btnColorless; + private javax.swing.JButton btnGreen; + private javax.swing.JButton btnRed; + private javax.swing.JButton btnWhite; + private javax.swing.JLabel lblBlack; + private javax.swing.JLabel lblBlue; + private javax.swing.JLabel lblColorless; + private javax.swing.JLabel lblGreen; + private javax.swing.JLabel lblRed; + private javax.swing.JLabel lblWhite; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/PlayAreaPanel.form b/Mage.Client/src/mage/client/game/PlayAreaPanel.form new file mode 100644 index 00000000000..7c38b0f3dba --- /dev/null +++ b/Mage.Client/src/mage/client/game/PlayAreaPanel.form @@ -0,0 +1,90 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/mage/client/game/PlayAreaPanel.java new file mode 100644 index 00000000000..ffc6db906a5 --- /dev/null +++ b/Mage.Client/src/mage/client/game/PlayAreaPanel.java @@ -0,0 +1,142 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * PlayAreaPanel.java + * + * Created on Dec 22, 2009, 10:41:54 AM + */ + +package mage.client.game; + +import java.util.UUID; +import mage.client.cards.BigCard; +import mage.view.PlayerView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PlayAreaPanel extends javax.swing.JPanel { + + + /** Creates new form PlayAreaPanel */ + public PlayAreaPanel() { + initComponents(); + } + + public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId) { + this(); + init(player, bigCard, gameId); + update(player); + } + + public void init(PlayerView player, BigCard bigCard, UUID gameId) { + this.playerPanel.init(gameId, player.getPlayerId(), bigCard); + this.battlefieldPanel.init(gameId, bigCard); + } + + public void update(PlayerView player) { + this.playerPanel.update(player); + this.manaPool.update(player.getManaPool()); + this.battlefieldPanel.update(player.getBattlefield()); + } + + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + playerPanel = new mage.client.game.PlayerPanel(); + manaPool = new mage.client.game.ManaPool(); + jScrollPane1 = new javax.swing.JScrollPane(); + battlefieldPanel = new mage.client.game.BattlefieldPanel(); + + jPanel1.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(manaPool, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE) + .addComponent(playerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(playerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(manaPool, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(64, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout battlefieldPanelLayout = new javax.swing.GroupLayout(battlefieldPanel); + battlefieldPanel.setLayout(battlefieldPanelLayout); + battlefieldPanelLayout.setHorizontalGroup( + battlefieldPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 522, Short.MAX_VALUE) + ); + battlefieldPanelLayout.setVerticalGroup( + battlefieldPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 300, Short.MAX_VALUE) + ); + + jScrollPane1.setViewportView(battlefieldPanel); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 524, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private mage.client.game.BattlefieldPanel battlefieldPanel; + private javax.swing.JPanel jPanel1; + private javax.swing.JScrollPane jScrollPane1; + private mage.client.game.ManaPool manaPool; + private mage.client.game.PlayerPanel playerPanel; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/game/PlayerPanel.form b/Mage.Client/src/mage/client/game/PlayerPanel.form new file mode 100644 index 00000000000..a1141f257f8 --- /dev/null +++ b/Mage.Client/src/mage/client/game/PlayerPanel.form @@ -0,0 +1,156 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Mage.Client/src/mage/client/game/PlayerPanel.java b/Mage.Client/src/mage/client/game/PlayerPanel.java new file mode 100644 index 00000000000..23aacef53d1 --- /dev/null +++ b/Mage.Client/src/mage/client/game/PlayerPanel.java @@ -0,0 +1,208 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +/* + * PlayerPanel.java + * + * Created on Nov 18, 2009, 3:01:31 PM + */ + +package mage.client.game; + +import java.util.UUID; +import mage.client.MageFrame; +import mage.client.cards.BigCard; +import mage.client.dialog.ShowCardsDialog; +import mage.client.remote.Session; +import mage.view.PlayerView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PlayerPanel extends javax.swing.JPanel { + + private UUID playerId; + private UUID gameId; + private Session session; + private PlayerView player; + + private ShowCardsDialog graveyard; + private BigCard bigCard; + + /** Creates new form PlayerPanel */ + public PlayerPanel() { + initComponents(); + } + + public void init(UUID gameId, UUID playerId, BigCard bigCard) { + this.gameId = gameId; + this.playerId = playerId; + this.bigCard = bigCard; + session = MageFrame.getSession(); + } + + public void update(PlayerView player) { + this.player = player; + this.txtLife.setText(Integer.toString(player.getLife())); + this.txtHand.setText(Integer.toString(player.getHandCount())); + this.txtLibrary.setText(Integer.toString(player.getLibraryCount())); + this.btnGrave.setText(Integer.toString(player.getGraveyard().size())); + this.btnPlayerName.setText(player.getName()); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + btnPlayerName = new javax.swing.JButton(); + lblLife = new javax.swing.JLabel(); + lblLibrary = new javax.swing.JLabel(); + lblHand = new javax.swing.JLabel(); + txtLife = new javax.swing.JLabel(); + txtLibrary = new javax.swing.JLabel(); + txtHand = new javax.swing.JLabel(); + lblGrave = new javax.swing.JLabel(); + btnGrave = new javax.swing.JButton(); + + setName("Form"); // NOI18N + + btnPlayerName.setText("Player Name"); // NOI18N + btnPlayerName.setName("btnPlayerName"); // NOI18N + btnPlayerName.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnPlayerNameActionPerformed(evt); + } + }); + + lblLife.setLabelFor(txtLife); + lblLife.setText("Life:"); // NOI18N + lblLife.setName("lblLife"); // NOI18N + + lblLibrary.setLabelFor(txtLibrary); + lblLibrary.setText("Library:"); // NOI18N + lblLibrary.setName("lblLibrary"); // NOI18N + + lblHand.setLabelFor(txtHand); + lblHand.setText("Hand:"); // NOI18N + lblHand.setName("lblHand"); // NOI18N + + txtLife.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + txtLife.setName("txtLife"); // NOI18N + + txtLibrary.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + txtLibrary.setName("txtLibrary"); // NOI18N + + txtHand.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0))); + txtHand.setName("txtHand"); // NOI18N + + lblGrave.setLabelFor(btnGrave); + lblGrave.setText("Grave:"); // NOI18N + lblGrave.setName("lblGrave"); // NOI18N + + btnGrave.setName("btnGrave"); // NOI18N + btnGrave.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + btnGraveActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblLife, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 42, Short.MAX_VALUE) + .addComponent(lblGrave, javax.swing.GroupLayout.DEFAULT_SIZE, 42, Short.MAX_VALUE) + .addComponent(lblHand, javax.swing.GroupLayout.DEFAULT_SIZE, 42, Short.MAX_VALUE) + .addComponent(lblLibrary, javax.swing.GroupLayout.DEFAULT_SIZE, 42, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtLife, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) + .addComponent(txtLibrary, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) + .addComponent(txtHand, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) + .addComponent(btnGrave, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE)) + .addContainerGap()) + .addComponent(btnPlayerName, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(btnPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtLife, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblLife, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtLibrary, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblLibrary, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtHand, javax.swing.GroupLayout.DEFAULT_SIZE, 14, Short.MAX_VALUE) + .addComponent(lblHand)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(lblGrave) + .addComponent(btnGrave, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + }// //GEN-END:initComponents + + private void btnPlayerNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlayerNameActionPerformed + session.sendPlayerUUID(gameId, playerId); + }//GEN-LAST:event_btnPlayerNameActionPerformed + + private void btnGraveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGraveActionPerformed + if (graveyard == null) { + graveyard = new ShowCardsDialog(); + } + graveyard.loadCards(player.getName() + " graveyard", player.getGraveyard(), bigCard, gameId); + }//GEN-LAST:event_btnGraveActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton btnGrave; + private javax.swing.JButton btnPlayerName; + private javax.swing.JLabel lblGrave; + private javax.swing.JLabel lblHand; + private javax.swing.JLabel lblLibrary; + private javax.swing.JLabel lblLife; + private javax.swing.JLabel txtHand; + private javax.swing.JLabel txtLibrary; + private javax.swing.JLabel txtLife; + // End of variables declaration//GEN-END:variables + +} diff --git a/Mage.Client/src/mage/client/remote/ClientImpl.java b/Mage.Client/src/mage/client/remote/ClientImpl.java new file mode 100644 index 00000000000..eb2cd31ef44 --- /dev/null +++ b/Mage.Client/src/mage/client/remote/ClientImpl.java @@ -0,0 +1,97 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.remote; + +import java.io.Serializable; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.client.MageFrame; +import mage.interfaces.Client; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ClientImpl implements Client, Serializable { + + private final static Logger logger = Logging.getLogger(ClientImpl.class.getName()); + + private UUID clientId; + private String userName; + private MageFrame frame; + + public ClientImpl(MageFrame frame, String userName) { + + this.clientId = UUID.randomUUID(); + this.userName = userName; + this.frame = frame; + try { + UnicastRemoteObject.exportObject(this, 0); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + + } + + @Override + public UUID getId() throws RemoteException { + return clientId; + } + + @Override + public UUID getPlayerId() throws RemoteException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void gameStarted(UUID gameId, UUID playerId) throws RemoteException { + frame.showGame(gameId, playerId); + logger.info("Game client started for player " + playerId); + } + + @Override + public String getUserName() throws RemoteException { + return userName; + } + + @Override + public void watchGame(UUID gameId) throws RemoteException { + frame.watchGame(gameId); + } + + @Override + public void replayGame(UUID gameId) throws RemoteException { + frame.replayGame(gameId); + } + +} diff --git a/Mage.Client/src/mage/client/remote/GameClientImpl.java b/Mage.Client/src/mage/client/remote/GameClientImpl.java new file mode 100644 index 00000000000..ea80ecbdd04 --- /dev/null +++ b/Mage.Client/src/mage/client/remote/GameClientImpl.java @@ -0,0 +1,151 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.remote; + +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.client.game.GamePanel; +import mage.interfaces.GameClient; +import mage.interfaces.MageException; +import mage.util.Logging; +import mage.view.AbilityPickerView; +import mage.view.CardsView; +import mage.view.GameView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameClientImpl implements GameClient { + + private final static Logger logger = Logging.getLogger(GameClientImpl.class.getName()); + + private UUID gameClientId; + private GamePanel gamePanel; + + public GameClientImpl(GamePanel gamePanel) { + gameClientId = UUID.randomUUID(); + this.gamePanel = gamePanel; + try { + UnicastRemoteObject.exportObject(this, 0); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + @Override + public synchronized UUID getId() throws RemoteException { + return gameClientId; + } + + public UUID getIdLocal() { + return gameClientId; + } + + @Override + public synchronized void update(GameView gameView) throws RemoteException { + logger.info("Received update event for game"); + gamePanel.updateGame(gameView); + } + + @Override + public synchronized void init(GameView gameView) throws RemoteException { + gamePanel.init(gameView); + } + + @Override + public synchronized void ask(String question, GameView gameView) throws RemoteException { + gamePanel.updateGame(gameView); + gamePanel.ask(question); + } + + @Override + public synchronized void inform(String message, GameView gameView) throws RemoteException { + gamePanel.inform(message, null, gameView); + } + + @Override + public synchronized void target(String message, CardsView cardView, boolean required, GameView gameView) throws RemoteException { + if (required) { + gamePanel.inform(message, cardView, gameView); + } else { + gamePanel.cancel(message, cardView, gameView); + } + } + + @Override + public synchronized void gameOver(String message) throws RemoteException { + gamePanel.modalMessage(message); + gamePanel.hideGame(); + } + + @Override + public synchronized void select(String message, GameView gameView) throws RemoteException { + gamePanel.select(message, gameView); + } + + @Override + public synchronized void playMana(String message, GameView gameView) throws RemoteException { + gamePanel.playMana(message, gameView); + } + + @Override + public synchronized void playXMana(String message, GameView gameView) throws RemoteException { + gamePanel.playXMana(message, gameView); + } + + @Override + public synchronized void chooseAbility(AbilityPickerView abilities) throws RemoteException { + gamePanel.pickAbility(abilities); + } + + public void handleException(Exception ex) throws MageException { + logger.log(Level.SEVERE, "", ex); + throw new MageException("Server error"); + } + + @Override + public synchronized void revealCards(String name, CardsView cards) throws RemoteException { + gamePanel.revealCards(name, cards); + } + + @Override + public synchronized void getAmount(int min, int max) throws RemoteException { + gamePanel.getAmount(min, max); + } + + @Override + public synchronized void choose(String message, String[] choices) throws RemoteException { + gamePanel.getChoice(message, choices); + } + +} diff --git a/Mage.Client/src/mage/client/remote/GameReplayClientImpl.java b/Mage.Client/src/mage/client/remote/GameReplayClientImpl.java new file mode 100644 index 00000000000..71c18a76832 --- /dev/null +++ b/Mage.Client/src/mage/client/remote/GameReplayClientImpl.java @@ -0,0 +1,87 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.remote; + +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.client.game.GamePanel; +import mage.interfaces.GameReplayClient; +import mage.util.Logging; +import mage.view.GameView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameReplayClientImpl implements GameReplayClient { + + private final static Logger logger = Logging.getLogger(GameClientImpl.class.getName()); + + private UUID replayClientId; + private GamePanel gamePanel; + + public GameReplayClientImpl(GamePanel gamePanel) { + replayClientId = UUID.randomUUID(); + this.gamePanel = gamePanel; + try { + UnicastRemoteObject.exportObject(this, 0); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + @Override + public UUID getId() throws RemoteException { + return replayClientId; + } + + @Override + public synchronized void update(GameView game) throws RemoteException { + gamePanel.updateGame(game); + } + + @Override + public synchronized void init(GameView gameView) throws RemoteException { + gamePanel.init(gameView); + } + + @Override + public synchronized void gameOver(String message) throws RemoteException { + gamePanel.modalMessage(message); + gamePanel.hideGame(); + } + + public synchronized void message(String message) throws RemoteException { + gamePanel.replayMessage(message); + } + +} diff --git a/Mage.Client/src/mage/client/remote/MageRemoteException.java b/Mage.Client/src/mage/client/remote/MageRemoteException.java new file mode 100644 index 00000000000..006252fd760 --- /dev/null +++ b/Mage.Client/src/mage/client/remote/MageRemoteException.java @@ -0,0 +1,37 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.remote; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class MageRemoteException extends Exception { + +} diff --git a/Mage.Client/src/mage/client/remote/Session.java b/Mage.Client/src/mage/client/remote/Session.java new file mode 100644 index 00000000000..d662059bda4 --- /dev/null +++ b/Mage.Client/src/mage/client/remote/Session.java @@ -0,0 +1,491 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.remote; + +import java.rmi.NotBoundException; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.JOptionPane; +import mage.Constants; +import mage.cards.decks.DeckCardLists; +import mage.client.MageFrame; +import mage.client.util.Config; +import mage.interfaces.ChatClient; +import mage.interfaces.Client; +import mage.interfaces.GameClient; +import mage.interfaces.GameReplayClient; +import mage.interfaces.MageException; +import mage.interfaces.Server; +import mage.util.Logging; +import mage.view.TableView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Session { + + private final static Logger logger = Logging.getLogger(Session.class.getName()); + + private UUID sessionId; + private Server server; + private Client client; + private String userName; + private MageFrame frame; + private String[] playerTypes; + private String[] gameTypes; + + public Session(MageFrame frame) { + this.frame = frame; + } + + public void connect(String userName, String serverName, int port) throws RemoteException, NotBoundException { + if (isConnected()) { + disconnect(); + } + this.userName = userName; + this.client = new ClientImpl(frame, userName); + System.setSecurityManager(null); + Registry reg = LocateRegistry.getRegistry(serverName, port); + this.server = (Server) reg.lookup(Config.remoteServer); + try { + sessionId = server.registerClient(client); + playerTypes = server.getPlayerTypes(); + gameTypes = server.getGameTypes(); + logger.info("Connected to RMI server at " + serverName + ":" + port); + frame.enableButtons(); + } catch (MageException ex) { + Logger.getLogger(Session.class.getName()).log(Level.SEVERE, null, ex); + } + } + + public void disconnect() { + + if (isConnected()) { + try { + server.deregisterClient(sessionId); + server = null; + logger.info("Disconnected ... "); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, "Error disconnecting ...", ex); + } catch (MageException ex) { + logger.log(Level.SEVERE, "Error disconnecting ...", ex); + } + } + } + + public boolean isConnected() { + return server != null; + } + + public String[] getPlayerTypes() { + return playerTypes; + } + + public String[] getGameTypes() { + return gameTypes; + } + + public UUID getMainRoomId() { + try { + return server.getMainRoomId(); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return null; + } + + public UUID getRoomChatId(UUID roomId) { + try { + return server.getRoomChatId(roomId); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return null; + } + + public UUID getTableChatId(UUID tableId) { + try { + return server.getTableChatId(tableId); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return null; + } + + public UUID getGameChatId(UUID gameId) { + try { + return server.getGameChatId(gameId); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return null; + } + + public TableView getTable(UUID roomId, UUID tableId) { + try { + return server.getTable(roomId, tableId); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return null; + } + + public boolean watchTable(UUID roomId, UUID tableId) { + try { + server.watchTable(sessionId, roomId, tableId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean replayTable(UUID roomId, UUID tableId) { + try { + server.replayTable(sessionId, roomId, tableId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean joinTable(UUID roomId, UUID tableId, int seat, String playerName, DeckCardLists deckList) { + try { + return server.joinTable(sessionId, roomId, tableId, seat, playerName, deckList); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public Collection getTables(UUID roomId) throws MageRemoteException { + try { + return server.getTables(roomId); + } catch (RemoteException ex) { + handleRemoteException(ex); + throw new MageRemoteException(); + } catch (MageException ex) { + handleMageException(ex); + throw new MageRemoteException(); + } + } + + public boolean sendPlayerUUID(UUID gameId, UUID data) { + try { + server.sendPlayerUUID(gameId, sessionId, data); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean sendPlayerBoolean(UUID gameId, boolean data) { + try { + server.sendPlayerBoolean(gameId, sessionId, data); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean sendPlayerInteger(UUID gameId, int data) { + try { + server.sendPlayerInteger(gameId, sessionId, data); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean sendPlayerString(UUID gameId, String data) { + try { + server.sendPlayerString(gameId, sessionId, data); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean joinChat(UUID chatId, ChatClient client) { + try { + server.joinChat(chatId, client); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean leaveChat(UUID chatId, UUID clientId) { + try { + server.leaveChat(chatId, clientId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean sendChatMessage(UUID chatId, String message) { + try { + server.sendChatMessage(chatId, userName, message); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean joinGame(UUID gameId, GameClient gameClient) { + try { + server.joinGame(gameId, sessionId, gameClient); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean watchGame(UUID gameId, GameClient gameClient) { + try { + server.watchGame(gameId, sessionId, gameClient); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean replayGame(UUID gameId, GameReplayClient replayClient) { + try { + server.replayGame(gameId, sessionId, replayClient); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public TableView createTable(UUID roomId, String gameType, Constants.DeckType deckType, List playerTypes) { + try { + return server.createTable(sessionId, roomId, gameType, deckType, playerTypes); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return null; + } + + public boolean isTableOwner(UUID roomId, UUID tableId) { + try { + return server.isTableOwner(sessionId, roomId, tableId); + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean removeTable(UUID roomId, UUID tableId) { + try { + server.removeTable(sessionId, roomId, tableId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean leaveTable(UUID roomId, UUID tableId) { + try { + server.leaveTable(sessionId, roomId, tableId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean startGame(UUID roomId, UUID tableId) { + try { + server.startGame(sessionId, roomId, tableId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean concedeGame(UUID gameId) { + try { + server.concedeGame(gameId, sessionId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean stopWatching(UUID gameId, UUID gameClientId) { + try { + server.stopWatching(gameId, gameClientId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean stopReplay() { + try { + server.stopReplay(sessionId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean nextPlay() { + try { + server.nextPlay(sessionId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean previousPlay() { + try { + server.previousPlay(sessionId); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + public boolean cheat(UUID gameId, DeckCardLists deckList) { + try { + server.cheat(gameId, sessionId, deckList); + return true; + } catch (RemoteException ex) { + handleRemoteException(ex); + } catch (MageException ex) { + handleMageException(ex); + } + return false; + } + + private void handleRemoteException(RemoteException ex) { + server = null; + logger.log(Level.SEVERE, "Connection to server lost", ex); + JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Connection to server lost.", "Error", JOptionPane.ERROR_MESSAGE); + frame.disableButtons(); + } + + private void handleMageException(MageException ex) { + logger.log(Level.SEVERE, "Server error", ex); + JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Critical server error. Disconnecting", "Error", JOptionPane.ERROR_MESSAGE); + disconnect(); + frame.disableButtons(); + } + + public String getUserName() { + return userName; + } + +} \ No newline at end of file diff --git a/Mage.Client/src/mage/client/util/ButtonColumn.java b/Mage.Client/src/mage/client/util/ButtonColumn.java new file mode 100644 index 00000000000..fa414eb93a2 --- /dev/null +++ b/Mage.Client/src/mage/client/util/ButtonColumn.java @@ -0,0 +1,132 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import javax.swing.AbstractCellEditor; +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JTable; +import javax.swing.UIManager; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumnModel; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener, MouseListener { + + private JTable table; + private Action action; + private JButton renderButton; + private JButton editButton; + private String text; + private boolean isButtonColumnEditor; + + public ButtonColumn(JTable table, Action action, int column) { + super(); + this.table = table; + this.action = action; + renderButton = new JButton(); + + editButton = new JButton(); + editButton.setFocusPainted(false); + editButton.addActionListener(this); + + TableColumnModel columnModel = table.getColumnModel(); + columnModel.getColumn(column).setCellRenderer(this); + columnModel.getColumn(column).setCellEditor(this); + table.addMouseListener(this); + } + + public Object getCellEditorValue() { + return text; + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (hasFocus) + { + renderButton.setForeground(table.getForeground()); + renderButton.setBackground(UIManager.getColor("Button.background")); + } + else if (isSelected) + { + renderButton.setForeground(table.getSelectionForeground()); + renderButton.setBackground(table.getSelectionBackground()); + } + else + { + renderButton.setForeground(table.getForeground()); + renderButton.setBackground(UIManager.getColor("Button.background")); + } + + renderButton.setText( (value == null) ? "" : value.toString() ); + return renderButton; + } + + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + text = (value == null) ? "" : value.toString(); + editButton.setText( text ); + return editButton; + } + + public void actionPerformed(ActionEvent e) { + int row = table.convertRowIndexToModel( table.getEditingRow() ); + fireEditingStopped(); + ActionEvent event = new ActionEvent(table, ActionEvent.ACTION_PERFORMED, "" + row); + action.actionPerformed(event); + + } + + public void mousePressed(MouseEvent arg0) { + if (table.isEditing() && table.getCellEditor() == this) + isButtonColumnEditor = true; + } + + public void mouseReleased(MouseEvent arg0) { + if (isButtonColumnEditor && table.isEditing()) + table.getCellEditor().stopCellEditing(); + + isButtonColumnEditor = false; + } + + public void mouseClicked(MouseEvent arg0) {} + + public void mouseEntered(MouseEvent arg0) {} + + public void mouseExited(MouseEvent arg0) {} + + +} diff --git a/Mage.Client/src/mage/client/util/Config.java b/Mage.Client/src/mage/client/util/Config.java new file mode 100644 index 00000000000..5c59065db32 --- /dev/null +++ b/Mage.Client/src/mage/client/util/Config.java @@ -0,0 +1,87 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Config { + + private final static Logger logger = Logging.getLogger(Config.class.getName()); + + public static final String remoteServer; + public static final String serverName; + public static final int port; + public static final String cardsResourcePath; + public static final String frameResourcePath; + public static final String powerboxResourcePath; + public static final String cardArtResourcePath; + public static final String symbolsResourcePath; + public static final String resourcePath; + public static final boolean useResource; + + static { + Properties p = new Properties(); + try { + p.load(new FileInputStream(new File("config/config.properties"))); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + serverName = p.getProperty("server-name"); + port = Integer.parseInt(p.getProperty("port")); + remoteServer = p.getProperty("remote-server"); + cardsResourcePath = p.getProperty("cards-resource-path"); + resourcePath = p.getProperty("resource-path"); + File test = new File(cardsResourcePath); + if (test.isDirectory()) { + useResource = false; + frameResourcePath = cardsResourcePath + "Frame\\"; + powerboxResourcePath = cardsResourcePath + "PowerBox\\"; + cardArtResourcePath = cardsResourcePath + "Pics\\"; + symbolsResourcePath = p.getProperty("symbols-resource-path"); + } + else { + useResource = true; + frameResourcePath = resourcePath + "cards/frame/"; + powerboxResourcePath = resourcePath + "cards/powerbox/"; + cardArtResourcePath = resourcePath + "cards/art/"; + symbolsResourcePath = resourcePath + "symbols/"; + } + } + +} diff --git a/Mage.Client/src/mage/client/util/Constants.java b/Mage.Client/src/mage/client/util/Constants.java new file mode 100644 index 00000000000..2d32aab0f36 --- /dev/null +++ b/Mage.Client/src/mage/client/util/Constants.java @@ -0,0 +1,88 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public final class Constants { + private Constants() { + throw new AssertionError(); + } + + public static final int FRAME_MAX_HEIGHT = 367; + public static final int FRAME_MAX_WIDTH = 256; + public static final int ART_MAX_HEIGHT = 168; + public static final int ART_MAX_WIDTH = 227; + public static final int SYMBOL_MAX_HEIGHT = 28; + public static final int SYMBOL_MAX_WIDTH = 28; + public static final int SYMBOL_MAX_XOFFSET = 27; + public static final int SYMBOL_MAX_YOFFSET = 15; + public static final int SYMBOL_MAX_SPACE = 28; + public static final int CONTENT_MAX_XOFFSET = 15; + public static final int ART_MAX_YOFFSET = 37; + public static final int NAME_MAX_YOFFSET = 27; + public static final int TYPE_MAX_YOFFSET = 223; + public static final int TEXT_MAX_YOFFSET = 232; + public static final int TEXT_MAX_WIDTH = 227; + public static final int TEXT_MAX_HEIGHT = 105; + public static final int NAME_FONT_MAX_SIZE = 13; + public static final int TEXT_FONT_MAX_SIZE = 11; + public static final int PARAGRAPH_MAX_SPACING = 4; + public static final int POWBOX_MAX_TOP = 336; + public static final int POWBOX_MAX_LEFT = 202; + public static final int DAMAGE_MAX_LEFT = 180; + + public static final double SCALE_FACTOR = 0.5; + + public static final int FRAME_HEIGHT = (int)(FRAME_MAX_HEIGHT * SCALE_FACTOR); + public static final int FRAME_WIDTH = (int)(FRAME_MAX_WIDTH * SCALE_FACTOR); + public static final int ART_HEIGHT = (int)(ART_MAX_HEIGHT * SCALE_FACTOR); + public static final int ART_WIDTH = (int)(ART_MAX_WIDTH * SCALE_FACTOR); + public static final int SYMBOL_HEIGHT = (int)(SYMBOL_MAX_HEIGHT * SCALE_FACTOR); + public static final int SYMBOL_WIDTH = (int)(SYMBOL_MAX_WIDTH * SCALE_FACTOR); + public static final int SYMBOL_XOFFSET = (int)(SYMBOL_MAX_XOFFSET * SCALE_FACTOR); + public static final int SYMBOL_YOFFSET = (int)(SYMBOL_MAX_YOFFSET * SCALE_FACTOR); + public static final int SYMBOL_SPACE = (int)(SYMBOL_MAX_SPACE * SCALE_FACTOR); + public static final int CONTENT_XOFFSET = (int)(CONTENT_MAX_XOFFSET * SCALE_FACTOR); + public static final int ART_YOFFSET = (int)(ART_MAX_YOFFSET * SCALE_FACTOR); + public static final int NAME_YOFFSET = (int)(NAME_MAX_YOFFSET * SCALE_FACTOR); + public static final int TYPE_YOFFSET = (int)(TYPE_MAX_YOFFSET * SCALE_FACTOR); + public static final int TEXT_YOFFSET = (int)(TEXT_MAX_YOFFSET * SCALE_FACTOR); + public static final int TEXT_WIDTH = (int)(TEXT_MAX_WIDTH * SCALE_FACTOR); + public static final int TEXT_HEIGHT = (int)(TEXT_MAX_HEIGHT * SCALE_FACTOR); + public static final int POWBOX_TOP = (int)(POWBOX_MAX_TOP * SCALE_FACTOR); + public static final int POWBOX_LEFT = (int)(POWBOX_MAX_LEFT * SCALE_FACTOR); + public static final int DAMAGE_LEFT = (int)(DAMAGE_MAX_LEFT * SCALE_FACTOR); + public static final int NAME_FONT_SIZE = Math.max(9, (int)(NAME_FONT_MAX_SIZE * SCALE_FACTOR)); + public static final int TEXT_FONT_SIZE = Math.max(9, (int)(TEXT_FONT_MAX_SIZE * SCALE_FACTOR)); + public static final int PARAGRAPH_SPACING = (int)(PARAGRAPH_MAX_SPACING * SCALE_FACTOR); + +} diff --git a/Mage.Client/src/mage/client/util/Event.java b/Mage.Client/src/mage/client/util/Event.java new file mode 100644 index 00000000000..22bb0ea4830 --- /dev/null +++ b/Mage.Client/src/mage/client/util/Event.java @@ -0,0 +1,53 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.io.Serializable; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Event implements Serializable { + private Object source; + private String eventName; + + public Event(Object source, String eventName) { + this.source = source; + this.eventName = eventName; + } + + public Object getSource() { + return source; + } + + public String getEventName() { + return eventName; + } +} diff --git a/Mage.Client/src/mage/client/util/EventDispatcher.java b/Mage.Client/src/mage/client/util/EventDispatcher.java new file mode 100644 index 00000000000..e4a3de92076 --- /dev/null +++ b/Mage.Client/src/mage/client/util/EventDispatcher.java @@ -0,0 +1,62 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.io.Serializable; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public abstract class EventDispatcher implements Serializable { + + private List> listeners = new CopyOnWriteArrayList>(); + + public void addListener(Listener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + public void removeListener(Listener listener) { + listeners.remove(listener); + } + + public void fireEvent(E event) { + for (Listener listener : listeners) { + listener.event(event); + } + } + + public void clearListeners() { + listeners.clear(); + } +} diff --git a/Mage.Client/src/mage/client/util/EventSource.java b/Mage.Client/src/mage/client/util/EventSource.java new file mode 100644 index 00000000000..6cc851fd48b --- /dev/null +++ b/Mage.Client/src/mage/client/util/EventSource.java @@ -0,0 +1,42 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.io.Serializable; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public interface EventSource extends Serializable { + + void addListener(Listener listener); + void clearListeners(); + +} diff --git a/Mage.Client/src/mage/client/util/Frames.java b/Mage.Client/src/mage/client/util/Frames.java new file mode 100644 index 00000000000..f37b524a878 --- /dev/null +++ b/Mage.Client/src/mage/client/util/Frames.java @@ -0,0 +1,60 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.awt.Image; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Frames { + + public static Image Black = ImageHelper.loadImage(Config.frameResourcePath + "8 black.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Blue = ImageHelper.loadImage(Config.frameResourcePath + "8 blue.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Gold = ImageHelper.loadImage(Config.frameResourcePath + "8 gold.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Green = ImageHelper.loadImage(Config.frameResourcePath + "8 green.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Grey = ImageHelper.loadImage(Config.frameResourcePath + "8 grey.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Red = ImageHelper.loadImage(Config.frameResourcePath + "8 red.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image White = ImageHelper.loadImage(Config.frameResourcePath + "8 white.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + + public static Image Forest = ImageHelper.loadImage(Config.frameResourcePath + "8 land mana green.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Island = ImageHelper.loadImage(Config.frameResourcePath + "8 land mana blue.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Mountain = ImageHelper.loadImage(Config.frameResourcePath + "8 land mana red.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Plains = ImageHelper.loadImage(Config.frameResourcePath + "8 land mana white.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + public static Image Swamp = ImageHelper.loadImage(Config.frameResourcePath + "8 land mana black.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + + public static Image Effect = ImageHelper.loadImage(Config.frameResourcePath + "Effects\\effect0.png", FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + + public static Image PowBoxLeft = ImageHelper.loadImage(Config.powerboxResourcePath + "graphic_card_powerbox_a_left.png"); + public static Image PowBoxMid = ImageHelper.loadImage(Config.powerboxResourcePath + "graphic_card_powerbox_a_middle.png"); + public static Image PowBoxRight = ImageHelper.loadImage(Config.powerboxResourcePath + "graphic_card_powerbox_a_right.png"); + +} diff --git a/Mage.Client/src/mage/client/util/ImageHelper.java b/Mage.Client/src/mage/client/util/ImageHelper.java new file mode 100644 index 00000000000..9580045d648 --- /dev/null +++ b/Mage.Client/src/mage/client/util/ImageHelper.java @@ -0,0 +1,200 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.awt.image.MemoryImageSource; +import java.awt.image.PixelGrabber; +import java.io.File; +import java.util.HashMap; +import java.util.List; +import javax.imageio.ImageIO; +import mage.Constants.CardType; +import mage.view.CardView; +import mage.view.StackAbilityView; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ImageHelper { + protected static HashMap images = new HashMap(); + protected static HashMap backgrounds = new HashMap(); + + public static Image loadImage(String ref, int width, int height) { + Image image = loadImage(ref); + if (image != null) + return ScaleImage(image, width, height); + return null; + } + + public static Image loadImage(String ref) { + if (!images.containsKey(ref)) { + try { + if (Config.useResource) + images.put(ref, ImageIO.read(ImageHelper.class.getResourceAsStream(ref))); + else + images.put(ref, ImageIO.read(new File(ref))); + } catch (Exception e) { + return null; + } + } + return images.get(ref); + } + + public static BufferedImage getBackground(CardView card) { + // card background should be the same for all cards with the same name/art + String cardName = card.getName()+card.getArt(); + if (backgrounds.containsKey(cardName)) { + return backgrounds.get(cardName); + } + + BufferedImage background = new BufferedImage(FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT, BufferedImage.TYPE_INT_RGB); + Graphics2D g = (Graphics2D) background.getGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(Color.WHITE); + g.fillRect(0, 0, FRAME_MAX_WIDTH, FRAME_MAX_HEIGHT); + g.drawImage(getFrame(card), 0, 0, Color.WHITE, null); + if (!card.getArt().equals("")) { + Image art = loadImage(Config.cardArtResourcePath + card.getArt(), ART_MAX_WIDTH, ART_MAX_HEIGHT); + g.drawImage(art, CONTENT_MAX_XOFFSET, ART_MAX_YOFFSET, null); + } + + if (card.getCardTypes().contains(CardType.CREATURE) || card.getCardTypes().contains(CardType.PLANESWALKER)) { + g.drawImage(Frames.PowBoxLeft, POWBOX_MAX_LEFT, POWBOX_MAX_TOP, null); + g.drawImage(Frames.PowBoxMid, POWBOX_MAX_LEFT + 7, POWBOX_MAX_TOP, null); + g.drawImage(Frames.PowBoxRight, POWBOX_MAX_LEFT + 38, POWBOX_MAX_TOP, null); + } + + g.dispose(); + + backgrounds.put(cardName, background); + return background; + } + + protected static Image getFrame(CardView card) { + if (card instanceof StackAbilityView) { + return Frames.Effect; + } + + if (card.getCardTypes().contains(CardType.LAND)) { + return getLandFrame(card); + } + else { + if (card.getColor().isColorless()) { + return Frames.Grey; + } else if (card.getColor().isMulticolored()) { + return Frames.Gold; + } else { + if (card.getColor().isBlack()) { + return Frames.Black; + } else if (card.getColor().isBlue()) { + return Frames.Blue; + } else if (card.getColor().isRed()) { + return Frames.Red; + } else if (card.getColor().isGreen()) { + return Frames.Green; + } else if (card.getColor().isWhite()) { + return Frames.White; + } + } + } + return Frames.Grey; + } + + protected static Image getLandFrame(CardView card) { + if (card.getSuperTypes().contains("Basic")) { + if (card.getSubTypes().contains("Forest")) { + return Frames.Forest; + } + else if (card.getSubTypes().contains("Island")) { + return Frames.Island; + } + else if (card.getSubTypes().contains("Mountain")) { + return Frames.Mountain; + } + else if (card.getSubTypes().contains("Plains")) { + return Frames.Plains; + } + else if (card.getSubTypes().contains("Swamp")) { + return Frames.Swamp; + } + } + return Frames.Grey; + } + + public static Image ScaleImage(Image image, int width, int height) { + return image.getScaledInstance(width, height, Image.SCALE_SMOOTH); + } + + public static MemoryImageSource rotate(Image image) { + int buffer[] = new int[FRAME_WIDTH * FRAME_HEIGHT]; + int rotate[] = new int[FRAME_HEIGHT * FRAME_WIDTH]; + PixelGrabber grabber = new PixelGrabber(image, 0, 0, FRAME_WIDTH, FRAME_HEIGHT, buffer, 0, FRAME_WIDTH); + try { + grabber.grabPixels(); + } + catch(InterruptedException e) { + e.printStackTrace(); + } + for(int y = 0; y < FRAME_HEIGHT; y++) { + for(int x = 0; x < FRAME_WIDTH; x++) { + rotate[((FRAME_WIDTH - x - 1) *FRAME_HEIGHT)+y] = buffer[(y*FRAME_WIDTH)+x]; + } + } + + return new MemoryImageSource(FRAME_HEIGHT, FRAME_WIDTH, rotate, 0, FRAME_HEIGHT); + + } + + public static void DrawCosts(List costs, Graphics2D g, int xOffset, int yOffset, ImageObserver o) { + if (costs.size() > 0) { + int costLeft = xOffset; + for (int i = costs.size() - 1; i >= 0; i--) { + String symbol = costs.get(i); + Image image = Symbols.getSymbol(symbol); + if (image != null) { + g.drawImage(image, costLeft, yOffset, o); + costLeft -= SYMBOL_SPACE; + } + else { + g.drawString(symbol, costLeft, yOffset + SYMBOL_SPACE); + costLeft -= SYMBOL_SPACE + 4; + } + } + } + } + +} diff --git a/Mage.Client/src/mage/client/util/Listener.java b/Mage.Client/src/mage/client/util/Listener.java new file mode 100644 index 00000000000..9f9cd5613ef --- /dev/null +++ b/Mage.Client/src/mage/client/util/Listener.java @@ -0,0 +1,39 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.io.Serializable; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public interface Listener extends Serializable { + void event(E event); +} diff --git a/Mage.Client/src/mage/client/util/Symbols.java b/Mage.Client/src/mage/client/util/Symbols.java new file mode 100644 index 00000000000..79024dfb9e2 --- /dev/null +++ b/Mage.Client/src/mage/client/util/Symbols.java @@ -0,0 +1,96 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.client.util; + +import java.awt.Image; +import java.util.HashMap; +import java.util.Map; +import static mage.client.util.Constants.*; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Symbols { + + public static Map symbols = new HashMap(); + + static { + symbols.put("{B}", ImageHelper.loadImage(Config.symbolsResourcePath + "mana_black.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{U}", ImageHelper.loadImage(Config.symbolsResourcePath + "mana_blue.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{G}", ImageHelper.loadImage(Config.symbolsResourcePath + "mana_green.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{R}", ImageHelper.loadImage(Config.symbolsResourcePath + "mana_red.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{W}", ImageHelper.loadImage(Config.symbolsResourcePath + "mana_white.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + + symbols.put("{0}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_0.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{1}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_1.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{2}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_2.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{3}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_3.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{4}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_4.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{5}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_5.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{6}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_6.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{7}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_7.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{8}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_8.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{9}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_9.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{10}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_10.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{11}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_11.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{12}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_12.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{13}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_13.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{14}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_14.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{15}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_15.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{16}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_16.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{X}", ImageHelper.loadImage(Config.symbolsResourcePath + "colorless_x.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + + symbols.put("{B/G}", ImageHelper.loadImage(Config.symbolsResourcePath + "black_green.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{B/R}", ImageHelper.loadImage(Config.symbolsResourcePath + "black_red.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{U/B}", ImageHelper.loadImage(Config.symbolsResourcePath + "blue_black.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{U/R}", ImageHelper.loadImage(Config.symbolsResourcePath + "blue_red.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{G/B}", ImageHelper.loadImage(Config.symbolsResourcePath + "green_blue.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{G/W}", ImageHelper.loadImage(Config.symbolsResourcePath + "green_white.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{R/G}", ImageHelper.loadImage(Config.symbolsResourcePath + "red_green.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{R/W}", ImageHelper.loadImage(Config.symbolsResourcePath + "red_white.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{W/B}", ImageHelper.loadImage(Config.symbolsResourcePath + "white_black.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{W/U}", ImageHelper.loadImage(Config.symbolsResourcePath + "white_blue.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + + symbols.put("{2/B}", ImageHelper.loadImage(Config.symbolsResourcePath + "two_black.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{2/U}", ImageHelper.loadImage(Config.symbolsResourcePath + "two_blue.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{2/G}", ImageHelper.loadImage(Config.symbolsResourcePath + "two_green.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{2/R}", ImageHelper.loadImage(Config.symbolsResourcePath + "two_red.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + symbols.put("{2/W}", ImageHelper.loadImage(Config.symbolsResourcePath + "two_white.png", SYMBOL_WIDTH, SYMBOL_HEIGHT)); + + } + + public static Image getSymbol(String symbol) { + + if (symbols.containsKey(symbol)) + return(symbols.get(symbol)); + return null; + + } +} diff --git a/Mage.Client/src/mage/client/util/resources/config.properties b/Mage.Client/src/mage/client/util/resources/config.properties new file mode 100644 index 00000000000..7c8e6bc7d45 --- /dev/null +++ b/Mage.Client/src/mage/client/util/resources/config.properties @@ -0,0 +1,6 @@ +server-name=localhost +port=17171 +remote-server=mage-server +cards-resource-path=resources/images/cards/ +symbols-resource-path=resources/images/symbols/ +resource-path=resources/images/ \ No newline at end of file diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 black.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 black.png new file mode 100644 index 0000000000000000000000000000000000000000..e66069eef5b2f2c8a3c0809ed75c59d741f584f3 GIT binary patch literal 26072 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

GI;%)lAJ#F=D9ef|**>{u%^I~6guxnyvG^X| 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 Ix=qA?05hyHfdBvi literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 gold.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 gold.png new file mode 100644 index 0000000000000000000000000000000000000000..2a681b37a93414a5da0f43ae358e4b25801ecf83 GIT binary patch literal 26658 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 literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 green.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 green.png new file mode 100644 index 0000000000000000000000000000000000000000..a830ccfff6ff2fa288763d3bc01053dbc581908f GIT binary patch literal 24540 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%0DH29h<=JbI z?#A)rH#UT~_W3MRlP2bPh%x_;;^q4dtD<_@#Y$$uru*fI+TGoQnA@nQlwyIXR;Ab=bIvVYc9@i&{{Ax&ydcBrsbj4di{nss0``Dgy?@Oy^`9oM**Y~N@K4_UId)Dwj!fhMRg7P_x-l6@TT9oo#BK%@T zWtu7{?HUDl4jwx8Yue$IUsOY#y6q=ES4s3|P#b=n7aur^sJ>#ZICJ0%I`mhdgSX6H z=0!%%z{rXOf4{u<27LD!95n*@D*5p6@kwNLN}~hI81c2N$h^Gn0WI2QkVT^j+bg6S zY{91jzviYmHs-BFDOrPerl7!Oa}p=y;ZCFY>)@=B8oshA&jS%x&xyej_V@@FZn(2p z9@h;-g_2M|RM2@{{mcy{VA~ZUoj5#G#Bh&HcSs^I1QH}q!)IHSuy&?8bmgd2O*8jB z_*o@?@-4XL;h+f1-RVPV`Q=~xO{0ZN8(cZ;@_y$7p*DDTyd(&}#dFI{uy=SE7`>0D Msivn|s%#nZKdZWjjsO4v literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 grey.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 grey.png new file mode 100644 index 0000000000000000000000000000000000000000..bb4a0b49de0d431f83511c1682074aa093a00ab5 GIT binary patch literal 20449 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�WvBoRuHagWAVRUZ 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 XTK=dB0!Vd%`r;RgThg&?69tqqytWv=In0 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 literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana blue.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana blue.png new file mode 100644 index 0000000000000000000000000000000000000000..05e017ac609a3a99044b805391ce54ed28bffc27 GIT binary patch literal 31175 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 G;C}$pH%%u1 literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana red.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana red.png new file mode 100644 index 0000000000000000000000000000000000000000..5f6ca1ebad151dab693f1505110cb77fd4db3824 GIT binary patch literal 31169 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�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î>Yit>G}uRM~@Nl7mwsO3z?D*ah2G> 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 NNlRZdPu=>~e*?<`X1o9Z literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana white.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 land mana white.png new file mode 100644 index 0000000000000000000000000000000000000000..05f79e9d57a793620d37e229ca4ef312ae179ce2 GIT binary patch literal 31253 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 literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 white.png b/Mage.Client/src/mage/client/util/resources/images/cards/frame/8 white.png new file mode 100644 index 0000000000000000000000000000000000000000..65fb0651b0c2849027a1240d6fa3f6e8e2fafd8b GIT binary patch literal 25700 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 JF6*2UngIN0qp$z~ literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/cards/powerbox/graphic_card_powerbox_a_middle.png b/Mage.Client/src/mage/client/util/resources/images/cards/powerbox/graphic_card_powerbox_a_middle.png new file mode 100644 index 0000000000000000000000000000000000000000..13ec5b46dece8243f600187476600fc1ed8144d2 GIT binary patch literal 1299 zcmV+u1?>8XP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0yi>|?-D)$00fgsL_t(Y$HkUGj^xMv-M)>NzLl>wyMb4RmvaIGUK@k% z%B)OD5hT3`bB|0n_e!B4sb_!sccpHTa6@}K{H(m1SAzy(1!AuUFiIZQHrsZm22|fr#M4skQR@_QtX-?EB8+;{z=P zE5#5Ih@|(9yQ5ktW@N^cM+NtRV5lmY$^CvqL{Ke^F^CAZZ6iEb*Of6G9|Nm4*NWir z_+Wc(hzcTLA|N6JL3ompAc=^ODP#r_fqOs`mSvf0kgV$k5kW*4V_?Pb>ZmHU3bj`5 z_ZwD>%p^R{!c!SLj-3cc5K0lW+9{huf@+xs7=$|!!M<-~g4tkM7Pf7pwMGU+Rsb>~ zGq_x?tm}emAu>@d0E|Ac))qk6bHl?ar{rUF60o9xFfxeEd4InF;O?yJLhp&W`+OPB=;IFwYegj4wvEiBwML;}R#}&o z-UrX;6Eg$gI0mh?xvMd#wUU{rD!q@>oRFEHb?k>LMFdf$6yrE{#x_5wwNBT%(^{K_ zM`zzQ_TxCck?i|Ut&NwLE2>JX6;Y+t!tMUx<>du;r<7^XwKXgvF*8(+YD#Mh?t!Wz zBJ_R$oX^V954LTa1zH0V6+uJc4|x5D^qDr&3Df1X8#&NQQU5>V@OjDOymSYqn*j)^4({G7%>6)@23Y{r$$aZI~&lii!Y9L;`uj1Vr>xJp{ggdna8OzG1d7hSSH~ zTzF7hojJEm$eF>Sg>_v)gfW~k`U!_1V*6tp%50|E^guB~WO6;+&mj~iH#$DfIUz!1 zkeOH?ot6uk2|#O=%jLrTeh0v;QmY{{Y4)Q*QJt?cu&#|-=c1*QGcvQ$Vv~gT`yKZ{P-?9l{h-yA zL_Uw>hx|5tr(lRQdhe71B8Dmuv&g>hG^xDQ%F#Q=aZrk4R`D^|kAt_jS40XKdX8pg zS*~Pm6f;!IWI_g+J`Mc!%U7<~%O^@Rr)hi)BK+L(!sT*hxSv^_qcI{F?wA!sl;`tF z?{T7fp|zC^@Zq=*;`}$59&rTt75L>R{KNg-fPVvj{Rzc?`#_9Be!3HFcw}g5CDaPU;cPEB*=VV?2Ic!PZ?k)`f zL2$v|<&%LToCO|{#S9GG!XV7ZFl&wkP>{XE)7O>#7BerCiGpXf!B(Itx}GkMAsXjX zCmH%3b`WsA-*Y{C`CGsQrj$(3D{16VQHfeoq9WS2XSZ{r_Kmb9 zQ{Aep|JR>g$MD@`tI1~3xk3*(H5y`X%j;VvFs^CTEV#}mBdQmFf7`ZuHIg3~&NOz; zTqr;P{`nb+CmE(4@Lb)rOyp#3pT5oP?{D{fWp!YjbNZx7a)h6YWr!$8i`AC}VORML zT{oRkT=m!Uy?2mTMf`-MSBC|Z+7B~6FPe2g_Qf1$mkvcGqX|bHTvj^w^4U7`ESWM( zIN3foa!LnBn%ky*E0vrgr>)R1Yf-$?~4k4N~7u%aQ+<)I;SZHWB zn`yGL%>4OrmG4i?+Iyc*zM3s&d;Lqn88ao*+OiM&rYC*fu2_-zyLF~*Df3^Zi8@V3 U3q@VCfMLnt>FVdQ&MBb@0C5zgNB{r; literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/black_green.png b/Mage.Client/src/mage/client/util/resources/images/symbols/black_green.png new file mode 100644 index 0000000000000000000000000000000000000000..97eca8af0479802dba7c9ea6b3df29ae0d676cc3 GIT binary patch literal 983 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 N002ovPDHLkV1mb+aa8~S literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_1.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_1.png new file mode 100644 index 0000000000000000000000000000000000000000..9121d993140b370a8f238718199590b148af03ff GIT binary patch literal 952 zcmV;p14sOcP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0|hvph{a|A00THlL_t(o!^M|NOcPNQKu@b+HwG;j1ffEIf?%njXrp5Nkhmq$xHAz$ zjETC@of~waE8@n5A0&WEq7qT#PD3gfsukKg0UDt-hA3LWwp5}Cl#H8>DM+EkI^5mN zeKYsG`|i6RSY}Zqy3lR6^Tr$%Tgwhs@3+=V&nsheM-qwlirohiOE8N0 zFIe#=BV}7k>YjJn9smQ%m?TppSN5yiR-R)t=xSpu zhlYI(QVdkeT?4d*1sb4A0x-!9V9@ITDkT8D+yI)q4FDzyAX{z#wR$apUb)QeK(;cb zp35qMKyX$j^vVq|^64{xUjh*11{n7G0K5`_LvDcnK@Wf+0d!4-!y|GTAM*O>a|r+r zWi*|RPESYLZZ`d#PKy58EY5%I9~3b`+jcCki_$Ti07R) zfDT|(8S{gIU@+ADzjy!W$uoQ(K01Mie>J6UyG&Zr<}hjJLMk=jyfVh@yB3 zxc*m5X0}*Gqh5Qo&-KoeYUAyXpVHcPA5jz=fE#hU;>MP{lbZaz?(c!%E?r?kcB*!M zyX79^-vc**%fMt@002j?)8F0m`iV-lsw^!nO}j2Db4i9h?}xbA)Iw8h8$W;kYKR*D zy5L+ONhA`P?0NI{ZaDly@oj9(s8Xp`XR6f+-}8qZPibtv!z=q6CvXY461($chtm?H zL04N^Ty$7lSfDZJb!hT7NF|j(Ajrt4&kTEg^bdOIa|zNt?}$eGz&}sN(vXwPgbXY? aA^!#gr6Cx)Yc8Mw0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}BK!WR!0J00fCiL_t(o!^M|tOp|96$A85^-$9fKE+{D1wt&S-mdI>~fJCOu8F$fb zaf{J8!=fM9gvY8q-*62ck6d(!E016<)uI>R0fF7s?suHzn zU0wmuSff(|n}JvCj;EDDi=|_1Oe|Rt9F&)+O>3SNfW{h~49Eg@0?*Bc-k$rt-R6OT z+&Go;P@*=?He&#dHM)hsUSN+m?)heY9`y{>z*ZjKx0hky^g6=Zdg`%z$#H)yxnY{+D;A?EAr8*Q;Xklp$Fu5K~|o83kG`@8m$s7;&J zVQF~6vWVo<(VS1vcA%2@oHvV)-)lPCz}ufW62Zbto*1i6UKH-4y*) zN?FA(0KE6^Hn#x2$oZOYa=)jyuOCqq5k-;SzJ98%)-W_QO!CU430pxB=H6;*e%Nm^ zUwX>EmNL1>tXQ>X#&q9qZl$=i47uEo1N%N^OCfb1iYPN&r-f z7!u;+Hnp`IbEGRs^5nkHUAP3mj;(L8aeXEM0saI8`1A6H7uojqn*datzv#3lIw~?8 zNRa?&rlX4m!7i9Zqwwnu2jSTBuM}io-okaJzn6#LR}LmG;|>V z_d1=6VEE!N0F4A7#1jD4VJiSn3xbO-z~3K$q2Xbt^`M~n016+k_Vy|A-Z2HIkPsh- zem-mQ4;Vk?$jC!ic1A{=n2^L|GCP%GgNMz=DHfdKqjT!`=(yJj&?5oRdjep2f*OF| zbX6|8->a{Vr&+>Mr}cJ&5x^h;sPzQE`gIuq@wA;Mk zw5O@16+kal!m2@wr6X|Oyl}~2s@m_k=2#yz32I*3_!6b%l^i_$najS{U){(ub^OHt zHiMD620cKnkNv}4V`E~8CoCM?zncU5b`ck=M3Bo7v|tJ1;3aOJPwlHk&O6 zIOg_Me7xY~Q23I?)%_-Oa!gcYh__DuUBM~(`c21xY+%SO0D#(?^*zsSbAy9|X5_fd zVC3|fvmDPq!PT1U^}rF}bH|fE?r^GBDP!JAh>zP89Tgd_RKyUzI817(m`r9m?sd{` zFw)f0N?n6q%JVb!Xm9p-I+ps*<4nlFv=j2bVM3;jxVV$M00000NkvXXu0mjf5Ib)c literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_11.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_11.png new file mode 100644 index 0000000000000000000000000000000000000000..cb67a18c0dcb54c5d90d30ca7e906037d938358c GIT binary patch literal 961 zcmV;y13vtTP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}CJ!XK=m%00TiuL_t(o!^M|fNRwd{$A4SRc2njw%+$H>G;NJYYecr9pxdD6E~tno z3W`3iBciUnj>=4}gh;ZiyF!+R%c*k>bu_mU^P{D0x}?Aj*3J9IQm32Ed9GgG^M~_4 z|8t)6JO@_TB#8o@HtQy!5~u)-fDXtN+h`l2uVOM=5+-o&(zSWxKBc1_Y zl~{s`bl(9QwMq$8iV7Ix45Yu`iPS$Cyk4gTs1Oyz1Yh!$3!UeR73XqensF|FaI(($xOm{=Kkd2O^X$v2^f{eNYxh%PS!4W_Rn9w#`k&90X&=YB2uf0F1vdB+m{r;9R9ZU4=?5NHQQt|nPx*y_L2g-KY6%UQ%6mG z1HXR#t`dTOTW~KBEfR@Lw|8_t4uyV7zK@R^mX#DA(Wq5Qy-tg=AYZ&v2?T-+4UaJ3_0ik!rn|=_p7SQ5+xz}| jI~JFmWHw}A(GB?zn#40`kwgp#00000NkvXXu0mjfJUF*n literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_12.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_12.png new file mode 100644 index 0000000000000000000000000000000000000000..635a8fb7c73f876a965e1971d4cc55a27c2ad794 GIT binary patch literal 1240 zcmV;}1Sk86P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}C?a-U0Ri00dY`L_t(o!^M|>Ow@H4$6tqF=Mv3>hCkro;5d&TA(2uy7g46`pVCre zwPHq?wshL0IoFn&6#W=&Zmnq|6C^ej1C&)mqYI3S-zRa9aEImu#DhCH$@p<{{o#Gt z$#HVPQO`f$?|0Ah-TVDKpXbNtf&W=V?iy+}>ZL#e5D&xvav;F2?gsQgBTx;L$Ep%L zJwiaMQAYurftT&TlS;qEa(!gPTHx;|$&OVe>ZV0Nt5J)9ZNOF_ZaU%ZzGdt(_w^l9 zD#8!MsuFE(6VPhZi-9y?k0;K#wqAQNI#QYZ)Uz*ijn~a_0e%43>8V6px@2)^O^7SXk;pm4e0+RDEtcD&_N&*_0NxI|&91Wj-Q6Fcsj5M% zQM&{zzf{Rj7t3h4{0By35A){DBRVRAl;qc075DgF1{u^5{q~6mY!&h_q9c@>TH6en0)hCMo_XH!Blmp=2L*EQ!@aC~X%p?&{&KPpm4!%w1c5-z z1pQ#_Jyw-CEmFR|^Y1<9KkTFnmxlqw3uP#ujY(Hque}%El}|Y7q=Cx-Vgv#Ko(3Nr z9OCddNAdRd=AD#eC%r_n2te*N8=jAjj`C4@271F)_NDD2OcvtGG{DPYp5v(o^vM@r zQTnr*9otgbxc`$srgSnKeV59YbGz-rsfua zMv>5p`z;pD!UYSY?$-YJx!_K(5dLY^8+h;iy%>9XUh}g5+&MC0E%>i)!ezf!VC?B> z1j@&zp}(IbyRX0htw$CvTr`n~?s_+wv|MTBLYW$%5a{%B2%*kw?mIEt-hW?Qf}#Cd zJ#fb9MkEUf-qYCBTrpeVx%sCkC^`>t4A40dh*c%p6!Ordx`xXwo(3-{I!A8)DQq@d zCUDf{tvD+uZ$KIpSkY@TuMU%i1bE8x<2m2a(`z~kdBmhudTi;z#`FpWg{Ll&? zAD_@i{r#o|+;XLrZ?kjA&duk}oqsaz;5Q$*7YJgtS_dktYVs_W+oD@Wqe3he`}#>F zZUMLI4V)=FN7jjxT+&q410Mq!j-F3-IgL_;howYEC^v=5LZspHFrPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}KdilTL#G00f6gL_t(o!^M|-Y?DAOvF+F=!AN3^wKzHeg($2_lq@tkB&`-9<;cjk=3t&~{}PX)E;) zT5QJ(yL9pV^?m0#`JU%I=RNQHz3@K|$zT^6^}4A*I*UFb#MZl{*;s=f{r_<_odx|DTOLJ1vGHQn+ zXR4HnGDAgGM<5n4fbDC1)(?5OT&|E<+T(MR6f)UCQ52_y6yPHsw(U_-QTN3&pM5&% zy_Ij~1s?sFe$l=Km=X@#yMkfB+s6;;+M0!!$9qrfF!de zAhF=~cxY>Dr{M4rickIoz}s)V9#X)ISxcz-Eyp+l!^KiQ-c~lQ=U0 zS?n|bL{S`jxu*8-8#eoCzXR$0lg!+wo*R#$F6Kj zF6i0*?Jk~}mkL09gsg@umTi6ksUtn}qWt{>h*Gm5cO2y`I?>s6h3awhjruAz9IQ{FnAl%y0 z3ee#fU>dC>a5`@S@XzhrLGxG4767wffMKLWSxcAmL*Y>xo3G+>x#;Wb!%$JhN9#7+ zsfMYK1+A~Cs|PUoW1ytV>9md?H%@-PyB|2$zb=?9O?>{LWh`5=n8OG6F>UI9MfU9ZQaZ0+ zHvuJ*z;f*9>MDJB{P+o@c`fVzXkh*3tymhHHvtd-7gttat`9ePQSk}#3J&4*dba_) zL;e--&CTzY%VJA!*z8YgRLYoe?R;PE_gueW+YM|5x{5BY(|J>Jt+O*;6veU8Qt6hu){jN0f_(r002ovPDHLkV1nIySZ@FT literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_14.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_14.png new file mode 100644 index 0000000000000000000000000000000000000000..14421a7ac97fec6a78f493533d8a6d7a2af3dd24 GIT binary patch literal 1097 zcmV-P1h)H$P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}LE+Nt*ru00YTML_t(o!^M|fOq*pC$A4ujmJ5d~7{&(uZUtebSsdCJvCb`eJ2PUu zF>z*DG-}K?E~ar3S#+8(Z%oV_;$V|xjtn+6F=}Rog-ZEcM`;G_wlH8TuzrnwguY3= z>ATcIOItcT$$Rsj^E~H&{?9q*c@F%~B1zS7*k;`b)Bx3h5zqleQMDIv0}j9rbeYVS z>8t=4wplBHT3~0?@v;&Og(kvbp}nv`-fS{koEZTawpk^>USJQfB@=qRGqX4Sfxz)H zgTCHmwnS0}Fl@7K01g2AvvJP-gTsGTK3(?ab1%JmGhVkQf%AIc{cI)L#^Mc{zJZ|~ zYL&9b-aqJ#)#WTf`++F+Y0JXGLPDMS*{w!pY3WIsOjeu_K-6)@wCCpLCe`oQ_M-8< zy>GY19{rlQY(ESXXM^@gB!Wb;IK`w=sU{Sh&Gv>v4&wm;Kt+>-!}b#t+y{N=My(3In;0@p}zW=EyV`C zb~nJ<=)aoyCbRX0?HN&j|G@+H9sGp(yLS`X7<5`H%gc6+je8o!BdE?+$sPXkC~nU+ zR7yosJB?bU0BS@4#wGf}!!K3&>1-#z{`Nb0d3hW?(vZ|vuhRllivV;hjr_9H#aCZ{ z13>*pb!b$|r1pxEO#ns_K+#H^2ZBNBKK>Lz5O|~ZHD1}iZP_()`Fa3dPBzZ{;GqU? zd1t8FT*1B%-c4s|(b|~%T$w2Vo4p@^OP8HXR*%>VV)M!8^Z%z6yI1=qG%+~^;1wBg z054~{S)xi=DsoZA-5vn9$bfyd85kLL0XRekx`Lt5ME<&Uig@%(MU*V+RAkKUVPMDs zV9$weJRJ@T?W-02g}=L*ottw2T_OV%7RZ|e!Qfj@ zJ}`92m2Kzko#$z7J53}KX#|cXd=)pfoSIjZmUQ3t`JdOSRYlo~{QH(4nY-;f27C_8 zCj#vFpkh-!-?;+}g&yd-ofo&Tl213q%nFVZNug z?^GysM=~=zYmmugj~B@0DcAX#j`K8~ILSp@?;!9Q@I`Fo=?$E6JHi=g%KA)e7$tlL&9!5r83=BEMI`4>PyK}|Uu{h+UGa&=ZPRRcPZ6;v+;VX!k P00000NkvXXu0mjf+T;DO literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_15.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_15.png new file mode 100644 index 0000000000000000000000000000000000000000..90c66a0ad6ca7a9a0f39ea6ce62e6044d20cab53 GIT binary patch literal 1154 zcmV-|1bzF7P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}L*>p38m!00aU_L_t(o!^M|fOp|96$A3i%&CFne3*QC$B@9+OB8+Ak!lDZoyD`Ce zvFsxlH71%Y(_L*BXb4-JB>Tu*9E=G%5|t>r-OaE9hK}#rQP`kGhM+^Rg$fSahVH_4 zc?*`0^0J-F=bZQb|DXRk&v~8$|FcO}8)z~b5`h9B56}WCAkOEW0IYx+=m1)D`og=S z5HJ}HS-@Ukj}Lf7n{hfv-EL3A*4UUDoxac#5&@IZAOQ{m2Y{SVOHsVOPvWinYpPy#;SkY$gEh*;LY`?a0gBZv0a z2~)pmQMH!?31Z0Z^?H#=mX?@QDpfe04<*C5M+^Yr0^i4>7iPVlo<*1=Z;b zS31&UZqu;+#jFEAHyJJgmM}q+*&_^gdpz738|Rzq?=iM_irW41cH|^z)XGw!0tJhk zOzx|@LIzk#DUC`=c4kJ&;E=7-Uxa!8^&Ox{Pm==$eg(A4?P8_ehGJ@!5+Kh{KqcnS z^NWgcxm-j?NAZ$2n}enAlA%!t#K@DA0JQ!T#ED5@etw>Xg#{drX_}gE^4`HC4E#PA z5EB!#1wa)pCa^GVb90aQ&C<{5FTciWyUm%Z8osLhbnz!~VS@WyRNK7y8S?XXaH_oQ z2|06LfZuL+1hiu7Mpb)CQsR@eJboOoJ~}oIFySX)-Y5dyy|(~Jl_v+R4_R#hRzHD` z^#Z;5_I@s1Y2?q*JGk9$X6NR(@k=uwou~ldjpEk>;`{ms0L=a(Y?*O7N28;nM{n847Ci9BARnKsz&1Q` z0w@a;$ZK&prq6Bk9dPB^PuPY>dVtGIUPS3>smIKH{jD1XURQsShQ=QOssPIp0y=%6 zSEEww>+ZcZAU1eI<8|ulFXHujD}l2?U&Yn67iQ%t$*m9Uj#rfFX>nrh{JYv8n0jD8 z3seBJK?wkKboETMw*7idCX3uIl}Z)QZ;cJP;J&S?rKYZ)N00ul^nw4i>|EeCkH<6H z*4}x+>3k@;KRKz9$z;#Q#>A`&c+hI&^4059pF7V@V|x#968J>8^R*7ASsJynG&?h+ zM3J5*SF4oBlau^cDt5br(XnxctTy`k2k7oK`_K7RU$tA-JstapoV85Iz={*{Kj`## U0d>1UPyhe`07*qoM6N<$f^`8TCjbBd literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_16.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_16.png new file mode 100644 index 0000000000000000000000000000000000000000..359c0b6e086656b31ec087e8d6285b06fbe0e3ce GIT binary patch literal 1307 zcmV+$1?2jPP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0}Te0FjB<;00f&!L_t(o!^M|s;bF4I zrj`w{G0}Ammzxc)zJN(&-|dio+BPyW;?bABd|7gIRMas+5W+nYZ~)I(_Q1fv`}#Mm zdp!Bo>=!Fsw|>^RXx|5f`$KlS-Hu2!F~lSiiOgcTE$aEZw`RNonVzEk<=5UIHC^o$ zuuk8@N1q-bW6KLHS8rs=%C&6Vw0X=QzgR^|Qo?p10YL0hWHMYoG-|VP2$e!UAuWk&6J5odiOCA<+9z9{``^A9Ncx-ZF9a+wZvaTOH+v zhml4_j`>1D<^w1K{E_oks}+D zfIGv(ZsUDduK^gG1hl>oNJ&Zn;KGkTP4IR6*#$skgnNbW*69IsP67?S5Xj7U8i0de z6jJ%s*H|pK85tR&p{a#;_vQhx>8U5(*0gnW0%%3fQaog_XoBa?m3o`|u5|+7P(cw# z%TG)?clF8@9N51PvG`unb?Nl%eEm%ZjK(bi4zTN^qqZtvRLI$}o&6uaM@muxf*=qW z7|3Fkg12&aaqzReF>rvNf2n1_Xw(9iM6Sp2;LuR*yx`#Z5Aqt``BxY3?9D^p)B6Fi zC%{GWcC&e~>_PVdr_Y{8-_zR+oSJYWij9fR)wXriJ}B^t%9B)8e*;hiv`-+Any$91 z6tZWUTCQ~Z8@#Ie92J!(vD@wWz!8tP;^Ok-R%ujZ?Jbjel{_{k)L(yowEP6dTc#sG z9$@uI0HEP=v!S-`_p^c!lp>KxWX?)AlYlEMDW{~OlHuWh^Bv$f?%NkQ&1SP%>*^bi zTP(LlHwOk(f*?G+ASA>q;4Yn>Q)kXmTy~6KHTBKFUf^TbKc8-MnxIn3w5BNda$OyAXObnEoAb#&6yqIKr^8Ar6Y``jHno1E!%$iS2x@_&x`p|e=^ RdAPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0|p?a$qw@X00fFjL_t(o!^M|tOp|96$A2vYUyO1oE`Z9tbRZ0I2DDzVny@*|=3I2! zr)6_9&UlGaH{F+MHa3mXExIic=Ln!9aq7J6mZ_6k&?<7XDG*CxfGCzrZ(vz~?A-@j zgFSQ-LfX6G#K(K)CbR1Q-DwPzGqym8yH=LZDi! zP61W}E1kd|#b&p+^!E>(ni3|n7w3CnyJ0LaR0&YUIfI)T;PoM93ax&4;C+bjbcqH zEq7XR^!DXNG%>Kn*jvIwbEiYSUmBtt{Y-`_vpZts>f{@tX0(gmwM zMZ3e%OK?ySAH4Str;GBrS#pWuKhE;$&h1Q`7)Y_El%k(bKa6h4@ClauoPwFpr>q51 z9$COyWO4=-mSM$UG?IJh01M{LK^7W zxAZmtbeSy|To%akrpSD?H;3ThpyAzs_0GTcV^05*)efAdsR8CiTlIZEv0Mc9p!p8!B zy{w$y{=CTKNt1YM)k?2)WU^2Ixpb^AzuVTvC%Zle;G-=Y2@MJHMLk?PsGs{RHk+MI zTX$ly+E~4E1+Ok&>b0)fYYwO6EJ&S!gyYTb#^NB#cu>rv7YDQ(=Dt7nuu;Igx(dlc+m_3U_`}YtK z5a6@>^tE*WI+q1BHoLvWqu(r6-rukVoxYZNb2Is7|6T$G!Dn!Tv4M&z9YC2BAYG}t z*WW*I%9G-n^_#hEFtRvn0SEVefgns6Rpwm2QbI>(rw-6Ong^zY$?~i=+q)sb!J+OH zo0=aQsaR7=Mpm|`Vb)E>G;r~<8sH3Y?@=8{SE_0(7Hj^~-UEI<_bUyJO_jjOAwy}k zRxQ!#Ypk3qrGO#+p%lO@nu5>JZ{MU0ZuHZH5A-K9{>OV07*qoM6N<$f)7z> Ar2qf` literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_3.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_3.png new file mode 100644 index 0000000000000000000000000000000000000000..2360fb67d0218d572bb95c5744eb9b19100c98c0 GIT binary patch literal 1351 zcmV-N1-SZ&P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z0|qux9lN3c00hTLL_t(o!^M|tOp|96$A86Es%~Kx9dfahQYs3o#7taghMl)yOlC~f z&BQIy#F@oiT-3QNCevlnWz*>{Y+f0HV;USzw|&s9S_@JIf!Yad*s4Q7TaZhI0#f(x zOG{8_U&JmupWeLBInV$9oXc~b1OKx~hN@__m|}noARW*F8X(HI>;&w94JZZ7X?jCr zNC;RhrW9Z)u-FGID(!A}U2m`V*tkeVcADN$H7o*Fi%9~k0agRkhT~qRtLav2TigC* zZPJ!By+If<0jtF{0oVYn4@I0WRak#dos#_8b1!DzdU$O_0ProqTcJv{nCJ=WvhvD# z399&#(n}T2{%c`_xP61q^^Yv~?%fNxrk^og7e8@go?I@E?*Cu3V9Mpc^>{&Xe%ayz1i>@IVNB+5RyQ z9f*J-a}lSEXR$l3)9${D_x^qU5d^xrx~Okxr0BebbHydhojnVAcsLTtz!a0oWNNqj zuH@SF8>WXtuv9GDJ3StxBSx?=b3Whf`V{l2pD8akV*Is`?OQh!_4IgZ?GASA&KeXP zVDcm_Q=ds$4W#siz<0?k7K`!pX=!};!F$BT#ys#pQlVhM{JE%5k395Ji1VIS8k5-dN>g41lK#ZS2dML`xXfgvZ z=fwtE59m^-uyNg+qIOA|M1XWZ0nKp0)AWYE z?@37--e3PVixw_GDwT@bD&t}Sbp8-TJ+Axh*RE4^{sMLN4MWmbD8>S4q>lq?wV3Gj zdT}~koHZBo)t&>Cl~;nkeU}HoO#O_Y`_$SUlvmmSO2d5h+}PXeJtjt= ztisAm%U1Bo=U;O9k1D#lyXo%kq4KhgcQt!+8Mn4dmbz}C&1m}AHwdO{R3nGAV&IBHcqD_&X3kNG(~KVy2((-)rj1;@1; z6+pp&N2%3flGv_PpVOsIdEvhpLUQwuvg_+T2!ikiuxG%VFimd|v>Nrx<&~FfLJfZG zr<3I7A4L#^oxt9Jui^uT4tFRg#ueRZX`Pvvpo$9B$qyd-p5{9(dx330M?eAqrI#w4 zMI{$b$mQWvWipw1D0Lku;r3-8B0D!9kEd&=5Bzq}xxg=8ueYP*V%cH0`>w>*)TEWm z002ov JPDHLkV1n^+fye*= literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_4.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_4.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7fee8e9382f14e101da6493861e55ba3f80f58 GIT binary patch literal 1109 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 DKPZla literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_x.png b/Mage.Client/src/mage/client/util/resources/images/symbols/colorless_x.png new file mode 100644 index 0000000000000000000000000000000000000000..4114acb19732adf3c336b7f8812905a0044d8aca GIT binary patch literal 1316 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 VWO8J~o#_Ao002ovPDHLkV1l<;&(i<^ literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/green_white.png b/Mage.Client/src/mage/client/util/resources/images/symbols/green_white.png new file mode 100644 index 0000000000000000000000000000000000000000..c9db56e9bdfe074968aa6f4d4a5ea6d145e36036 GIT binary patch literal 1036 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 eETwE}LjDUM?dK{e@Xpf!0000OK2qk literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/mana_red.png b/Mage.Client/src/mage/client/util/resources/images/symbols/mana_red.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9f1e2d69c5417602a1a92326bcaeaa04202078 GIT binary patch literal 784 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 literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/red_white.png b/Mage.Client/src/mage/client/util/resources/images/symbols/red_white.png new file mode 100644 index 0000000000000000000000000000000000000000..d810e8f7cf7237b2695117e043c4dc84a78e1255 GIT binary patch literal 1032 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 Z{R{n~ZP=@Gf3N@m002ovPDHLkV1l8+F+l(T literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/white_black.png b/Mage.Client/src/mage/client/util/resources/images/symbols/white_black.png new file mode 100644 index 0000000000000000000000000000000000000000..762f4b8cdfc8986e7288c18c4964d56698fa3254 GIT binary patch literal 1001 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z10w`+IXcAv000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009-Nkl|bzFf$!r1N`F_od2a#=?Njkw&gXAu|hUWiokaRu~Ojx%a#S|q+B{?=vNLFvhfvw z?*snwN@y!r*8V&ejakoPFNVK)0(RtodMI>ts{8kw@v)cPt7>X46+Hnv=eInD-@1M^ zv>l*I%BDHX`Y@Zx-2F;~w%VVRlk=(|9=+()Nv-kS1>Aw^+ zl0xA3`7Q$Z?X?zf;AcideUYthj4P#V$j!~wIw@!?7v9}*=6Qdod?WZ5={exQ;`=jvt0h;~gMBaJ))T407_^FINRy!IP zF9H5I95Q|^m2Bp6U(|w;#lTM->wOXq89$Vx+SzOtVBB#a>>7Tw_i1F{#^!SGY+5OR z5k~{V?%+Mqh(5H*i{~=4;6Qi@Ky|P_VVb#EF?h$(o@Wt#XrmYKtZ9;)p9dKJR154L z?*HLOdd3Fzp(d|t^kgy#5LHSgJ}*W_DwUqdhqoU-`C>3Uw81NQ)-)Xf9{8dfRtM`X zA;h+PxDmOz-pe`Q_51e#QNZ}BC0kz87#kgZcnDC(4|l)x8vbT#%DMl$lu}l~wtQz> z>mP3?-W>E2KAB81ok{`hQA%Ad+7&;46%Q>HVpWxtOYT4|g@1Rccy8K-2UU!C;*f!Zmm@nRL`1wR8Twd}m6S*!n71sEjt literal 0 HcmV?d00001 diff --git a/Mage.Client/src/mage/client/util/resources/images/symbols/white_blue.png b/Mage.Client/src/mage/client/util/resources/images/symbols/white_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..b2c768daef77992d1848514b0dc553d725578879 GIT binary patch literal 1020 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igM- z10y6#R~iif000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000A5NklSywWRgy{HByG4ZF`s)^y2 z^rBZL#q_F4YXAWel1*T-%R(v9lr_7R-JR8jCSoB4nghGj=S3OwZj%k2Xy;a|?0(*sf2x$|N9*>in*sk31> z6Sn7LxLx2s4@Tu1sV_8FJ$loLab4F7QUzR61-}?D{ew~Ydb)svT|G5c!v6}eb~qK; ziwgmBb|@xa+bc+O)l+oHb$RC(Xj1|IB4Ez_5R<1e33k*rH|V-vX$$C30KYXHlNl$X zH?{z@6Hh$ z!1v!-VAXKD!awnwp|QC1s5&OsZu9~Kg%Ha-4r=hdLEj3N+OofmCA&;r-1OEQD8z2aHpDId^xEjNAa|<6@@FnH&{*Oqm!~xzE zLdacf!tbtL3(RXxM{iNrr4qh+{Tm+54g$O_gz)WI6)#PVjA;kTt4rL+J*qOd;O`3| z`u8o%0X7$XLvqDf(_GJN5tf z-RQO59<