view src/net/kryshen/charamega/ui.mirah @ 15:8ed3a7b4f6e9

Changed homepage URL.
author Mikhail Kryshen <mikhail@kryshen.net>
date Sun, 26 Jan 2014 16:12:22 +0400
parents 21bc7e1d1429
children
line source
1 #
2 # Copyright 2012, 2013, 2014 Mikhail Kryshen <mikhail@kryshen.net>
3 #
4 # This file is part of Charamega.
5 #
6 # Charamega is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # Charamega is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Charamega. If not, see <http://www.gnu.org/licenses/>.
18 #
20 package net.kryshen.charamega
22 import java.awt.*
23 import java.awt.event.*
24 import javax.swing.*
25 import java.net.URI
27 class Ui < JPanel
29 def self.initialize:void
30 @@title = 'Charamega'
31 @@home = 'http://www.games1729.com/'
32 end
34 def initialize(root_pane:JRootPane)
35 setLayout BorderLayout.new
37 @game = Game.new.shuffle(30)
38 @field = Field.new(@game)
39 @field.setBorder BorderFactory.createEmptyBorder(5, 5, 5, 5)
41 add @field, BorderLayout.CENTER
42 add create_status, BorderLayout.SOUTH
44 ui = self
45 @timer = Timer.new(250) { |e| ui.update }
47 @conf = create_configurator
48 root_pane.getLayeredPane.add @conf, JLayeredPane.MODAL_LAYER
49 root_pane.setDefaultButton @start
51 stop
52 update_status
53 end
55 def doLayout
56 @conf.setSize @conf.getPreferredSize
57 @conf.setLocation int(getWidth * 0.05), int(getHeight * 0.05)
58 super
59 end
61 def update
62 @field.repaint if @game.update
63 stop if @game.finished?
64 update_status
65 end
67 def update_status
68 @status.setText(@game.status)
69 end
71 def start
72 @conf.setVisible false
73 @field.setEnabled true
74 @start.setEnabled false
75 @stop.setEnabled true
76 @game.start
77 @timer.start
78 @field.repaint
79 end
81 def stop
82 @timer.stop
83 @game.stop
84 @stop.setEnabled false
85 @start.setEnabled true
86 @field.setEnabled false
87 @conf.setVisible true
88 @field.repaint
89 end
91 def self.create_frame
92 title = @@title
93 SwingUtilities.invokeLater do
94 # UIManager.setLookAndFeel UIManager.getSystemLookAndFeelClassName
96 frame = JFrame.new title
97 ui = Ui.new(frame.getRootPane)
99 frame.getContentPane.add ui
100 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
101 .pack
102 .setVisible(true)
103 end
104 end
106 #private
108 def create_status
109 ui = self
111 status_panel = JPanel.new
112 layout = GroupLayout.new(status_panel)
113 status_panel.setLayout layout
115 @status = JLabel.new('', SwingConstants.RIGHT)
116 @stop = JButton.new('New game')
117 @stop.addActionListener do |e|
118 ui.update_status
119 ui.stop
120 end
122 gap = 5
124 h_group = layout.createSequentialGroup
125 .addGap(1, gap, gap)
126 .addComponent(@stop)
127 .addGap(1, gap, gap)
128 .addComponent(@status,
129 GroupLayout.DEFAULT_SIZE,
130 GroupLayout.DEFAULT_SIZE,
131 Short.MAX_VALUE)
132 .addGap(1, gap, gap)
134 v_group = layout.createSequentialGroup
135 .addGap(1, gap, gap)
136 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
137 .addComponent(@stop)
138 .addComponent(@status))
139 .addGap(1, gap, gap)
141 layout.setHorizontalGroup h_group
142 layout.setVerticalGroup v_group
144 status_panel
145 end
147 def create_configurator
148 # Can't use object fields in closures in Mirah 0.11.
149 ui = self
150 game = @game
151 field = @field
153 conf = JPanel.new
154 layout = GroupLayout.new(conf)
155 conf.setLayout layout
156 conf.setBorder BorderFactory.createRaisedBevelBorder
158 layout.setAutoCreateGaps true
159 layout.setAutoCreateContainerGaps true
161 title = JLabel.new(@@title)
162 .setFont(Font.new('serif', Font.BOLD, 26))
164 version = JLabel.new("version #{@game.version}")
165 link = HyperlinkLabel.new(@@home)
167 players_label = JLabel.new('Players: ')
168 pairs_label = JLabel.new('Pairs: ')
170 players = SpinnerNumberModel.new(1, 1, 20, 1)
171 pairs = SpinnerNumberModel.new(@game.cards.size / 2, 2, 200, 10)
173 players_spinner = JSpinner.new(players)
174 pairs_spinner = JSpinner.new(pairs)
176 players.addChangeListener do |e|
177 game.players = players.getNumber.intValue
178 field.repaint if game.ensure_shuffled
179 ui.update_status
180 end
182 pairs.addChangeListener do |e|
183 game.shuffle pairs.getNumber.intValue
184 field.repaint
185 ui.update_status
186 end
188 @start = JButton.new("Start")
189 @start.addActionListener do |e|
190 ui.start
191 end
193 h_group = layout.createParallelGroup
194 .addGroup(layout.createSequentialGroup
195 .addComponent(title)
196 .addComponent(version))
197 .addGroup(layout.createSequentialGroup
198 .addComponent(link,
199 GroupLayout.DEFAULT_SIZE,
200 GroupLayout.DEFAULT_SIZE,
201 GroupLayout.PREFERRED_SIZE)
202 .addGap(0, 0, Short.MAX_VALUE))
203 .addGroup(layout.createSequentialGroup
204 .addGap(0, 0, Short.MAX_VALUE)
205 .addGroup(layout.createParallelGroup
206 .addComponent(pairs_label)
207 .addComponent(players_label))
208 .addGroup(layout.createParallelGroup
209 .addComponent(pairs_spinner)
210 .addComponent(players_spinner))
211 .addGap(0, 0, Short.MAX_VALUE))
212 .addGroup(layout.createSequentialGroup
213 .addGap(0, 0, Short.MAX_VALUE)
214 .addComponent(@start))
216 v_group = layout.createSequentialGroup
217 .addGroup(layout.createBaselineGroup(false, true)
218 .addComponent(title)
219 .addComponent(version))
220 .addComponent(link)
221 .addGap(25)
222 .addGroup(layout.createBaselineGroup(false, true)
223 .addComponent(pairs_label)
224 .addComponent(pairs_spinner))
225 .addGroup(layout.createBaselineGroup(false, true)
226 .addComponent(players_label)
227 .addComponent(players_spinner))
228 .addGap(15)
229 .addComponent(@start)
231 layout.setHorizontalGroup h_group
232 layout.setVerticalGroup v_group
234 conf
235 end
236 end
238 class HyperlinkLabel < JLabel
240 def initialize(uri:String)
241 initialize URI.new(uri), uri
242 end
244 def initialize(uri:URI)
245 initialize uri, uri.toString
246 end
248 def initialize(uri:URI, text:String)
249 @uri = uri
251 s = text.replace('&', '&amp;')
252 .replace('<', '&lt;')
253 .replace('>', '&gt;')
255 setText "<html><u>#{s}</u></html>"
256 setForeground Color.BLUE.darker
257 setCursor Cursor.new(Cursor.HAND_CURSOR)
259 enableEvents AWTEvent.MOUSE_EVENT_MASK
260 end
262 def processMouseEvent(event)
263 if event.getID == MouseEvent.MOUSE_CLICKED
264 # How to reference java.applet.Applet without importing?
265 root = SwingUtilities.getAncestorOfClass(JApplet.class, self)
266 if root
267 JApplet(root).getAppletContext.showDocument @uri.toURL
268 else
269 # Should work for applets too, but at least with IcedTea it does not.
270 Desktop.getDesktop.browse @uri
271 end
272 end
274 super
275 end
276 end
278 class Applet < JApplet
279 def initialize
280 getContentPane.add Ui.new(getRootPane)
281 end
282 end
284 create_frame