fxri 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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