fxri 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/fxri ADDED
@@ -0,0 +1,292 @@
1
+ #!/bin/env ruby
2
+
3
+ # Load FXRuby: try gem, then Fox 1.2, then Fox 1.0
4
+ begin
5
+ # try fxruby gem
6
+ require 'rubygems'
7
+ require_gem 'fxruby', '>= 1.1.0'
8
+ require 'fox12'
9
+ require 'fox12/colors'
10
+ FOXVERSION="1.2"
11
+ include Fox
12
+ rescue LoadError
13
+ # no gem? try fox12 direct.
14
+ begin
15
+ require "fox12"
16
+ require "fox12/colors"
17
+ FOXVERSION="1.2"
18
+ include Fox
19
+ rescue LoadError
20
+ # no gem, no fox12? try fox 1.0
21
+ require "fox"
22
+ require "fox/colors"
23
+ # grep for FOXVERSION to find all code that depends on this
24
+ FOXVERSION="1.0"
25
+ include Fox
26
+ FXMenuBar = FXMenubar
27
+ FXToolTip = FXTooltip
28
+ FXStatusBar = FXStatusbar
29
+ end
30
+ end
31
+
32
+ require 'thread'
33
+
34
+ require 'lib/RiManager'
35
+ require 'lib/Recursive_Open_Struct'
36
+ require 'lib/Globals'
37
+ require 'lib/Packet_List'
38
+ require 'lib/Packet_Item'
39
+ require 'lib/Empty_Text_Field_Handler'
40
+ require 'lib/Icon_Loader'
41
+ require 'lib/Search_Engine'
42
+ require 'lib/FoxDisplayer'
43
+ require 'lib/FoxTextFormatter'
44
+ require 'lib/fxirb'
45
+
46
+ # Responsible for application initialization
47
+ class Main_Window < FXMainWindow
48
+
49
+ # Initializes the XDCC-application.
50
+ def initialize(app)
51
+ super(app, $cfg.app.name, nil, nil, DECOR_ALL, 0, 0, $cfg.app.width, $cfg.app.height)
52
+ set_default_font
53
+ # load icons
54
+ icon_loader = Icon_Loader.new(FXApp::instance)
55
+ icon_loader.cfg_to_icons($cfg.icons)
56
+
57
+ @gui = Recursive_Open_Struct.new
58
+ @gui.main = self
59
+ @data = Recursive_Open_Struct.new
60
+ @data.gui_mutex = Mutex.new
61
+
62
+ build(self)
63
+ FXToolTip.new(FXApp::instance, TOOLTIP_NORMAL)
64
+
65
+ @gui.close
66
+ create_data
67
+
68
+ @data.close
69
+
70
+ @search_engine = Search_Engine.new(@gui, @data)
71
+
72
+ # show init message
73
+ @data.displayer.display_information($cfg.text.help)
74
+ end
75
+
76
+ # Automatically called when the Fox application is created
77
+ def create
78
+ super
79
+ show(PLACEMENT_SCREEN)
80
+ # load items
81
+ load_items
82
+ @search_engine.update_search_status_text
83
+ end
84
+
85
+ def create_data
86
+ @data.displayer = FoxDisplayer.new(@gui.text)
87
+ @data.ri_manager = RiManager.new(@data.displayer)
88
+ @data.items = Array.new
89
+ @desc = nil
90
+ end
91
+
92
+
93
+ # Set the default font to the first font of $cfg.app.font.name that is available on this system.
94
+ def set_default_font
95
+ @font = load_font($cfg.app.font.name)
96
+ FXApp::instance.normalFont = @font if @font
97
+ end
98
+
99
+ # Returns the first font of the given array of font names that can be loaded, or nil.
100
+ def load_font(font_array)
101
+ # load default font
102
+ font = nil
103
+ font_array.detect do |name|
104
+ next if FXFont.listFonts(name).empty?
105
+ font = FXFont.new(FXApp::instance, name, $cfg.app.font.size)
106
+ end
107
+ font
108
+ end
109
+
110
+ # build gui
111
+ def build(parent)
112
+ FXSplitter.new(parent, SPLITTER_TRACKING|LAYOUT_FILL_X|LAYOUT_FILL_Y) do |base|
113
+ FXVerticalFrame.new(base, LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,$cfg.packet_list_width,0, DEFAULT_SPACING, 0) do |search_frame|
114
+
115
+ @gui.search_field = FXTextField.new(search_frame, 1, nil, 0, TEXTFIELD_NORMAL|LAYOUT_FILL_X|FRAME_SUNKEN)
116
+ Empty_Text_Field_Handler.new(@gui.search_field, $cfg.text.search_field)
117
+ @gui.search_field.connect(SEL_CHANGED) do |*args|
118
+ on_search
119
+ end
120
+
121
+
122
+ FXVerticalFrame.new(search_frame, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0,0,0) do |list_frame|
123
+ @gui.packet_list = Packet_List.new(@data, list_frame, nil, 0, HSCROLLER_NEVER|VSCROLLER_ALWAYS|TREELIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y) do |packet_list|
124
+ packet_list.add_header($cfg.text.method_name, $cfg.packet_list_width) { |x| make_sortable(x) }
125
+ end
126
+ end
127
+
128
+ @gui.search_label = FXLabel.new(search_frame, "", nil, LAYOUT_FILL_X|LABEL_NORMAL|JUSTIFY_RIGHT, 0,0,0,0, 0,0,0,0)
129
+
130
+ @gui.packet_list.connect(SEL_SELECTED) do |sender, sel, data|
131
+ item = sender.getItem(data).packet_item
132
+ show_info(item.data)
133
+ end
134
+ end
135
+
136
+
137
+ FXSplitter.new(base, SPLITTER_TRACKING|LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_VERTICAL) do |split|
138
+ FXHorizontalFrame.new(split, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0,0,0) do |right|
139
+ @gui.text = FXText.new(right, nil, 0, TEXT_READONLY|TEXT_WORDWRAP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
140
+ end
141
+
142
+ FXHorizontalFrame.new(split, FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0,0,0) do |irb_frame|
143
+ @irb_frame = irb_frame
144
+ @gui.irb = FXIrb.init(irb_frame, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP|TEXT_SHOWACTIVE)
145
+ @gui.irb.setFont(@font) if @font
146
+ end
147
+ split.setSplit(0, $cfg.irb_height)
148
+ end
149
+ font = load_font($cfg.ri_font)
150
+ @gui.text.font = font if font
151
+ font.create
152
+ @gui.text_width = font.fontWidth
153
+
154
+ @gui.text.connect(SEL_CONFIGURE) do
155
+ on_show if @desc
156
+ end
157
+
158
+ # construct hilite styles
159
+ @gui.text.styled = true
160
+ @gui.text.hiliteStyles = create_styles
161
+
162
+ end
163
+ end
164
+
165
+ def create_empty_style
166
+ hs = FXHiliteStyle.new
167
+ hs.activeBackColor = FXColor::White
168
+ hs.hiliteBackColor = FXColor::DarkBlue
169
+ hs.normalBackColor = FXColor::White
170
+ hs.normalForeColor = FXColor::Black
171
+ hs.selectBackColor = FXColor::DarkBlue
172
+ hs.selectForeColor = FXColor::White
173
+ hs.style = 0
174
+ hs
175
+ end
176
+
177
+ def create_styles
178
+ styles = Array.new
179
+
180
+ #normal
181
+ styles.push create_empty_style
182
+
183
+ # bold
184
+ hs = create_empty_style
185
+ hs.style = FXText::STYLE_BOLD
186
+ styles.push hs
187
+
188
+ # H1
189
+ hs = create_empty_style
190
+ hs.style = FXText::STYLE_UNDERLINE|FXText::STYLE_BOLD
191
+ hs.normalForeColor = FXColor::ForestGreen
192
+ styles.push hs
193
+
194
+ # H2
195
+ hs = create_empty_style
196
+ hs.style = FXText::STYLE_UNDERLINE
197
+ hs.normalForeColor = FXColor::ForestGreen
198
+ styles.push hs
199
+
200
+ # H3
201
+ hs = create_empty_style
202
+ hs.normalForeColor = FXColor::ForestGreen
203
+ styles.push hs
204
+
205
+ # teletype
206
+ hs = create_empty_style
207
+ hs.normalForeColor = FXColor::DarkCyan
208
+ styles.push hs
209
+
210
+ # code
211
+ hs = create_empty_style
212
+ hs.activeBackColor = FXColor::LightGrey
213
+ hs.normalForeColor = FXColor::DarkGreen
214
+ hs.style = FXText::STYLE_UNDERLINE|FXText::STYLE_BOLD
215
+ styles.push hs
216
+
217
+ # emphasis
218
+ hs = create_empty_style
219
+ hs.normalForeColor = FXColor::DarkCyan
220
+ styles.push hs
221
+
222
+ # class
223
+ hs = create_empty_style
224
+ hs.style = FXText::STYLE_BOLD
225
+ hs.normalForeColor = FXColor::Blue
226
+ styles.push hs
227
+
228
+ styles
229
+ end
230
+
231
+
232
+ # loads all ri items
233
+ def load_items
234
+ @data.ri_manager.all_names.each do |name|
235
+ icon = case name.type
236
+ when NameDescriptor::CLASS
237
+ $cfg.icons.klass
238
+ when NameDescriptor::INSTANCE_METHOD
239
+ $cfg.icons.instance_method
240
+ when NameDescriptor::CLASS_METHOD
241
+ $cfg.icons.class_method
242
+ end
243
+ item = Packet_Item.new(@gui.packet_list, icon, name.to_s)
244
+ item.data = name
245
+ @data.items.push item
246
+ end
247
+ # quick hack to sort in right order :-)
248
+ @gui.packet_list.on_cmd_header(0)
249
+ @gui.packet_list.on_cmd_header(0)
250
+ @gui.packet_list.update_header_width
251
+ recalc
252
+ end
253
+
254
+ def on_search
255
+ @search_engine.on_search
256
+ end
257
+
258
+ def on_show
259
+ begin
260
+ w = @gui.text.width / @gui.text_width - 3
261
+ w = [w, $cfg.minimum_letters_per_line].max
262
+ @data.ri_manager.show(@desc, w)
263
+ rescue RiError => e
264
+ #puts desc
265
+ end
266
+ end
267
+
268
+ def show_info(desc)
269
+ @desc = desc
270
+ on_show
271
+ end
272
+
273
+
274
+ # x beeing the name of the ri doc, like "Set#delete"
275
+ # This creates a sortable representation. First class, then class methods, then instance.
276
+ def make_sortable(x)
277
+ [ x.downcase.gsub("::", " 1 ").gsub("#", " 2 "),
278
+ x.downcase,
279
+ x]
280
+ end
281
+
282
+ end
283
+
284
+ Thread.abort_on_exception= true
285
+
286
+ # move to directory of this file, so that icons can load correctly.
287
+ Dir.chdir(File.dirname(File.expand_path(__FILE__)))
288
+
289
+ $app = FXApp.new($cfg.app.name, $cfg.app.name)
290
+ $main_window = Main_Window.new($app)
291
+ $app.create
292
+ $app.run
data/fxri.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ #!/bin/env ruby
2
+ require 'rubygems'
3
+
4
+ spec = Gem::Specification.new do |s|
5
+ s.name = "fxri"
6
+ s.add_dependency('fxruby', '>= 1.2.0')
7
+ s.version = "0.1.0"
8
+ s.date = "2005-02-20"
9
+ s.summary = "Graphical interface to the RI documentation, with search engine."
10
+ s.require_paths = ["lib"]
11
+ s.email = "martin.ankerl@gmail.com"
12
+ s.homepage = "http://fxri.rubyforge.org/"
13
+ s.rubyforge_project = "fxri"
14
+ s.description = "FxRi is an FXRuby interface to the RI documentation, with a search engine that allows for search-on-typing."
15
+ s.has_rdoc = false
16
+ s.files = Dir.glob("**/*")
17
+ s.bindir = "."
18
+ s.executables = ["fxri"]
19
+ end
20
+
21
+ if __FILE__ == $0
22
+ Gem.manage_gems
23
+ Gem::Builder.new(spec).build
24
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2004, 2005 Martin Ankerl
2
+ # Shows a grey text in an FXTextField if the user did not enter any input. This is a nice way to
3
+ # give the user more information about what to enter into a text field, without the need of additional
4
+ # space in the GUI.
5
+ class Empty_Text_Field_Handler
6
+
7
+ # Create a new handler for the specified textfield, with the given text. From now on you have to use the
8
+ # created object to get and set text, not the textfield or this handler would come out of sync
9
+ def initialize(textField, myText)
10
+ @textField = textField
11
+ @myText = myText
12
+ @isEmpty = true
13
+ onTextFieldFocusOut
14
+ # create connections
15
+ @textField.connect(SEL_FOCUSIN, method(:onTextFieldFocusIn))
16
+ @textField.connect(SEL_FOCUSOUT, method(:onTextFieldFocusOut))
17
+ end
18
+
19
+ # Check if textfield is empty (no user input).
20
+ def empty?
21
+ @isEmpty
22
+ end
23
+
24
+ # Set new text for the textfield
25
+ def text=(newText)
26
+ onTextFieldFocusIn
27
+ @textField.text = newText.to_s
28
+ onTextFieldFocusOut
29
+ end
30
+
31
+ # Get the textfield's text, if the user has entered something.
32
+ def text
33
+ if empty? && !@inside
34
+ ""
35
+ else
36
+ @textField.text
37
+ end
38
+ end
39
+
40
+ # Set focus to the textfield.
41
+ def setFocus
42
+ @textField.setFocus
43
+ end
44
+
45
+ private
46
+
47
+ def onTextFieldFocusIn(*args)
48
+ @inside = true
49
+ return if !@isEmpty
50
+ @textField.textColor = FXColor::Black
51
+ @textField.text = ""
52
+ end
53
+
54
+ def onTextFieldFocusOut(*args)
55
+ @inside = false
56
+ @textField.killSelection
57
+ @isEmpty = @textField.text == ""
58
+ return if !@isEmpty
59
+ @textField.textColor = FXColor::DarkGrey
60
+ @textField.text = @myText
61
+ @isEmpty = true
62
+ end
63
+ end
@@ -0,0 +1,148 @@
1
+ class FoxDisplayer
2
+ attr_accessor :reader
3
+
4
+ def initialize(text_field)
5
+ @text_field = text_field
6
+ @formatter = FoxTextFormatter.new(70, "") do |arg, style|
7
+ startpos = @str.size
8
+ @str << arg
9
+ @formats.push [startpos, arg.size, style]
10
+ end
11
+ @reader = nil
12
+ end
13
+
14
+ def width=(newWidth)
15
+ @formatter.width = newWidth
16
+ end
17
+
18
+ def no_info_available
19
+ @text_field.text="nothing here, move on!"
20
+ end
21
+
22
+ def init_text
23
+ @str = ""
24
+ @formats = Array.new
25
+ end
26
+
27
+ # Sets a new text, and all styles
28
+ def set_text
29
+ @text_field.text = @str
30
+ @formats.each do |start, n, style|
31
+ case style
32
+ when FoxTextFormatter::STYLE_BOLD
33
+ @text_field.changeStyle(start, n, 2)
34
+ when FoxTextFormatter::STYLE_H1
35
+ @text_field.changeStyle(start, n, 3)
36
+ when FoxTextFormatter::STYLE_H2
37
+ @text_field.changeStyle(start, n, 4)
38
+ when FoxTextFormatter::STYLE_H3
39
+ @text_field.changeStyle(start, n, 5)
40
+ when FoxTextFormatter::STYLE_TELETYPE
41
+ @text_field.changeStyle(start, n, 6)
42
+ when FoxTextFormatter::STYLE_CODE
43
+ @text_field.changeStyle(start, n, 7)
44
+ when FoxTextFormatter::STYLE_EMPHASIS
45
+ @text_field.changeStyle(start, n, 8)
46
+ when FoxTextFormatter::STYLE_CLASS
47
+ @text_field.changeStyle(start, n, 9)
48
+ else
49
+ @text_field.changeStyle(start, n, 1)
50
+ end
51
+
52
+ end
53
+ end
54
+
55
+ # Display method information
56
+ def display_method_info(method)
57
+ init_text
58
+ @formatter.draw_line(method.full_name)
59
+ @formatter.display_params(method)
60
+ @formatter.draw_line
61
+ display_flow(method.comment)
62
+
63
+ if method.aliases && !method.aliases.empty?
64
+ @formatter.blankline
65
+ aka = "(also known as "
66
+ aka << method.aliases.map {|a| a.name }.join(", ")
67
+ aka << ")"
68
+ @formatter.wrap(aka)
69
+ end
70
+ set_text
71
+ end
72
+
73
+ def display_information(message)
74
+ init_text
75
+ display_flow(message)
76
+ set_text
77
+ end
78
+
79
+ def display_class_info(klass)
80
+ init_text
81
+ superclass = klass.superclass_string
82
+ if superclass
83
+ superclass = " < " + superclass
84
+ else
85
+ superclass = ""
86
+ end
87
+ @formatter.draw_line(klass.display_name + ": " + klass.full_name + superclass)
88
+ display_flow(klass.comment)
89
+ @formatter.draw_line
90
+
91
+ unless klass.includes.empty?
92
+ @formatter.blankline
93
+ @formatter.display_heading("Includes:", 2, "")
94
+ incs = []
95
+ klass.includes.each do |inc|
96
+ inc_desc = @reader.find_class_by_name(inc.name)
97
+ if inc_desc
98
+ str = inc.name + "("
99
+ str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
100
+ str << ")"
101
+ incs << str
102
+ else
103
+ incs << inc.name
104
+ end
105
+ end
106
+ @formatter.wrap(incs.sort.join(', '))
107
+ end
108
+
109
+ unless klass.constants.empty?
110
+ @formatter.blankline
111
+ @formatter.display_heading("Constants:", 2, "")
112
+ len = 0
113
+ klass.constants.each { |c| len = c.name.length if c.name.length > len }
114
+ len += 2
115
+ klass.constants.each do |c|
116
+ @formatter.wrap(c.value, @formatter.indent+((c.name+":").ljust(len)))
117
+ end
118
+ end
119
+
120
+ unless klass.class_methods.empty?
121
+ @formatter.blankline
122
+ @formatter.display_heading("Class methods:", 2, "")
123
+ @formatter.wrap(klass.class_methods.map{|m| m.name}.sort.join(', '))
124
+ end
125
+
126
+ unless klass.instance_methods.empty?
127
+ @formatter.blankline
128
+ @formatter.display_heading("Instance methods:", 2, "")
129
+ @formatter.wrap(klass.instance_methods.map{|m| m.name}.sort.join(', '))
130
+ end
131
+
132
+ unless klass.attributes.empty?
133
+ @formatter.blankline
134
+ @formatter.wrap("Attributes:", "")
135
+ @formatter.wrap(klass.attributes.map{|a| a.name}.sort.join(', '))
136
+ end
137
+
138
+ set_text
139
+ end
140
+
141
+ def display_flow(flow)
142
+ if !flow || flow.empty?
143
+ @formatter.wrap("(no description...)\n")
144
+ else
145
+ @formatter.display_flow(flow)
146
+ end
147
+ end
148
+ end