Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
require 'fox16'
include Fox
class GemBrowser
#
# A reference to the currently selected Gem specification, or +nil+
# if none is selected.
#
attr_accessor :currentSpec
def initialize
@currentSpec = nil
end
#
# Install the Gem described by the named spec file, and return the
# Specification for this Gem.
#
def install(filename)
Gem::Installer.new(filename).install
spec = nil
cache.each do |n, s|
spec = s if (File.basename(filename, ".gem") == s.full_name)
end
spec
end
#
# Uninstall the Gem described by this specification.
#
def uninstall(spec)
Gem::Uninstaller.new(spec.name).uninstall
end
# Return an array of the installed specifications.
def cache
# Gem.cache
Gem::Cache.from_installed_gems
end
end
class GemInfoPanel < FXVerticalFrame
attr_reader :browser
def initialize(p, b, opts)
# Initialize base class
super(p, opts)
@browser = b
self.backColor = FXRGB(255, 255, 255)
File.open(File.join("icons", "gem_big.png"), "rb") do |f|
@bigIcon = FXPNGIcon.new(getApp(), f.read)
end
nameLabel = FXLabel.new(self, "", @bigIcon, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_FILL_X)
nameLabel.backColor = FXRGB(255, 255, 255)
nameLabel.connect(SEL_UPDATE) { |nameLabel, sel, ptr|
if currentSpec
nameLabel.text = specDescription(currentSpec)
nameLabel.show
else
nameLabel.text = ""
nameLabel.hide
end
}
summaryText = FXText.new(self, nil, 0, TEXT_READONLY|TEXT_WORDWRAP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
summaryText.backColor = FXRGB(255, 255, 255)
summaryText.connect(SEL_UPDATE) { |summaryText, sel, ptr|
theText = currentSpec ? currentSpec.summary : nil
summaryText.text = theText unless (summaryText.text == theText)
}
end
#
# Return a reference to the currently selected Gem specification,
# or +nil+ if none is selected.
#
def currentSpec
browser.currentSpec
end
# Return a multiline string (suitable for use with an FXLabel) describing this spec.
def specDescription(spec)
[spec.name, "version #{spec.version}", spec.author, spec.email, spec.homepage].join("\n")
end
def create
super
@bigIcon.create
end
end
class GemsPanel < FXVerticalFrame
attr_reader :browser
def initialize(p, br, opts)
# Initialize base class
super(p, opts)
# Save a reference to the browser
@browser = br
File.open(File.join("icons", "gem_big.png"), "rb") do |f|
@bigIcon = FXPNGIcon.new(getApp(), f.read)
end
File.open(File.join("icons", "gem_small.png"), "rb") do |f|
@smallIcon = FXPNGIcon.new(getApp(), f.read)
end
@iconList = FXIconList.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|ICONLIST_MINI_ICONS|ICONLIST_BROWSESELECT)
@iconList.connect(SEL_SELECTED) { |sender, sel, ptr|
browser.currentSpec = itemSpec(ptr)
}
# Fill the list with installed specifications.
browser.cache.each { |name, spec| appendItem(spec) }
if numItems > 0
selectItem(0)
browser.currentSpec = itemSpec(0)
end
end
def appendItem(spec)
@iconList.appendItem(spec.name, @bigIcon, @smallIcon, spec)
if numItems == 1
selectItem(0)
browser.currentSpec = itemSpec(0)
end
end
def currentItem
@iconList.currentItem
end
#
# Return the specification associated with the item at _index_, or
# +nil+ if no such item.
#
def itemSpec(index)
(index >= 0) ? getItem(index).data : nil
end
def currentItemSpec
itemSpec(currentItem)
end
def getItem(*args)
@iconList.getItem(*args)
end
def selectItem(index)
@iconList.selectItem(index, true)
end
def numItems
@iconList.numItems
end
def create
super
@bigIcon.create
@smallIcon.create
self.width = @iconList.font.getTextWidth("MMMMMMMMMMMMM")
end
end
class GemBrowserWindow < FXMainWindow
attr_reader :browser
def initialize(anApp)
# Initialize base class first
super(anApp, "Gem Browser", nil, nil, DECOR_ALL)
# Menu bar
menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File menu
filemenu = FXMenuPane.new(self)
FXMenuTitle.new(menubar, "&File", nil, filemenu)
installCmd = FXMenuCommand.new(filemenu, "Install a Gem...")
installCmd.connect(SEL_COMMAND) { install }
uninstallCmd = FXMenuCommand.new(filemenu, "Uninstall this Gem")
uninstallCmd.connect(SEL_COMMAND) { uninstall }
uninstallCmd.connect(SEL_UPDATE) do |sender, sel, ptr|
spec = browser.currentSpec
if spec
sender.text = "Uninstall #{spec.name}"
sender.enable
else
sender.text = "Uninstall this Gem"
sender.disable
end
end
FXMenuCommand.new(filemenu, "&Quit\tCtl-Q").connect(SEL_COMMAND) { quit }
# Main window interior
contents = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
@browser = GemBrowser.new
# Horizontal splitter with info pane on the left, icon list on the right
@splitter = FXSplitter.new(contents, LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_HORIZONTAL|SPLITTER_REVERSED) do |splitter|
infoPanel = GemInfoPanel.new(splitter, @browser, LAYOUT_FILL_X|LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK)
@gemsPanel = GemsPanel.new(splitter, @browser, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK)
end
# Catch these too
self.connect(SEL_CLOSE) { quit }
anApp.addSignal("SIGINT") { quit }
end
def install
FXFileDialog.new(self, "Install Gem") { |dlg|
dlg.directory = @directory unless @directory.empty?
dlg.patternList = ["Gem Files (*.gem)", "All Files (*)"]
if dlg.execute != 0
@directory = dlg.directory
begin
spec = browser.install(dlg.filename)
@gemsPanel.appendItem(spec)
rescue => ex
FXMessageBox.error(self, MBOX_OK, "Installation Failed", ex.to_s)
end
end
}
end
def uninstall
begin
browser.uninstall(browser.currentSpec)
rescue => ex
FXMessageBox.error(self, MBOX_OK, "Uninstall Failed", ex.to_s)
end
end
def quit
getApp().reg().writeIntEntry("SETTINGS", "x", x)
getApp().reg().writeIntEntry("SETTINGS", "y", y)
getApp().reg().writeIntEntry("SETTINGS", "width", width)
getApp().reg().writeIntEntry("SETTINGS", "height", height)
getApp().reg().writeIntEntry("SETTINGS", "listWidth", @splitter.first.next.width)
getApp().reg().writeStringEntry("SETTINGS", "directory", @directory) if @directory
getApp().exit(0)
end
def create
# Do base class create
super
# Get size, etc. from registry
xx = getApp().reg().readIntEntry("SETTINGS", "x", 0)
yy = getApp().reg().readIntEntry("SETTINGS", "y", 0)
ww = getApp().reg().readIntEntry("SETTINGS", "width", 450)
hh = getApp().reg().readIntEntry("SETTINGS", "height", 300)
position(xx, yy, ww, hh)
# Splitter child sizes
rightPaneSize = getApp().reg().readIntEntry("SETTINGS", "listWidth", -1)
if rightPaneSize >= 0
@splitter.first.next.width = rightPaneSize
end
# Last directory for Gem files
@directory = getApp().reg().readStringEntry("SETTINGS", "directory", "")
# Show it
show
end
end
if __FILE__ == $0
FXApp.new("GemBrowser", "FXRuby") do |theApp|
GemBrowserWindow.new(theApp)
theApp.create
theApp.run
end
end