view src/net/kryshen/charamega/ui.mirah @ 0:91ecd24948de

Imported.
author Mikhail Kryshen <mikhail@kryshen.net>
date Sat, 14 Jul 2012 05:46:29 +0400
parents
children fac1b8f35265
line source
1 #
2 # Copyright 2012 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
28 @@title = 'Charamega'
29 @@version = '0.9'
30 @@home = 'http://kryshen.net/games/'
32 def initialize(root_pane:JRootPane)
33 super LayoutManager(BorderLayout.new)
35 @game = Game.new.shuffle(20)
36 @field = Field.new(@game)
37 @field.setBorder BorderFactory.createEmptyBorder(5, 5, 5, 5)
39 add @field, BorderLayout.CENTER
40 add create_status, BorderLayout.SOUTH
42 ui = self
43 @timer = Timer.new(250) { |e| ui.update }
45 @conf = create_configurator
46 root_pane.getLayeredPane.add @conf, JLayeredPane.MODAL_LAYER
47 root_pane.setDefaultButton @start
49 stop
50 update_status
51 end
53 def doLayout
54 @conf.setSize @conf.getPreferredSize
55 @conf.setLocation int(getWidth * 0.05), int(getHeight * 0.05)
56 super
57 end
59 def update
60 @field.repaint if @game.update
61 stop if @game.finished?
62 update_status
63 end
65 def update_status
66 @status.setText(@game.status)
67 end
69 def start
70 @conf.setVisible false
71 @field.setEnabled true
72 @start.setEnabled false
73 @stop.setEnabled true
74 @game.start
75 @timer.start
76 @field.repaint
77 end
79 def stop
80 @timer.stop
81 @game.stop
82 @stop.setEnabled false
83 @start.setEnabled true
84 @field.setEnabled false
85 @conf.setVisible true
86 @field.repaint
87 end
89 private
91 def create_status
92 ui = self
94 status_panel = JPanel.new
95 layout = GroupLayout.new(status_panel)
96 status_panel.setLayout layout
98 @status = JLabel.new('', SwingConstants.RIGHT)
99 @stop = JButton.new('New game')
100 @stop.addActionListener do |e|
101 ui.update_status
102 ui.stop
103 end
105 gap = 5
107 h_group = layout.createSequentialGroup
108 .addGap(1, gap, gap)
109 .addComponent(@stop)
110 .addGap(1, gap, gap)
111 .addComponent(@status,
112 GroupLayout.DEFAULT_SIZE,
113 GroupLayout.DEFAULT_SIZE,
114 Short.MAX_VALUE)
115 .addGap(1, gap, gap)
117 v_group = layout.createSequentialGroup
118 .addGap(1, gap, gap)
119 .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
120 .addComponent(@stop)
121 .addComponent(@status))
122 .addGap(1, gap, gap)
124 layout.setHorizontalGroup h_group
125 layout.setVerticalGroup v_group
127 status_panel
128 end
130 def create_configurator
131 # Can't use object fields in closures in Mirah 0.11.
132 ui = self
133 game = @game
134 field = @field
136 conf = JPanel.new
137 layout = GroupLayout.new(conf)
138 conf.setLayout layout
139 conf.setBorder BorderFactory.createRaisedBevelBorder
141 layout.setAutoCreateGaps true
142 layout.setAutoCreateContainerGaps true
144 title = JLabel.new(@@title)
145 .setFont(Font.new('serif', Font.BOLD, 26))
147 version = JLabel.new("version #{@@version}")
148 link = HyperlinkLabel.new(@@home)
150 players_label = JLabel.new('Players: ')
151 pairs_label = JLabel.new('Pairs: ')
153 players = SpinnerNumberModel.new(1, 1, 20, 1)
154 pairs = SpinnerNumberModel.new(20, 2, 200, 5)
156 players_spinner = JSpinner.new(players)
157 pairs_spinner = JSpinner.new(pairs)
159 players.addChangeListener do |e|
160 game.players = players.getNumber.intValue
161 field.repaint if game.shuffle
162 ui.update_status
163 end
165 pairs.addChangeListener do |e|
166 game.shuffle pairs.getNumber.intValue
167 field.repaint
168 ui.update_status
169 end
171 @start = JButton.new("Start")
172 @start.addActionListener do |e|
173 ui.start
174 end
176 h_group = layout.createParallelGroup
177 .addGroup(layout.createSequentialGroup
178 .addComponent(title)
179 .addComponent(version))
180 .addGroup(layout.createSequentialGroup
181 .addComponent(link,
182 GroupLayout.DEFAULT_SIZE,
183 GroupLayout.DEFAULT_SIZE,
184 GroupLayout.PREFERRED_SIZE)
185 .addGap(0, 0, Short.MAX_VALUE))
186 .addGroup(layout.createSequentialGroup
187 .addGap(0, 0, Short.MAX_VALUE)
188 .addGroup(layout.createParallelGroup
189 .addComponent(pairs_label)
190 .addComponent(players_label))
191 .addGroup(layout.createParallelGroup
192 .addComponent(pairs_spinner)
193 .addComponent(players_spinner))
194 .addGap(0, 0, Short.MAX_VALUE))
195 .addGroup(layout.createSequentialGroup
196 .addGap(0, 0, Short.MAX_VALUE)
197 .addComponent(@start))
199 v_group = layout.createSequentialGroup
200 .addGroup(layout.createBaselineGroup(false, true)
201 .addComponent(title)
202 .addComponent(version))
203 .addComponent(link)
204 .addGap(25)
205 .addGroup(layout.createBaselineGroup(false, true)
206 .addComponent(pairs_label)
207 .addComponent(pairs_spinner))
208 .addGroup(layout.createBaselineGroup(false, true)
209 .addComponent(players_label)
210 .addComponent(players_spinner))
211 .addGap(15)
212 .addComponent(@start)
214 layout.setHorizontalGroup h_group
215 layout.setVerticalGroup v_group
217 conf
218 end
219 end
221 class HyperlinkLabel < JLabel
223 def initialize(uri:String)
224 initialize URI.new(uri), uri
225 end
227 def initialize(uri:URI)
228 initialize uri, uri.toString
229 end
231 def initialize(uri:URI, text:String)
232 @uri = uri
234 s = text.replace('&', '&amp;')
235 .replace('<', '&lt;')
236 .replace('>', '&gt;')
238 setText "<html><u>#{s}</u></html>"
239 setForeground Color.BLUE.darker
240 setCursor Cursor.new(Cursor.HAND_CURSOR)
242 enableEvents AWTEvent.MOUSE_EVENT_MASK
243 end
245 def processMouseEvent(event)
246 if event.getID == MouseEvent.MOUSE_CLICKED
247 Desktop.getDesktop.browse @uri
248 end
250 super
251 end
252 end
254 # UIManager.setLookAndFeel UIManager.getSystemLookAndFeelClassName
256 frame = JFrame.new 'Charamega'
257 ui = Ui.new(frame.getRootPane)
259 frame.getContentPane.add ui
260 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
261 .setSize(800, 600)
262 .validate
263 .setVisible(true)