fxruby 1.6.22 → 1.6.23
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +14 -0
- data/.yardopts +8 -0
- data/History.txt +6 -0
- data/Manifest.txt +317 -24
- data/README.git +3 -0
- data/README.rdoc +537 -0
- data/Rakefile +62 -46
- data/Rakefile.cross +397 -0
- data/doap.rdf +3 -3
- data/doap.rdf.erb +87 -0
- data/examples/WhatAQuietStiff.rb +356 -0
- data/examples/canvasdemo.rb +88 -0
- data/examples/gdchart.rb +76 -0
- data/examples/gembrowser.rb +289 -0
- data/examples/rmagick.rb +44 -0
- data/lib/fox16/canvas.rb +606 -0
- data/lib/fox16/irb.rb +1 -0
- data/lib/fox16/splashscreen.rb +1 -0
- data/lib/fox16/tkcompat.rb +56 -0
- data/lib/fox16/version.rb +1 -1
- data/rdoc-sources/FX4Splitter.rb +44 -44
- data/rdoc-sources/FX7Segment.rb +3 -3
- data/rdoc-sources/FXAccelTable.rb +1 -1
- data/rdoc-sources/FXApp.rb +51 -51
- data/rdoc-sources/FXArrowButton.rb +6 -6
- data/rdoc-sources/FXBMPIcon.rb +12 -12
- data/rdoc-sources/FXBMPImage.rb +6 -6
- data/rdoc-sources/FXBitmap.rb +9 -9
- data/rdoc-sources/FXBitmapFrame.rb +3 -3
- data/rdoc-sources/FXBitmapView.rb +12 -12
- data/rdoc-sources/FXButton.rb +5 -5
- data/rdoc-sources/FXCanvas.rb +4 -4
- data/rdoc-sources/FXCheckButton.rb +7 -7
- data/rdoc-sources/FXChoiceBox.rb +16 -16
- data/rdoc-sources/FXColorBar.rb +9 -9
- data/rdoc-sources/FXColorDialog.rb +4 -4
- data/rdoc-sources/FXColorList.rb +1 -1
- data/rdoc-sources/FXColorRing.rb +4 -4
- data/rdoc-sources/FXColorSelector.rb +38 -38
- data/rdoc-sources/FXColorWell.rb +15 -15
- data/rdoc-sources/FXColorWheel.rb +8 -8
- data/rdoc-sources/FXComboBox.rb +24 -24
- data/rdoc-sources/FXCursor.rb +12 -12
- data/rdoc-sources/FXDC.rb +176 -176
- data/rdoc-sources/FXDCPrint.rb +20 -20
- data/rdoc-sources/FXDCWindow.rb +2 -2
- data/rdoc-sources/FXDataTarget.rb +1 -1
- data/rdoc-sources/FXDebugTarget.rb +1 -1
- data/rdoc-sources/FXDelegator.rb +2 -2
- data/rdoc-sources/FXDial.rb +9 -9
- data/rdoc-sources/FXDialogBox.rb +3 -3
- data/rdoc-sources/FXDict.rb +2 -3
- data/rdoc-sources/FXDirBox.rb +2 -2
- data/rdoc-sources/FXDirList.rb +14 -14
- data/rdoc-sources/FXDirSelector.rb +14 -14
- data/rdoc-sources/FXDockBar.rb +35 -35
- data/rdoc-sources/FXDockHandler.rb +2 -2
- data/rdoc-sources/FXDockSite.rb +11 -11
- data/rdoc-sources/FXDockTitle.rb +2 -2
- data/rdoc-sources/FXDocument.rb +2 -2
- data/rdoc-sources/FXDragCorner.rb +2 -2
- data/rdoc-sources/FXDrawable.rb +5 -5
- data/rdoc-sources/FXDriveBox.rb +3 -3
- data/rdoc-sources/FXFileDialog.rb +24 -24
- data/rdoc-sources/FXFileDict.rb +11 -11
- data/rdoc-sources/FXFileList.rb +25 -25
- data/rdoc-sources/FXFileSelector.rb +31 -31
- data/rdoc-sources/FXFileStream.rb +3 -3
- data/rdoc-sources/FXFoldingList.rb +76 -76
- data/rdoc-sources/FXFont.rb +133 -133
- data/rdoc-sources/FXFontDialog.rb +1 -1
- data/rdoc-sources/FXFontSelector.rb +14 -14
- data/rdoc-sources/FXFrame.rb +5 -5
- data/rdoc-sources/FXGIFCursor.rb +6 -6
- data/rdoc-sources/FXGIFIcon.rb +6 -6
- data/rdoc-sources/FXGIFImage.rb +5 -5
- data/rdoc-sources/FXGLContext.rb +1 -1
- data/rdoc-sources/FXGLObject.rb +8 -8
- data/rdoc-sources/FXGLShape.rb +23 -23
- data/rdoc-sources/FXGLViewer.rb +51 -51
- data/rdoc-sources/FXGLVisual.rb +1 -0
- data/rdoc-sources/FXGradientBar.rb +31 -31
- data/rdoc-sources/FXGroupBox.rb +6 -6
- data/rdoc-sources/FXHeader.rb +30 -33
- data/rdoc-sources/FXHorizontalFrame.rb +12 -12
- data/rdoc-sources/FXICOIcon.rb +14 -14
- data/rdoc-sources/FXICOImage.rb +5 -5
- data/rdoc-sources/FXIcon.rb +7 -7
- data/rdoc-sources/FXIconDict.rb +1 -0
- data/rdoc-sources/FXIconList.rb +60 -60
- data/rdoc-sources/FXId.rb +1 -1
- data/rdoc-sources/FXImage.rb +49 -49
- data/rdoc-sources/FXImageFrame.rb +12 -12
- data/rdoc-sources/FXImageView.rb +10 -10
- data/rdoc-sources/FXInputDialog.rb +4 -4
- data/rdoc-sources/FXJPGIcon.rb +13 -13
- data/rdoc-sources/FXJPGImage.rb +5 -5
- data/rdoc-sources/FXKnob.rb +12 -12
- data/rdoc-sources/FXLabel.rb +3 -3
- data/rdoc-sources/FXList.rb +31 -31
- data/rdoc-sources/FXListBox.rb +7 -7
- data/rdoc-sources/FXMDIChild.rb +24 -24
- data/rdoc-sources/FXMDIClient.rb +1 -1
- data/rdoc-sources/FXMatrix.rb +2 -2
- data/rdoc-sources/FXMemoryBuffer.rb +1 -1
- data/rdoc-sources/FXMemoryStream.rb +1 -1
- data/rdoc-sources/FXMenuButton.rb +20 -19
- data/rdoc-sources/FXMenuCaption.rb +9 -9
- data/rdoc-sources/FXMenuCascade.rb +1 -1
- data/rdoc-sources/FXMenuCheck.rb +2 -2
- data/rdoc-sources/FXMenuCommand.rb +1 -1
- data/rdoc-sources/FXMenuRadio.rb +2 -2
- data/rdoc-sources/FXMenuSeparator.rb +2 -2
- data/rdoc-sources/FXMenuTitle.rb +5 -5
- data/rdoc-sources/FXMessageBox.rb +16 -16
- data/rdoc-sources/FXOptionMenu.rb +14 -14
- data/rdoc-sources/FXPCXIcon.rb +12 -12
- data/rdoc-sources/FXPCXImage.rb +5 -5
- data/rdoc-sources/FXPNGIcon.rb +12 -12
- data/rdoc-sources/FXPNGImage.rb +5 -5
- data/rdoc-sources/FXPPMIcon.rb +6 -6
- data/rdoc-sources/FXPPMImage.rb +5 -5
- data/rdoc-sources/FXPacker.rb +4 -4
- data/rdoc-sources/FXPopup.rb +5 -5
- data/rdoc-sources/FXPrintDialog.rb +21 -21
- data/rdoc-sources/FXProgressBar.rb +10 -10
- data/rdoc-sources/FXProgressDialog.rb +3 -3
- data/rdoc-sources/FXQuatd.rb +19 -19
- data/rdoc-sources/FXQuatf.rb +23 -23
- data/rdoc-sources/FXRGBIcon.rb +13 -13
- data/rdoc-sources/FXRGBImage.rb +5 -5
- data/rdoc-sources/FXRadioButton.rb +10 -10
- data/rdoc-sources/FXRanged.rb +2 -2
- data/rdoc-sources/FXRangef.rb +2 -2
- data/rdoc-sources/FXRealSlider.rb +33 -33
- data/rdoc-sources/FXRealSpinner.rb +31 -31
- data/rdoc-sources/FXRecentFiles.rb +14 -14
- data/rdoc-sources/FXRectangle.rb +22 -22
- data/rdoc-sources/FXRegistry.rb +3 -3
- data/rdoc-sources/FXReplaceDialog.rb +20 -20
- data/rdoc-sources/FXRootWindow.rb +2 -2
- data/rdoc-sources/FXRuler.rb +28 -28
- data/rdoc-sources/FXRulerView.rb +5 -5
- data/rdoc-sources/FXScrollArea.rb +27 -27
- data/rdoc-sources/FXScrollBar.rb +26 -26
- data/rdoc-sources/FXScrollPane.rb +3 -3
- data/rdoc-sources/FXScrollWindow.rb +6 -6
- data/rdoc-sources/FXSearchDialog.rb +8 -8
- data/rdoc-sources/FXSeparator.rb +24 -24
- data/rdoc-sources/FXSettings.rb +44 -44
- data/rdoc-sources/FXShutter.rb +35 -35
- data/rdoc-sources/FXSize.rb +14 -14
- data/rdoc-sources/FXSlider.rb +33 -33
- data/rdoc-sources/FXSphered.rb +2 -2
- data/rdoc-sources/FXSpheref.rb +2 -2
- data/rdoc-sources/FXSpinner.rb +30 -30
- data/rdoc-sources/FXSplashWindow.rb +5 -5
- data/rdoc-sources/FXSplitter.rb +18 -18
- data/rdoc-sources/FXSpring.rb +15 -15
- data/rdoc-sources/FXStatusBar.rb +14 -14
- data/rdoc-sources/FXStatusLine.rb +7 -7
- data/rdoc-sources/FXStream.rb +20 -20
- data/rdoc-sources/FXSwitcher.rb +23 -23
- data/rdoc-sources/FXTGAIcon.rb +12 -12
- data/rdoc-sources/FXTGAImage.rb +5 -5
- data/rdoc-sources/FXTIFIcon.rb +13 -13
- data/rdoc-sources/FXTIFImage.rb +5 -5
- data/rdoc-sources/FXTabBar.rb +31 -31
- data/rdoc-sources/FXTabBook.rb +13 -13
- data/rdoc-sources/FXTabItem.rb +22 -22
- data/rdoc-sources/FXTable.rb +148 -148
- data/rdoc-sources/FXText.rb +91 -91
- data/rdoc-sources/FXTextField.rb +39 -39
- data/rdoc-sources/FXToggleButton.rb +32 -32
- data/rdoc-sources/FXToolBar.rb +25 -25
- data/rdoc-sources/FXToolBarGrip.rb +12 -12
- data/rdoc-sources/FXToolBarShell.rb +13 -13
- data/rdoc-sources/FXToolBarTab.rb +16 -16
- data/rdoc-sources/FXTopWindow.rb +18 -18
- data/rdoc-sources/FXTranslator.rb +1 -1
- data/rdoc-sources/FXTreeList.rb +66 -66
- data/rdoc-sources/FXTreeListBox.rb +20 -20
- data/rdoc-sources/FXTriStateButton.rb +23 -23
- data/rdoc-sources/FXVec2d.rb +1 -1
- data/rdoc-sources/FXVec2f.rb +1 -1
- data/rdoc-sources/FXVec3d.rb +1 -1
- data/rdoc-sources/FXVec3f.rb +1 -1
- data/rdoc-sources/FXVec4d.rb +1 -1
- data/rdoc-sources/FXVec4f.rb +1 -1
- data/rdoc-sources/FXVerticalFrame.rb +12 -12
- data/rdoc-sources/FXVisual.rb +19 -19
- data/rdoc-sources/FXWindow.rb +96 -96
- data/rdoc-sources/FXWizard.rb +9 -9
- data/rdoc-sources/FXXBMIcon.rb +7 -7
- data/rdoc-sources/FXXBMImage.rb +6 -6
- data/rdoc-sources/FXXPMIcon.rb +13 -13
- data/rdoc-sources/FXXPMImage.rb +5 -5
- data/rdoc-sources/Makefile +3 -3
- metadata +44 -31
- data/README +0 -39
- data/README.txt +0 -483
data/doap.rdf
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
<doap:Project>
|
8
8
|
<doap:name>FXRuby</doap:name>
|
9
9
|
<doap:shortname>FXRuby</doap:shortname>
|
10
|
-
<doap:homepage rdf:resource="http://
|
10
|
+
<doap:homepage rdf:resource="http://github.com/larskanis/fxruby"/>
|
11
11
|
<doap:old-homepage rdf:resource="http://fxruby.sourceforge.net"/>
|
12
12
|
<doap:created>2001-01-01</doap:created>
|
13
13
|
<doap:description>FXRuby is an extension module for Ruby that provides an interface to the FOX GUI toolkit.</doap:description>
|
@@ -77,8 +77,8 @@
|
|
77
77
|
<doap:release>
|
78
78
|
<doap:Version>
|
79
79
|
<doap:branch>fox16</doap:branch>
|
80
|
-
<doap:created>2012-
|
81
|
-
<doap:revision>1.
|
80
|
+
<doap:created>2012-03-08</doap:created>
|
81
|
+
<doap:revision>1.6.23</doap:revision>
|
82
82
|
</doap:Version>
|
83
83
|
</doap:release>
|
84
84
|
|
data/doap.rdf.erb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-15"?>
|
2
|
+
<rdf:RDF
|
3
|
+
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
4
|
+
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
5
|
+
xmlns:doap="http://usefulinc.com/ns/doap#"
|
6
|
+
xmlns:foaf="http://xmlns.com/foaf/0.1/">
|
7
|
+
<doap:Project>
|
8
|
+
<doap:name>FXRuby</doap:name>
|
9
|
+
<doap:shortname>FXRuby</doap:shortname>
|
10
|
+
<doap:homepage rdf:resource="http://github.com/larskanis/fxruby"/>
|
11
|
+
<doap:old-homepage rdf:resource="http://fxruby.sourceforge.net"/>
|
12
|
+
<doap:created>2001-01-01</doap:created>
|
13
|
+
<doap:description>FXRuby is an extension module for Ruby that provides an interface to the FOX GUI toolkit.</doap:description>
|
14
|
+
<doap:shortdesc>FXRuby is a Ruby interface to the FOX GUI toolkit.</doap:shortdesc>
|
15
|
+
<doap:wiki rdf:resource="http://fxruby.rubyforge.org/wiki/wiki.pl"/>
|
16
|
+
<doap:bug-database rdf:resource="http://rubyforge.org/tracker/?atid=1223&group_id=300&func=browse"/>
|
17
|
+
<doap:mailing-list rdf:resource="http://rubyforge.org/mailman/listinfo/fxruby-users"/>
|
18
|
+
<doap:screenshots rdf:resource="http://www.fxruby.org/doc/examples.html"/>
|
19
|
+
<doap:programming-language>Ruby</doap:programming-language>
|
20
|
+
<doap:license rdf:resource="http://usefulinc.com/doap/licenses/lgpl"/>
|
21
|
+
<doap:download-page rdf:resource="http://rubyforge.org/frs/?group_id=300"/>
|
22
|
+
|
23
|
+
<doap:maintainer>
|
24
|
+
<foaf:Person>
|
25
|
+
<foaf:name>Lyle Johnson</foaf:name>
|
26
|
+
<foaf:nick>lyle</foaf:nick>
|
27
|
+
<foaf:mbox_sha1sum>6a53ac5fe72eaa9e17d14207ed0bbdaa2fb8aed9</foaf:mbox_sha1sum>
|
28
|
+
<rdfs:seeAlso rdf:resource="http://lylejohnson.name/foaf.rdf"/>
|
29
|
+
</foaf:Person>
|
30
|
+
</doap:maintainer>
|
31
|
+
|
32
|
+
<doap:repository>
|
33
|
+
<doap:CVSRepository>
|
34
|
+
<doap:anon-root>:pserver:anonymous@rubyforge.org:/var/cvs/fxruby</doap:anon-root>
|
35
|
+
<doap:module>FXRuby</doap:module>
|
36
|
+
<doap:browse rdf:resource="http://rubyforge.org/cgi-bin/viewcvs/cgi/viewcvs.cgi/?cvsroot=fxruby"/>
|
37
|
+
</doap:CVSRepository>
|
38
|
+
</doap:repository>
|
39
|
+
|
40
|
+
<!-- Software Development :: Libraries :: Ruby Modules -->
|
41
|
+
<doap:category rdf:resource="http://freshmeat.net/browse/955/"/>
|
42
|
+
|
43
|
+
<!-- Software Development :: User Interfaces -->
|
44
|
+
<doap:category rdf:resource="http://freshmeat.net/browse/909/"/>
|
45
|
+
|
46
|
+
<!-- Software Development :: Widget Sets -->
|
47
|
+
<doap:category rdf:resource="http://freshmeat.net/browse/851/"/>
|
48
|
+
|
49
|
+
<!-- current fox release -->
|
50
|
+
<doap:release>
|
51
|
+
<doap:Version>
|
52
|
+
<doap:branch>fox</doap:branch>
|
53
|
+
<doap:created>2004-06-16</doap:created>
|
54
|
+
<doap:revision>1.0.29</doap:revision>
|
55
|
+
</doap:Version>
|
56
|
+
</doap:release>
|
57
|
+
|
58
|
+
<!-- current fox12 release -->
|
59
|
+
<doap:release>
|
60
|
+
<doap:Version>
|
61
|
+
<doap:branch>fox12</doap:branch>
|
62
|
+
<doap:created>2005-04-15</doap:created>
|
63
|
+
<doap:revision>1.2.6</doap:revision>
|
64
|
+
</doap:Version>
|
65
|
+
</doap:release>
|
66
|
+
|
67
|
+
<!-- current fox14 release -->
|
68
|
+
<doap:release>
|
69
|
+
<doap:Version>
|
70
|
+
<doap:branch>fox14</doap:branch>
|
71
|
+
<doap:created>2006-09-13</doap:created>
|
72
|
+
<doap:revision>1.4.7</doap:revision>
|
73
|
+
</doap:Version>
|
74
|
+
</doap:release>
|
75
|
+
|
76
|
+
<!-- current fox16 release -->
|
77
|
+
<doap:release>
|
78
|
+
<doap:Version>
|
79
|
+
<doap:branch>fox16</doap:branch>
|
80
|
+
<doap:created><%= Date.today %></doap:created>
|
81
|
+
<doap:revision><%= PKG_VERSION %></doap:revision>
|
82
|
+
</doap:Version>
|
83
|
+
</doap:release>
|
84
|
+
|
85
|
+
</doap:Project>
|
86
|
+
</rdf:RDF>
|
87
|
+
|
@@ -0,0 +1,356 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# Depends on Kou's RSS Parser module (http://raa.ruby-lang.org/list.rhtml?name=rss).
|
5
|
+
#
|
6
|
+
# Potential enhancements:
|
7
|
+
#
|
8
|
+
# - preference of whether the pictures are listed latest first, or
|
9
|
+
# oldest first.
|
10
|
+
# - option to always show the latest picture after a refresh
|
11
|
+
#
|
12
|
+
|
13
|
+
require 'fox16'
|
14
|
+
require 'open-uri'
|
15
|
+
|
16
|
+
begin
|
17
|
+
require 'rss/parser'
|
18
|
+
require 'rss/2.0'
|
19
|
+
rescue LoadError
|
20
|
+
require 'fox16/missingdep'
|
21
|
+
MSG = <<EOM
|
22
|
+
Sorry, this example depends on the RSS extension. Please
|
23
|
+
check the Ruby Application Archives for an appropriate
|
24
|
+
download site.
|
25
|
+
EOM
|
26
|
+
missingDependency(MSG)
|
27
|
+
end
|
28
|
+
|
29
|
+
include Fox
|
30
|
+
|
31
|
+
class WhatAQuietWindow < FXMainWindow
|
32
|
+
|
33
|
+
RSS_FEED_URL = "http://whytheluckystiff.net/quiet/quiet.xml"
|
34
|
+
DEFAULT_REFRESH_DELAY = 60 # in minutes
|
35
|
+
|
36
|
+
def initialize(app)
|
37
|
+
# Invoke base class initialize first
|
38
|
+
super(app, "What a Quiet Stiff", :opts => DECOR_ALL, :width => 850, :height => 600, :padLeft => 0, :padRight => 0)
|
39
|
+
|
40
|
+
# Icons for list items
|
41
|
+
File.open("icons/bluebullet14x14.gif", "rb") do |f|
|
42
|
+
bytes = f.read
|
43
|
+
@itemIcon = FXGIFIcon.new(getApp(), bytes)
|
44
|
+
end
|
45
|
+
File.open("icons/transpbullet14x14.gif", "rb") do |f|
|
46
|
+
bytes = f.read
|
47
|
+
@transpIcon = FXGIFIcon.new(getApp(), bytes)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Menubar
|
51
|
+
menuBar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
52
|
+
|
53
|
+
# File menu
|
54
|
+
fileMenu = FXMenuPane.new(self)
|
55
|
+
saveCmd = FXMenuCommand.new(fileMenu, "Save selected image...")
|
56
|
+
saveCmd.connect(SEL_COMMAND, method(:onCmdSave))
|
57
|
+
saveCmd.connect(SEL_UPDATE, method(:onUpdSave))
|
58
|
+
FXMenuCommand.new(fileMenu, "Preferences...").connect(SEL_COMMAND, method(:onCmdPreferences))
|
59
|
+
FXMenuCommand.new(fileMenu, "&Quit\tCtrl+Q").connect(SEL_COMMAND, method(:onQuit))
|
60
|
+
FXMenuTitle.new(menuBar, "&File", nil, fileMenu)
|
61
|
+
|
62
|
+
# Help menu
|
63
|
+
helpMenu = FXMenuPane.new(self)
|
64
|
+
FXMenuTitle.new(menuBar, "&Help", nil, helpMenu, LAYOUT_RIGHT)
|
65
|
+
aboutCmd = FXMenuCommand.new(helpMenu, "&About...")
|
66
|
+
aboutCmd.connect(SEL_COMMAND) do
|
67
|
+
FXMessageBox.information(self, MBOX_OK, "About This Program",
|
68
|
+
"What a Quiet Stiff\nA Sliding Surface for Found Imagery\nCourtesy of http://whytheluckystiff.net")
|
69
|
+
end
|
70
|
+
|
71
|
+
# Respond to window close
|
72
|
+
self.connect(SEL_CLOSE, method(:onQuit))
|
73
|
+
|
74
|
+
# Main contents area is split left-to-right.
|
75
|
+
splitter = FXSplitter.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
76
|
+
|
77
|
+
# Put the list in a sunken frame
|
78
|
+
listFrame = FXVerticalFrame.new(splitter,
|
79
|
+
FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,
|
80
|
+
:padding => 00)
|
81
|
+
|
82
|
+
# List of items appears on the left.
|
83
|
+
@itemList = FXList.new(listFrame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
84
|
+
@itemList.numVisible = 12
|
85
|
+
@itemList.connect(SEL_COMMAND) do |sender, sel, itemIndex|
|
86
|
+
@showLinkedImage = false
|
87
|
+
getApp().beginWaitCursor do
|
88
|
+
setImage(@itemList.getItemData(itemIndex))
|
89
|
+
@itemList.setItemIcon(itemIndex, @transpIcon)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sunken border for image widget
|
94
|
+
imagebox = FXHorizontalFrame.new(splitter,
|
95
|
+
FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,
|
96
|
+
:padding => 0)
|
97
|
+
|
98
|
+
# Make image widget
|
99
|
+
@imageview = FXImageView.new(imagebox, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
100
|
+
@imageview.enable
|
101
|
+
@imageview.connect(SEL_LEFTBUTTONRELEASE) { toggleImage }
|
102
|
+
|
103
|
+
# Cache previously viewed images in a Hash
|
104
|
+
@cache = {}
|
105
|
+
@showLinkedImage = false
|
106
|
+
|
107
|
+
# Start out with the current feed's contents.
|
108
|
+
refreshList
|
109
|
+
end
|
110
|
+
|
111
|
+
# Return true if an item is selected, false otherwise.
|
112
|
+
def itemSelected?
|
113
|
+
begin
|
114
|
+
@itemList.itemSelected?(@itemList.currentItem)
|
115
|
+
rescue IndexError
|
116
|
+
false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# Enable or disable the "Save Image" command, depending on
|
122
|
+
# whether or not any items are selected.
|
123
|
+
#
|
124
|
+
def onUpdSave(sender, sel, ptr)
|
125
|
+
if itemSelected?
|
126
|
+
sender.handle(self, FXSEL(SEL_COMMAND, ID_ENABLE), nil)
|
127
|
+
else
|
128
|
+
sender.handle(self, FXSEL(SEL_COMMAND, ID_DISABLE), nil)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Save the currently selected image to a file.
|
133
|
+
def onCmdSave(sender, sel, ptr)
|
134
|
+
saveDialog = FXFileDialog.new(self, "Save Image")
|
135
|
+
saveDialog.filename = @itemList.getItemText(@itemList.currentItem)
|
136
|
+
if saveDialog.execute != 0
|
137
|
+
if File.exists? saveDialog.filename
|
138
|
+
if MBOX_CLICKED_NO == FXMessageBox.question(self, MBOX_YES_NO,
|
139
|
+
"Overwrite Image", "Overwrite existing image?")
|
140
|
+
return 1
|
141
|
+
end
|
142
|
+
end
|
143
|
+
getApp().beginWaitCursor do
|
144
|
+
FXFileStream.open(saveDialog.filename, FXStreamSave) do |stream|
|
145
|
+
@imageview.image.restore
|
146
|
+
@imageview.image.savePixels(stream)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Display the Preferences dialog box.
|
153
|
+
def onCmdPreferences(sender, sel, ptr)
|
154
|
+
refreshDelayTarget = FXDataTarget.new(@refreshDelay)
|
155
|
+
|
156
|
+
prefsDialog = FXDialogBox.new(self, "Preferences", :padding => 2)
|
157
|
+
|
158
|
+
buttons = FXHorizontalFrame.new(prefsDialog, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
|
159
|
+
FXFrame.new(buttons, LAYOUT_FILL_X)
|
160
|
+
FXButton.new(buttons, "Cancel", nil, prefsDialog, FXDialogBox::ID_CANCEL,
|
161
|
+
LAYOUT_SIDE_RIGHT|LAYOUT_CENTER_Y|FRAME_RAISED|FRAME_THICK,
|
162
|
+
:padLeft => 20, :padRight => 20, :padTop => 4, :padBottom => 4)
|
163
|
+
FXButton.new(buttons, "OK", nil, prefsDialog, FXDialogBox::ID_ACCEPT,
|
164
|
+
LAYOUT_SIDE_RIGHT|LAYOUT_CENTER_Y|FRAME_RAISED|FRAME_THICK,
|
165
|
+
:padLeft => 30, :padRight => 30, :padTop => 4, :padBottom => 4)
|
166
|
+
|
167
|
+
FXHorizontalSeparator.new(prefsDialog, SEPARATOR_GROOVE|LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
|
168
|
+
|
169
|
+
contents = FXMatrix.new(prefsDialog, 2, MATRIX_BY_COLUMNS|LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
170
|
+
FXLabel.new(contents, "Refresh Delay (minutes):", nil, LAYOUT_CENTER_Y)
|
171
|
+
FXTextField.new(contents, 5, refreshDelayTarget, FXDataTarget::ID_VALUE,
|
172
|
+
LAYOUT_CENTER_Y|FRAME_SUNKEN|FRAME_THICK|JUSTIFY_RIGHT)
|
173
|
+
|
174
|
+
if prefsDialog.execute != 0
|
175
|
+
@refreshDelay = refreshDelayTarget.value
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
#
|
180
|
+
# Given an RSS object, populate the list of images with one
|
181
|
+
# per item in the RSS.
|
182
|
+
#
|
183
|
+
def populateItemList(rss)
|
184
|
+
@itemList.clearItems
|
185
|
+
liveItems = {}
|
186
|
+
rss.items.each do |rssItem|
|
187
|
+
srcURL = getSourceURL(rssItem)
|
188
|
+
linkURL = getLinkURL(rssItem)
|
189
|
+
itemIcon = (@cache.key?(srcURL) || @cache.key?(linkURL)) ? @transpIcon : @itemIcon
|
190
|
+
@itemList.appendItem(rssItem.title, itemIcon, rssItem)
|
191
|
+
liveItems[srcURL] = 1 if @cache.key?(srcURL)
|
192
|
+
liveItems[linkURL] = 1 if @cache.key?(linkURL)
|
193
|
+
end
|
194
|
+
@cache.delete_if { |key, value| !liveItems.key?(key) }
|
195
|
+
end
|
196
|
+
|
197
|
+
def toggleImage
|
198
|
+
@showLinkedImage = !@showLinkedImage
|
199
|
+
if itemSelected?
|
200
|
+
itemIndex = @itemList.currentItem
|
201
|
+
getApp().beginWaitCursor do
|
202
|
+
setImage(@itemList.getItemData(itemIndex))
|
203
|
+
@itemList.setItemIcon(itemIndex, @transpIcon)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def setImage(rssItem)
|
209
|
+
url = getImageURL(rssItem)
|
210
|
+
img = @cache[url]
|
211
|
+
if img.nil?
|
212
|
+
img = makeImage(url)
|
213
|
+
img.create
|
214
|
+
@cache[url] = img
|
215
|
+
end
|
216
|
+
@imageview.image = img
|
217
|
+
end
|
218
|
+
|
219
|
+
def getRSSFeed(url)
|
220
|
+
rss = nil
|
221
|
+
open(url) do |f|
|
222
|
+
doc = f.read
|
223
|
+
begin
|
224
|
+
rss = RSS::Parser.parse(doc)
|
225
|
+
rescue RSS::InvalidRSSError
|
226
|
+
rss = RSS::Parser.parse(doc, false)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
rss
|
230
|
+
end
|
231
|
+
|
232
|
+
# Return the URL listed in the src tag of the description's HTML text.
|
233
|
+
def getSourceURL(rssItem)
|
234
|
+
rssItem.description =~ /src="(.*?)"/
|
235
|
+
return $1
|
236
|
+
end
|
237
|
+
|
238
|
+
# Return the URL listed in the href tag of the description's HTML text.
|
239
|
+
def getLinkURL(rssItem)
|
240
|
+
rssItem.description =~ /href="(.*?)"/
|
241
|
+
return $1
|
242
|
+
end
|
243
|
+
|
244
|
+
# Return the appropriate URL given the current settings.
|
245
|
+
def getImageURL(rssItem)
|
246
|
+
@showLinkedImage ? getLinkURL(rssItem) : getSourceURL(rssItem)
|
247
|
+
end
|
248
|
+
|
249
|
+
def getImageData(url)
|
250
|
+
bytes = nil
|
251
|
+
open(url, "rb") do |f|
|
252
|
+
bytes = f.read
|
253
|
+
end
|
254
|
+
bytes
|
255
|
+
end
|
256
|
+
|
257
|
+
# This is a little weak...
|
258
|
+
def makeImage(url)
|
259
|
+
bytes = getImageData(url)
|
260
|
+
extension = url.split('.').last.upcase
|
261
|
+
case extension
|
262
|
+
when "GIF"
|
263
|
+
FXGIFImage.new(getApp(), bytes)
|
264
|
+
when "JPG"
|
265
|
+
FXJPGImage.new(getApp(), bytes)
|
266
|
+
when "PNG"
|
267
|
+
FXPNGImage.new(getApp(), bytes)
|
268
|
+
else
|
269
|
+
raise "Unrecognized file extension for: #{url}"
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def resizeItemList
|
274
|
+
maxItemSize = 0
|
275
|
+
@itemList.each do |listItem|
|
276
|
+
itemSize = @itemList.font.getTextWidth(listItem.text)
|
277
|
+
maxItemSize = [maxItemSize, itemSize].max
|
278
|
+
end
|
279
|
+
@itemList.parent.width = maxItemSize
|
280
|
+
end
|
281
|
+
|
282
|
+
def refreshList
|
283
|
+
# Grab the latest RSS feed
|
284
|
+
@rss = getRSSFeed(RSS_FEED_URL)
|
285
|
+
|
286
|
+
# Repopulate the list with this set of items
|
287
|
+
populateItemList(@rss)
|
288
|
+
end
|
289
|
+
|
290
|
+
def onRefreshList(sender, sel, ptr)
|
291
|
+
# Refresh, then re-register the timeout
|
292
|
+
getApp().beginWaitCursor { refreshList }
|
293
|
+
getApp().addTimeout(1000*60*@refreshDelay, method(:onRefreshList))
|
294
|
+
end
|
295
|
+
|
296
|
+
def onQuit(sender, sel, ptr)
|
297
|
+
writeRegistry
|
298
|
+
getApp().exit(0)
|
299
|
+
end
|
300
|
+
|
301
|
+
def readRegistry
|
302
|
+
xx = getApp().reg().readIntEntry("SETTINGS", "x", 0)
|
303
|
+
yy = getApp().reg().readIntEntry("SETTINGS", "y", 0)
|
304
|
+
ww = getApp().reg().readIntEntry("SETTINGS", "width", 850)
|
305
|
+
hh = getApp().reg().readIntEntry("SETTINGS", "height", 600)
|
306
|
+
@refreshDelay = getApp().reg().readIntEntry("SETTINGS", "refreshDelay", DEFAULT_REFRESH_DELAY)
|
307
|
+
end
|
308
|
+
|
309
|
+
def writeRegistry
|
310
|
+
getApp().reg().writeIntEntry("SETTINGS", "x", x)
|
311
|
+
getApp().reg().writeIntEntry("SETTINGS", "y", y)
|
312
|
+
getApp().reg().writeIntEntry("SETTINGS", "width", width)
|
313
|
+
getApp().reg().writeIntEntry("SETTINGS", "height", height)
|
314
|
+
getApp().reg().writeIntEntry("SETTINGS", "refreshDelay", @refreshDelay)
|
315
|
+
end
|
316
|
+
|
317
|
+
def create
|
318
|
+
# Do base class create first
|
319
|
+
super
|
320
|
+
|
321
|
+
readRegistry
|
322
|
+
|
323
|
+
@itemIcon.create
|
324
|
+
@transpIcon.create
|
325
|
+
|
326
|
+
# Make the item list wide enough to show the longest item
|
327
|
+
resizeItemList
|
328
|
+
|
329
|
+
# Resize main window
|
330
|
+
# Resize main window client area to fit image size
|
331
|
+
# resize(@imageview.contentWidth, @imageview.contentHeight)
|
332
|
+
|
333
|
+
# Now show it
|
334
|
+
show(PLACEMENT_SCREEN)
|
335
|
+
|
336
|
+
# Start the updates timer
|
337
|
+
getApp().addTimeout(1000*60*@refreshDelay, method(:onRefreshList))
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
if __FILE__ == $0
|
342
|
+
# Make application
|
343
|
+
application = FXApp.new("WhatAQuietWindow", "FXRuby")
|
344
|
+
|
345
|
+
# Make window
|
346
|
+
window = WhatAQuietWindow.new(application)
|
347
|
+
|
348
|
+
# Handle interrupts to terminate program gracefully
|
349
|
+
application.addSignal("SIGINT", window.method(:onQuit))
|
350
|
+
|
351
|
+
# Create it
|
352
|
+
application.create
|
353
|
+
|
354
|
+
# Run
|
355
|
+
application.run
|
356
|
+
end
|