ruber 0.0.5 → 0.0.7

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.
Files changed (83) hide show
  1. data/CHANGES +25 -0
  2. data/bin/ruber +0 -0
  3. data/data/share/apps/ruber/ruberui.rc +15 -1
  4. data/data/share/icons/{ruber.png → ruber-old.pgn} +0 -0
  5. data/lib/ruber/application/application.rb +216 -73
  6. data/lib/ruber/application/plugin.yaml +2 -2
  7. data/lib/ruber/document_project.rb +25 -5
  8. data/lib/ruber/documents/document_list.rb +11 -15
  9. data/lib/ruber/editor/document.rb +106 -50
  10. data/lib/ruber/editor/editor_view.rb +4 -2
  11. data/lib/ruber/external_program_plugin.rb +8 -0
  12. data/lib/ruber/kde_config_option_backend.rb +12 -4
  13. data/lib/ruber/kde_sugar.rb +35 -1
  14. data/lib/ruber/main_window/choose_plugins_dlg.rb +10 -10
  15. data/lib/ruber/main_window/hint_solver.rb +263 -0
  16. data/lib/ruber/main_window/main_window.rb +462 -206
  17. data/lib/ruber/main_window/main_window_actions.rb +228 -62
  18. data/lib/ruber/main_window/main_window_internal.rb +169 -115
  19. data/lib/ruber/main_window/plugin.yaml +13 -3
  20. data/lib/ruber/main_window/save_modified_files_dlg.rb +1 -1
  21. data/lib/ruber/main_window/ui/choose_plugins_widget.rb +1 -1
  22. data/lib/ruber/main_window/ui/main_window_settings_widget.rb +1 -1
  23. data/lib/ruber/main_window/ui/new_project_widget.rb +1 -1
  24. data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +1 -1
  25. data/lib/ruber/main_window/ui/output_color_widget.rb +1 -1
  26. data/lib/ruber/main_window/ui/workspace_settings_widget.rb +51 -0
  27. data/lib/ruber/main_window/ui/workspace_settings_widget.ui +28 -0
  28. data/lib/ruber/main_window/view_manager.rb +418 -0
  29. data/lib/ruber/main_window/workspace.png +0 -0
  30. data/lib/ruber/output_widget.rb +43 -37
  31. data/lib/ruber/pane.rb +621 -0
  32. data/lib/ruber/plugin_specification_reader.rb +8 -1
  33. data/lib/ruber/projects/project_files_list.rb +6 -0
  34. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +1 -1
  35. data/lib/ruber/projects/ui/project_files_widget.rb +1 -1
  36. data/lib/ruber/qt_sugar.rb +94 -4
  37. data/lib/ruber/utils.rb +16 -7
  38. data/lib/ruber/version.rb +2 -2
  39. data/plugins/autosave/autosave.rb +62 -1
  40. data/plugins/autosave/plugin.yaml +1 -0
  41. data/plugins/autosave/ui/autosave_config_widget.rb +37 -14
  42. data/plugins/autosave/ui/autosave_config_widget.ui +62 -12
  43. data/plugins/find_in_files/find_in_files_widgets.rb +1 -3
  44. data/plugins/find_in_files/ui/config_widget.rb +1 -1
  45. data/plugins/find_in_files/ui/find_in_files_widget.rb +1 -1
  46. data/plugins/rake/plugin.yaml +1 -1
  47. data/plugins/rake/ui/add_quick_task_widget.rb +1 -1
  48. data/plugins/rake/ui/choose_task_widget.rb +1 -1
  49. data/plugins/rake/ui/config_widget.rb +1 -1
  50. data/plugins/rake/ui/project_widget.rb +1 -1
  51. data/plugins/rspec/rspec.rb +14 -22
  52. data/plugins/rspec/ruber_rspec_formatter.rb +4 -1
  53. data/plugins/rspec/ui/rspec_project_widget.rb +1 -1
  54. data/plugins/ruby_development/plugin.yaml +7 -2
  55. data/plugins/ruby_development/ruby_development.rb +134 -13
  56. data/plugins/ruby_development/ui/config_widget.rb +66 -0
  57. data/plugins/ruby_development/ui/config_widget.ui +58 -0
  58. data/plugins/ruby_development/ui/project_widget.rb +1 -1
  59. data/plugins/ruby_runner/plugin.yaml +2 -2
  60. data/plugins/ruby_runner/ruby_runner.rb +15 -3
  61. data/plugins/ruby_runner/ui/config_widget.rb +1 -1
  62. data/plugins/ruby_runner/ui/project_widget.rb +1 -1
  63. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +1 -1
  64. data/plugins/state/plugin.yaml +6 -2
  65. data/plugins/state/state.rb +305 -81
  66. data/plugins/state/ui/config_widget.rb +1 -1
  67. data/spec/common.rb +11 -3
  68. data/spec/document_list_spec.rb +8 -8
  69. data/spec/document_project_spec.rb +98 -25
  70. data/spec/document_spec.rb +178 -152
  71. data/spec/editor_view_spec.rb +26 -5
  72. data/spec/framework.rb +5 -0
  73. data/spec/hint_solver_spec.rb +450 -0
  74. data/spec/kde_sugar_spec.rb +73 -6
  75. data/spec/output_widget_spec.rb +172 -156
  76. data/spec/pane_spec.rb +1165 -0
  77. data/spec/plugin_specification_reader_spec.rb +37 -1
  78. data/spec/project_files_list_spec.rb +30 -20
  79. data/spec/qt_sugar_spec.rb +269 -0
  80. data/spec/state_spec.rb +566 -353
  81. data/spec/utils_spec.rb +1 -1
  82. data/spec/view_manager_spec.rb +71 -0
  83. metadata +16 -4
@@ -0,0 +1,1165 @@
1
+ require './spec/common'
2
+ require 'ruber/pane'
3
+ require 'ruber/editor/document'
4
+
5
+ describe Ruber::Pane do
6
+
7
+ class PaneSpecComponentManager < Qt::Object
8
+ extend Forwardable
9
+ signals 'component_loaded(QObject*)', 'unloading_component(QObject*)'
10
+ def_delegators :@data, :[], :<<
11
+ def_delegator :@data, :each, :each_component
12
+
13
+ def initialize parent = nil
14
+ super
15
+ @data = []
16
+ end
17
+
18
+ end
19
+
20
+ before do
21
+ @main_window = Qt::Widget.new
22
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@main_window).by_default
23
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(PaneSpecComponentManager.new).by_default
24
+ @doc = Ruber::Document.new
25
+ end
26
+
27
+ it 'is enumerable' do
28
+ Ruber::Pane.ancestors.should include(QtEnumerable)
29
+ end
30
+
31
+ context 'when created with one view' do
32
+
33
+ it 'makes the view child of itself' do
34
+ view = @doc.create_view nil
35
+ pane = Ruber::Pane.new view
36
+ view.parent.should == pane
37
+ end
38
+
39
+ it 'inserts the view in the layout' do
40
+ view = @doc.create_view nil
41
+ pane = Ruber::Pane.new view
42
+ pane.layout.should include(view)
43
+ end
44
+
45
+ it 'allows a parent to be specified' do
46
+ view = @doc.create_view nil
47
+ w = Qt::Widget.new
48
+ pane = Ruber::Pane.new view, w
49
+ pane.parent.should == w
50
+ end
51
+
52
+ end
53
+
54
+ context 'when created with two panes and an orientation' do
55
+
56
+ before do
57
+ @panes = 2.times.map{Ruber::Pane.new @doc.create_view(nil)}
58
+ end
59
+
60
+ it 'inserts the two panes in a splitter with the given orientation' do
61
+ pane = Ruber::Pane.new Qt::Horizontal, @panes[0], @panes[1]
62
+ splitter = pane.layout.find{|c| c.is_a? Qt::Splitter}
63
+ splitter.should_not be_nil
64
+ splitter.orientation.should == Qt::Horizontal
65
+ splitter.widget(0).should == @panes[0]
66
+ splitter.widget(1).should == @panes[1]
67
+ end
68
+
69
+ it 'makes the panes child of the splitter' do
70
+ pane = Ruber::Pane.new Qt::Horizontal, @panes[0], @panes[1]
71
+ splitter = pane.find_child(Qt::Splitter)
72
+ @panes.each{|p| p.parent.should == splitter}
73
+ end
74
+
75
+ it 'allows a parent to be specified' do
76
+ w = Qt::Widget.new
77
+ pane = Ruber::Pane.new Qt::Horizontal, @panes[0], @panes[1], w
78
+ pane.parent.should == w
79
+ end
80
+
81
+ end
82
+
83
+ describe '#single_view?' do
84
+
85
+ it 'returns true if the pane only contains one view' do
86
+ pane = Ruber::Pane.new @doc.create_view(nil)
87
+ pane.single_view?.should be_true
88
+ end
89
+
90
+ it 'returns false if the pane contains two views' do
91
+ views = 2.times.map{@doc.create_view(nil)}
92
+ pane = Ruber::Pane.new Qt::Vertical, views[0], views[1]
93
+ pane.single_view?.should be_false
94
+ end
95
+
96
+ end
97
+
98
+ describe '#orientation' do
99
+
100
+ it 'returns nil if the pane contains a single view' do
101
+ pane = Ruber::Pane.new @doc.create_view(nil)
102
+ pane.orientation.should be_nil
103
+ end
104
+
105
+ it 'returns the orientation of the splitter if the pain contains multiple panes' do
106
+ views = 2.times.map{@doc.create_view(nil)}
107
+ pane = Ruber::Pane.new Qt::Vertical, views[0], views[1]
108
+ pane.orientation.should == Qt::Vertical
109
+ pane = Ruber::Pane.new Qt::Horizontal, views[0], views[1]
110
+ pane.orientation.should == Qt::Horizontal
111
+ end
112
+
113
+ end
114
+
115
+ describe '#view' do
116
+
117
+ it 'returns the view if the pane contains a single view' do
118
+ view = @doc.create_view(nil)
119
+ pane = Ruber::Pane.new view
120
+ pane.view.should == view
121
+ end
122
+
123
+ it 'returns nil if the pane contains multiple panes' do
124
+ views = 2.times.map{@doc.create_view(nil)}
125
+ pane = Ruber::Pane.new Qt::Vertical, views[0], views[1]
126
+ pane.view.should be_nil
127
+ end
128
+
129
+ end
130
+
131
+ describe '#split' do
132
+
133
+ context 'if the pane contains a single view' do
134
+
135
+ before do
136
+ @view = @doc.create_view nil
137
+ @pane = Ruber::Pane.new @view
138
+ end
139
+
140
+ shared_examples_for '#split when the pane contains a single view' do
141
+
142
+ it 'inserts the pane containing each of the views in a splitter with the given orientation' do
143
+ view = @doc.create_view nil
144
+ @pane.split @view, view, Qt::Vertical, @pos
145
+ @pane.single_view?.should be_false
146
+ splitter = @pane.splitter
147
+ splitter.should be_a(Qt::Splitter)
148
+ splitter.orientation.should == Qt::Vertical
149
+ splitter.count.should == 2
150
+ splitter.each{|w| w.should be_a(Ruber::Pane)}
151
+ splitter.widget(@old_idx).view.should == @view
152
+ splitter.widget(@new_idx).view.should == view
153
+ end
154
+
155
+ it 'returns an array with the pane containing the old view as first element and the pane containing the new view as second element' do
156
+ view = @doc.create_view nil
157
+ res = @pane.split @view, view, Qt::Horizontal, @pos
158
+ res[0].should be_a(Ruber::Pane)
159
+ res[0].view.should == @view
160
+ res[1].should be_a(Ruber::Pane)
161
+ res[1].view.should == view
162
+ end
163
+
164
+ it 'hides the label' do
165
+ view = @doc.create_view nil
166
+ label = @pane.instance_variable_get(:@label)
167
+ flexmock(label).should_receive(:hide).once
168
+ @pane.split @view, view, Qt::Horizontal, @pos
169
+ end
170
+
171
+ it 'sets the label of the first pane to the text of the label and shows it' do
172
+ view = @doc.create_view nil
173
+ @pane.label = 'xyz'
174
+ views = [@pane.view, view]
175
+ panes = 2.times.map{|i| Ruber::Pane.new views[i], @pane.splitter}
176
+ flexmock(Ruber::Pane).should_receive(:new).with(views[0], Qt::Splitter).once.and_return panes[0]
177
+ flexmock(Ruber::Pane).should_receive(:new).with(views[1]).once.and_return panes[1]
178
+ label = panes[0].instance_variable_get(:@label)
179
+ flexmock(label).should_receive(:visible=).once.with(true)
180
+ pane = @pane.split(@view, view, Qt::Horizontal, @pos)
181
+ label.text.should == 'xyz'
182
+ end
183
+
184
+ it 'emits the split(QWidget*, QWidget*,QWidget*) signal passing self, the original and the new view as arguments' do
185
+ view = @doc.create_view nil
186
+ mk = flexmock{|m| m.should_receive(:pane_split).once.with(@pane, @view, view)}
187
+ @pane.connect(SIGNAL('pane_split(QWidget*,QWidget*,QWidget*)')){|pn, v1,v2| mk.pane_split pn, v1, v2}
188
+ @pane.split @view, view, Qt::Vertical, @pos
189
+ end
190
+
191
+ end
192
+
193
+ context 'and the last argument is :after or missing' do
194
+ before do
195
+ @old_idx = 0
196
+ @new_idx = 1
197
+ @pos = :after
198
+ end
199
+ it_behaves_like '#split when the pane contains a single view'
200
+ end
201
+
202
+ context 'and the last argument is :after or missing' do
203
+ before do
204
+ @old_idx = 1
205
+ @new_idx = 0
206
+ @pos = :before
207
+ end
208
+ it_behaves_like '#split when the pane contains a single view'
209
+ end
210
+
211
+ end
212
+
213
+ context 'if the pane already contains a splitter and it has the same orientation passed to the method' do
214
+
215
+ before do
216
+ @views = 2.times.map{@doc.create_view(nil)}
217
+ @panes = @views.map{|v| Ruber::Pane.new v}
218
+ @pane = Ruber::Pane.new Qt::Vertical, @panes[0], @panes[1]
219
+ end
220
+
221
+ shared_examples_for '#split when there\'s already a splitter with the same orientation' do
222
+
223
+ it 'puts the view in a new pane and adds the given view to the splitter after the one specified as second argument' do
224
+ view = @doc.create_view nil
225
+ @pane.split @views[0], view, Qt::Vertical, @pos
226
+ splitter = @pane.find_child(Qt::Splitter)
227
+ splitter.count.should == 3
228
+ pane = splitter.widget(@idx)
229
+ pane.should be_a(Ruber::Pane)
230
+ pane.find_child(Ruber::EditorView).should == view
231
+ end
232
+
233
+ it 'makes the new pane child of the splitter' do
234
+ view = @doc.create_view nil
235
+ @pane.split @views[0], view, Qt::Vertical, @pos
236
+ splitter = @pane.find_child(Qt::Splitter)
237
+ pane = splitter.widget(@idx)
238
+ pane.parent.should == splitter
239
+ end
240
+
241
+ it 'returns an array with the pane containing the old view as first element and the pane containing the new view as second element' do
242
+ view = @doc.create_view nil
243
+ res = @pane.split @views[0], view, Qt::Horizontal, @pos
244
+ res[0].should be_a(Ruber::Pane)
245
+ res[0].view.should == @views[0]
246
+ res[1].should be_a(Ruber::Pane)
247
+ res[1].view.should == view
248
+ end
249
+
250
+ it 'emits the split(QWidget*, QWidget*,QWidget*) signal passing self, the original and the new view as arguments' do
251
+ view = @doc.create_view nil
252
+ mk = flexmock{|m| m.should_receive(:pane_split).once.with(@pane, @views[0], view)}
253
+ @pane.connect(SIGNAL('pane_split(QWidget*,QWidget*,QWidget*)')){|pn, v1,v2| mk.pane_split pn, v1, v2}
254
+ @pane.split @views[0], view, Qt::Vertical, @pos
255
+ end
256
+
257
+
258
+ end
259
+
260
+ context 'and the last argument is :after or missing' do
261
+ before do
262
+ @idx = 1
263
+ @pos = :after
264
+ end
265
+ it_behaves_like '#split when there\'s already a splitter with the same orientation'
266
+ end
267
+
268
+ context 'and the last argument is :before' do
269
+ before do
270
+ @idx = 0
271
+ @pos = :before
272
+ end
273
+ it_behaves_like '#split when there\'s already a splitter with the same orientation'
274
+ end
275
+
276
+ end
277
+
278
+ context 'if the pane already contains a splitter but it has a different orientation' do
279
+
280
+ before do
281
+ @views = 2.times.map{@doc.create_view(nil)}
282
+ @panes = @views.map{|v| Ruber::Pane.new v}
283
+ @pane = Ruber::Pane.new Qt::Horizontal, @panes[0], @panes[1]
284
+ end
285
+
286
+ shared_examples_for '#split when there\'s already a splitter but it has a different orientation' do
287
+
288
+ it 'puts the two views in a new pane in the position of the existing view' do
289
+ view = @doc.create_view nil
290
+ old_splitter = @pane.find_child(Qt::Splitter)
291
+ @pane.split @views[0], view, Qt::Vertical, @pos
292
+ @pane.find_children(Ruber::Pane).select{|c| c.is_a? Ruber::Pane}.size.should == 4
293
+ old_splitter.count.should == 2
294
+ new_pane = old_splitter.widget 0
295
+ new_pane.should be_a(Ruber::Pane)
296
+ new_pane.should_not be_single_view
297
+ inner_splitter = new_pane.find_child(Qt::Splitter)
298
+ inner_splitter.orientation.should == Qt::Vertical
299
+ inner_splitter.widget(@old_idx).view.should == @views[0]
300
+ inner_splitter.widget(@new_idx).view.should == view
301
+ end
302
+
303
+ it 'returns an array with the pane containing the old view as first element and the pane containing the new view as second element' do
304
+ view = @doc.create_view nil
305
+ res = @pane.split @views[0], view, Qt::Horizontal, @pos
306
+ res[0].should be_a(Ruber::Pane)
307
+ res[0].view.should == @views[0]
308
+ res[1].should be_a(Ruber::Pane)
309
+ res[1].view.should == view
310
+ end
311
+
312
+ it 'emits the split(QWidget*, QWidget*,QWidget*) signal passing self, the original and the new view as arguments' do
313
+ view = @doc.create_view nil
314
+ mk = flexmock{|m| m.should_receive(:pane_split).once.with(@pane, @views[0], view)}
315
+ @pane.connect(SIGNAL('pane_split(QWidget*,QWidget*,QWidget*)')){|pn, v1,v2| mk.pane_split pn, v1, v2}
316
+ @pane.split @views[0], view, Qt::Vertical, @pos
317
+ end
318
+
319
+
320
+ end
321
+
322
+ context 'and the last argument is :after or missing' do
323
+ before do
324
+ @old_idx = 0
325
+ @new_idx = 1
326
+ @pos = :after
327
+ end
328
+ it_behaves_like '#split when there\'s already a splitter but it has a different orientation'
329
+ end
330
+
331
+ context 'and the last argument is :before' do
332
+ before do
333
+ @old_idx = 1
334
+ @new_idx = 0
335
+ @pos = :before
336
+ end
337
+ it_behaves_like '#split when there\'s already a splitter but it has a different orientation'
338
+ end
339
+
340
+ end
341
+
342
+ context 'if the given view is not directly contained in the pane' do
343
+
344
+ it 'does nothing and returns nil if the view isn\'t contained in any of the children panes' do
345
+ doc = Ruber::Document.new
346
+ views = 5.times.map{doc.create_view}
347
+ pane = Ruber::Pane.new(views[0])
348
+ pane.split views[0], views[1], Qt::Horizontal, :after
349
+ panes = pane.split views[0], views[2], Qt::Vertical, :after
350
+ pane.split(views[3], views[4], Qt::Horizontal, :after).should be_nil
351
+ pane.find_children(Ruber::EditorView).find{|v| v == views[4]}.should be_nil
352
+ end
353
+
354
+ it 'calls the same method of the pane containing the view' do
355
+ doc = Ruber::Document.new
356
+ views = 4.times.map{doc.create_view}
357
+ pane = Ruber::Pane.new(views[0])
358
+ pane.split views[0], views[1], Qt::Horizontal, :after
359
+ panes = pane.split views[0], views[2], Qt::Vertical, :after
360
+ flexmock(panes[1].parent.parent).should_receive(:split).with(views[2], views[3], Qt::Vertical, :after).once
361
+ pane.split views[2], views[3], Qt::Vertical, :after
362
+ end
363
+
364
+ it 'emits the split(QWidget*, QWidget*,QWidget*) signal passing the pane where the view was contained, the original and the new view as arguments' do
365
+ doc = Ruber::Document.new
366
+ views = 4.times.map{doc.create_view}
367
+ pane = Ruber::Pane.new(views[0])
368
+ pane.split views[0], views[1], Qt::Horizontal, :after
369
+ panes = pane.split views[0], views[2], Qt::Vertical, :after
370
+ mk = flexmock{|m| m.should_receive(:pane_split).once.with(panes[1].parent.parent, views[2], views[3])}
371
+ pane.connect(SIGNAL('pane_split(QWidget*,QWidget*,QWidget*)')){|pn, v1,v2| mk.pane_split pn, v1, v2}
372
+ pane.split views[2], views[3], Qt::Vertical, :after
373
+ end
374
+
375
+ end
376
+
377
+ end
378
+
379
+ context 'when a view contained in it emits the closing signal' do
380
+
381
+ context 'if the pane is in single view mode' do
382
+
383
+ it 'calls the remove_view method' do
384
+ doc = Ruber::Document.new
385
+ view = doc.create_view nil
386
+ pane = Ruber::Pane.new view
387
+ flexmock(pane).should_receive(:remove_view).once.with(view)
388
+ view.instance_eval{emit closing self}
389
+ end
390
+
391
+ it 'emits the removing_view(QWidget*,QWidget*) signal passing self and the view as arguments' do
392
+ doc = Ruber::Document.new
393
+ view = doc.create_view nil
394
+ pane = Ruber::Pane.new view
395
+ mk = flexmock{|m| m.should_receive(:removing_view).with(pane, view).once}
396
+ pane.connect(SIGNAL('removing_view(QWidget*,QWidget*)')){|pn, v| mk.removing_view pn, v}
397
+ view.instance_eval{emit closing self}
398
+ end
399
+
400
+ end
401
+
402
+ context 'if the pane is in multiple view mode' do
403
+
404
+ it 'does not attempt to remove the view' do
405
+ doc = Ruber::Document.new
406
+ views = 3.times.map{doc.create_view nil}
407
+ pane = Ruber::Pane.new views[0]
408
+ 1.upto(2){|i| pane.split views[i-1], views[i], Qt::Vertical}
409
+ flexmock(pane).should_receive(:remove_view).never
410
+ views[0].instance_eval{emit closing self}
411
+ end
412
+
413
+ it 'emits the removing_view(QWidget*,QWidget*) signal passing the pane containing the view and the view itself as arguments' do
414
+ doc = Ruber::Document.new
415
+ views = 3.times.map{doc.create_view nil}
416
+ pane = Ruber::Pane.new views[0]
417
+ 1.upto(2){|i| pane.split views[i-1], views[i], Qt::Vertical}
418
+ mk = flexmock{|m| m.should_receive(:removing_view).with(views[0].parent, views[0]).once}
419
+ pane.connect(SIGNAL('removing_view(QWidget*,QWidget*)')){|pn, v| mk.removing_view pn, v}
420
+ views[0].instance_eval{emit closing self}
421
+ end
422
+
423
+ end
424
+
425
+ end
426
+
427
+ describe '#remove_view' do
428
+
429
+ before do
430
+ @doc = Ruber::Document.new
431
+ @view = @doc.create_view nil
432
+ @pane = Ruber::Pane.new @view
433
+ flexmock(@pane).should_receive(:delete_later).by_default
434
+ end
435
+
436
+ it 'emits the closing_last_view signal passing self as argument' do
437
+ mk = flexmock{|m| m.should_receive(:closing_last_view).once.with(@pane)}
438
+ @pane.connect(SIGNAL('closing_last_view(QWidget*)')){|w| mk.closing_last_view w}
439
+ @pane.send :remove_view, @view
440
+ end
441
+
442
+ it 'sets the view\'s parent to nil' do
443
+ @pane.send :remove_view, @view
444
+ @view.parent.should be_nil
445
+ end
446
+
447
+ it 'deletes the pane' do
448
+ flexmock(@pane).should_receive(:delete_later).once
449
+ @pane.send :remove_view, @view
450
+ end
451
+
452
+ end
453
+
454
+ context 'when a child pane emits the closing_last_view signal' do
455
+
456
+ before do
457
+ @doc = Ruber::Document.new
458
+ @views = 3.times.map{@doc.create_view}
459
+ end
460
+
461
+ it 'does nothing if the pane isn\'t directly contained in the pane' do
462
+ @pane = Ruber::Pane.new Qt::Vertical, Ruber::Pane.new(@views[0]), Ruber::Pane.new(@views[1])
463
+ child_pane = @pane.split( @views[1], @views[2], Qt::Horizontal)[1]
464
+ flexmock(@pane).should_receive(:remove_pane).never
465
+ child_pane.instance_eval{emit closing_last_view(self)}
466
+ end
467
+
468
+ context 'when only one pane remains' do
469
+
470
+ context 'and that pane contains a single view' do
471
+
472
+ before do
473
+ @pane = Ruber::Pane.new @views[0]
474
+ @panes = @pane.split @views[0], @views[1], Qt::Vertical
475
+ end
476
+
477
+ it 'switches to single view mode containing the view of the remaining pane if the latter is in single view mode' do
478
+ @panes[0].instance_eval{emit closing_last_view(self)}
479
+ @pane.should be_single_view
480
+ @pane.view.should == @views[1]
481
+ end
482
+
483
+ it 'uses the label of the remaining pane as its own label' do
484
+ @panes[1].label = 'xyz'
485
+ @panes[0].instance_eval{emit closing_last_view(self)}
486
+ @pane.label.should == 'xyz'
487
+ end
488
+
489
+ it 'displays the label unless the pane is s top level' do
490
+ view = @doc.create_view
491
+ panes = @panes[0].split @views[0], view, Qt::Vertical
492
+ panes[1].label = 'xyz'
493
+ label = @panes[0].instance_variable_get(:@label)
494
+ flexmock(label).should_receive(:visible=).with(true).once
495
+ panes[0].instance_eval{emit closing_last_view(self)}
496
+ end
497
+
498
+ it 'hides the label if it\'s a top level pane' do
499
+ label = @pane.instance_variable_get(:@label)
500
+ flexmock(label).should_receive(:visible=).with(false).once
501
+ @panes[1].label = 'xyz'
502
+ @panes[0].instance_eval{emit closing_last_view(self)}
503
+ end
504
+
505
+ it 'hides the label if the text is empty' do
506
+ view = @doc.create_view
507
+ panes = @panes[0].split @views[0], view, Qt::Vertical
508
+ panes[1].label = ''
509
+ label = @panes[0].instance_variable_get(:@label)
510
+ flexmock(label).should_receive(:visible=).with(false).once
511
+ panes[0].instance_eval{emit closing_last_view(self)}
512
+ end
513
+
514
+ it 'calls the delete_later method of the remaining pane' do
515
+ flexmock(@panes[1]).should_receive(:delete_later).once
516
+ @panes[0].instance_eval{emit closing_last_view(self)}
517
+ end
518
+
519
+ end
520
+
521
+ context 'and that pane contains more than one view' do
522
+
523
+ before do
524
+ @views << @doc.create_view << @doc.create_view
525
+ @pane = Ruber::Pane.new @views[0]
526
+ @closing_pane, @remaining_pane = @pane.split @views[0], @views[1], Qt::Vertical
527
+ @remaining_pane.split @views[1], @views[2], Qt::Horizontal
528
+ @remaining_pane.split @views[2], @views[3], Qt::Horizontal
529
+ end
530
+
531
+ it 'removes the remaining pane from the splitter' do
532
+ @closing_pane.instance_eval{emit closing_last_view self}
533
+ @pane.splitter.children.select{|c| c.is_a?(Ruber::Pane)}.should_not include(@remaining_pane)
534
+ end
535
+
536
+ it 'makes all the children panes its own children' do
537
+ @closing_pane.instance_eval{emit closing_last_view self}
538
+ @pane.should_not be_single_view
539
+ @pane.splitter.count.should == 3
540
+ @pane.splitter.widget(0).view.should == @views[1]
541
+ @pane.splitter.widget(1).view.should == @views[2]
542
+ @pane.splitter.widget(2).view.should == @views[3]
543
+ end
544
+
545
+ it 'calls the delete_later method of the remaining pane' do
546
+ flexmock(@remaining_pane).should_receive(:delete_later).once
547
+ @closing_pane.instance_eval{emit closing_last_view(self)}
548
+ end
549
+
550
+ end
551
+
552
+ end
553
+
554
+ context 'when more than one pane remains' do
555
+
556
+ it 'removes the pane from the splitter' do
557
+ @pane = Ruber::Pane.new @views[0]
558
+ @pane.split @views[0], @views[1], Qt::Vertical
559
+ pane_to_delete = @pane.split( @views[1], @views[2], Qt::Vertical)[1]
560
+ pane_to_delete.instance_eval{emit closing_last_view(self)}
561
+ pane_to_delete.parent.should be_nil
562
+ end
563
+
564
+ it 'doesn\'t alter anything else' do
565
+ @pane = Ruber::Pane.new @views[0]
566
+ @pane.split @views[0], @views[1], Qt::Vertical
567
+ panes = @pane.split @views[1], @views[2], Qt::Vertical
568
+ panes[0].instance_eval{emit closing_last_view self}
569
+ @pane.splitter.count.should == 2
570
+ @pane.splitter.widget(0).view.should == @views[0]
571
+ @pane.splitter.widget(1).view.should == @views[2]
572
+ end
573
+
574
+ end
575
+
576
+ end
577
+
578
+ describe '#each_pane' do
579
+
580
+ before do
581
+ @doc = Ruber::Document.new
582
+ @views = 4.times.map{@doc.create_view}
583
+ @pane = Ruber::Pane.new @views[0]
584
+ end
585
+
586
+ context 'when called with no argument' do
587
+
588
+ it 'iterates on all panes which are direct child of the pane' do
589
+ panes = []
590
+ panes += @pane.split @views[0], @views[1], Qt::Vertical
591
+ panes += @pane.split @views[1], @views[2], Qt::Vertical
592
+ @pane.split @views[1], @views[3], Qt::Horizontal
593
+ panes.uniq!
594
+ res = []
595
+ @pane.each_pane{|i| res << i}
596
+ res.should == panes
597
+ end
598
+
599
+ it 'does nothing if the pane is in single view mode' do
600
+ res = []
601
+ @pane.each_pane{|w| res << w}
602
+ res.should be_empty
603
+ end
604
+
605
+ it 'returns self if called with a block' do
606
+ @pane.each_pane{|w| w}.should == @pane
607
+ @pane.split @views[0], @views[1], Qt::Vertical
608
+ @pane.each_pane{|w| w}.should == @pane
609
+ end
610
+
611
+ it 'returns an enumerable if called without a block' do
612
+ panes = @pane.split @views[0], @views[1], Qt::Vertical
613
+ res = []
614
+ en = @pane.each_pane
615
+ en.should be_an(Enumerator)
616
+ en.each{|w| res << w}
617
+ res.should == panes
618
+ end
619
+
620
+ end
621
+
622
+ context 'when called with the :recursive argument' do
623
+
624
+ it 'iterates on all panes, recursively' do
625
+ panes = []
626
+ panes += @pane.split @views[0], @views[1], Qt::Vertical
627
+ panes += @pane.split @views[1], @views[2], Qt::Vertical
628
+ panes.uniq!
629
+ temp = @pane.split @views[1], @views[3], Qt::Horizontal
630
+ panes.insert 2, temp[0]
631
+ panes.insert 3, temp[1]
632
+ panes.uniq!
633
+ res = []
634
+ @pane.each_pane(:recursive){|i| res << i}
635
+ res.should == panes
636
+ end
637
+
638
+ it 'does nothing if the pane is in single view mode' do
639
+ res = []
640
+ @pane.each_pane(:recursive){|w| res << w}
641
+ res.should be_empty
642
+ end
643
+
644
+ it 'returns self if called with a block' do
645
+ @pane.each_pane(:recursive){|w| w}.should == @pane
646
+ @pane.split @views[0], @views[1], Qt::Vertical
647
+ @pane.each_pane(:recursive){|w| w}.should == @pane
648
+ end
649
+
650
+ it 'returns an enumerator which iterates on all child panes recursively if called without a block' do
651
+ panes = []
652
+ panes += @pane.split @views[0], @views[1], Qt::Vertical
653
+ panes += @pane.split @views[1], @views[2], Qt::Vertical
654
+ panes.uniq!
655
+ temp = @pane.split @views[1], @views[3], Qt::Horizontal
656
+ panes.insert 2, temp[0]
657
+ panes.insert 3, temp[1]
658
+ panes.uniq!
659
+ res = []
660
+ en = @pane.each_pane(:recursive)
661
+ en.should be_an(Enumerator)
662
+ en.each{|i| res << i}
663
+ res.should == panes
664
+ end
665
+
666
+ end
667
+
668
+ end
669
+
670
+ describe '#each_view' do
671
+
672
+ before do
673
+ @doc = Ruber::Document.new
674
+ @views = 4.times.map{@doc.create_view}
675
+ @pane = Ruber::Pane.new @views[0]
676
+ end
677
+
678
+ it 'calls iterates over all views contained in the pane' do
679
+ @pane.split @views[0], @views[1], Qt::Vertical
680
+ @pane.split @views[1], @views[2], Qt::Vertical
681
+ @pane.split @views[1], @views[3], Qt::Horizontal
682
+ res = []
683
+ @pane.each_view{|v| res << v}
684
+ res.should == [@views[0], @views[1], @views[3], @views[2]]
685
+ end
686
+
687
+ it 'yields the single view contained in the pane if the pane is in single view mode' do
688
+ res = []
689
+ @pane.each_view{|v| res << v}
690
+ res.should == [@views[0]]
691
+ end
692
+
693
+ it 'returns self' do
694
+ @pane.each_view{}.should == @pane
695
+ @pane.split @views[0], @views[1], Qt::Vertical
696
+ @pane.split @views[1], @views[2], Qt::Vertical
697
+ @pane.split @views[1], @views[3], Qt::Horizontal
698
+ @pane.each_view{}.should == @pane
699
+ end
700
+
701
+ it 'returns an enumerator which iterates on all views if no block is given' do
702
+ en = @pane.each_view
703
+ en.should be_an(Enumerator)
704
+ res_single = []
705
+ en.each{|v| res_single << v}
706
+ @pane.split @views[0], @views[1], Qt::Vertical
707
+ @pane.split @views[1], @views[2], Qt::Vertical
708
+ @pane.split @views[1], @views[3], Qt::Horizontal
709
+ en = @pane.each_view
710
+ en.should be_an(Enumerator)
711
+ res_multi = []
712
+ en.each{|v| res_multi << v}
713
+ res_single.should == [@views[0]]
714
+ res_multi.should == [@views[0], @views[1], @views[3], @views[2]]
715
+ end
716
+
717
+ end
718
+
719
+ describe '#parent_pane' do
720
+
721
+ before do
722
+ @doc = Ruber::Document.new
723
+ @views = 4.times.map{@doc.create_view}
724
+ @pane = Ruber::Pane.new @views[0]
725
+ end
726
+
727
+ it 'returns nil if the pane is a toplevel widget' do
728
+ @pane.parent_pane.should be_nil
729
+ end
730
+
731
+ it 'returns nil if the pane\'s parent is not a Qt::Splitter' do
732
+ w = Qt::Widget.new
733
+ @pane.parent = w
734
+ @pane.parent_pane.should be_nil
735
+ end
736
+
737
+ it 'returns nil if the pane\'s gandparent is not a Pane' do
738
+ w = Qt::Widget.new
739
+ s = Qt::Splitter.new w
740
+ s.add_widget @pane
741
+ @pane.parent_pane.should be_nil
742
+ end
743
+
744
+ it 'returns the pane\'s grandparent if it\'s a Pane' do
745
+ panes = @pane.split @views[0], @views[1], Qt::Horizontal
746
+ panes[0].parent_pane.should == @pane
747
+ end
748
+
749
+ end
750
+
751
+ describe '#contains?' do
752
+
753
+ before do
754
+ @doc = Ruber::Document.new
755
+ @views = 4.times.map{@doc.create_view}
756
+ @pane = Ruber::Pane.new @views[0]
757
+ end
758
+
759
+ context 'when called with one argument' do
760
+
761
+ context 'and the argument is a pane' do
762
+
763
+ it 'returns true if this pane contains, directly or not, the one given as argument' do
764
+ panes = @pane.split @views[0], @views[1], Qt::Vertical
765
+ @pane.contain?(panes[0]).should be_true
766
+ panes = @pane.split @views[1], @views[2], Qt::Horizontal
767
+ @pane.contain?(panes[1]).should be_true
768
+ end
769
+
770
+ it 'returns false if this pane doesn\'t contain the one given as argument' do
771
+ pane = Ruber::Pane.new @views[2]
772
+ @pane.contain?(pane).should be_false
773
+ end
774
+
775
+ end
776
+
777
+ context 'and the argument is a view' do
778
+
779
+ it 'returns true if the pane contains, directly or not, the view' do
780
+ @pane.contain?(@views[0]).should be_true
781
+ @pane.split @views[0], @views[1], Qt::Vertical
782
+ @pane.split @views[1], @views[2], Qt::Horizontal
783
+ @pane.contain?(@views[2]).should be_true
784
+ end
785
+
786
+ it 'returns vale if this pane doesn\'t contain the view' do
787
+ @pane.contain?(@views[2]).should be_false
788
+ end
789
+
790
+ end
791
+
792
+ end
793
+
794
+ context 'when called with two arguments' do
795
+
796
+ context 'and the first argument is a pane' do
797
+
798
+ it 'returns true if this pane directly contains the one given as argument' do
799
+ panes = @pane.split @views[0], @views[1], Qt::Vertical
800
+ @pane.contain?(panes[0], :directly).should be_true
801
+ end
802
+
803
+ it 'returns false if this pane doesn\'t contain the one given as argument' do
804
+ pane = Ruber::Pane.new @views[2]
805
+ @pane.contain?(pane, :directly).should be_false
806
+ end
807
+
808
+ it 'returns false if this pane contains the one given as argument indirectly' do
809
+ panes = @pane.split @views[0], @views[1], Qt::Vertical
810
+ panes = @pane.split @views[1], @views[2], Qt::Horizontal
811
+ @pane.contain?(panes[1], :directly).should be_false
812
+ end
813
+
814
+ end
815
+
816
+ end
817
+
818
+ context 'and the second argument is a view' do
819
+
820
+ it 'returns true if this pane directly contains the view' do
821
+ @pane.contain?(@views[0], :directly).should be_true
822
+ end
823
+
824
+ it 'returns false if this pane doesn\'t contain the view' do
825
+ @pane.contain?(@views[1], :directly).should be_false
826
+ end
827
+
828
+ it 'returns false if this pane contains the one given as argument indirectly' do
829
+ panes = @pane.split @views[0], @views[1], Qt::Vertical
830
+ panes = @pane.split @views[1], @views[2], Qt::Horizontal
831
+ @pane.contain?(@views[2], :directly).should be_false
832
+ end
833
+
834
+ end
835
+
836
+ end
837
+
838
+ describe '#set_view_label' do
839
+
840
+ context 'when the pane is in single view mode' do
841
+
842
+ it 'displays a label containing the given text if the contained view matches the first argument' do
843
+ view1 = @doc.create_view
844
+ view2 = @doc.create_view
845
+ outer_pane = Ruber::Pane.new view1
846
+ pane = outer_pane.split(view1, view2, Qt::Horizontal)[0]
847
+ text = 'xyz'
848
+ flexmock(pane.instance_variable_get(:@label)).should_receive(:visible=).once.with true
849
+ pane.set_view_label view1, text
850
+ label = pane.layout.item_at(1).widget
851
+ label.should be_a(Qt::Label)
852
+ label.text.should == text
853
+ end
854
+
855
+ it 'hides the label if the text is empty and the view matches the first argument' do
856
+ view1 = @doc.create_view
857
+ view2 = @doc.create_view
858
+ outer_pane = Ruber::Pane.new view1
859
+ pane = outer_pane.split(view1, view2, Qt::Horizontal)[0]
860
+ label = pane.instance_variable_get(:@label)
861
+ label.text = 'xyz'
862
+ flexmock(pane.instance_variable_get(:@label)).should_receive(:visible=).once.with false
863
+ pane.set_view_label view1, ''
864
+ label.text.should == ''
865
+ end
866
+
867
+ it 'does nothing if the view argument isn\'t the same view contained in the pane' do
868
+ view1 = @doc.create_view
869
+ view2 = @doc.create_view
870
+ view3 = @doc.create_view
871
+ outer_pane = Ruber::Pane.new view1
872
+ pane = outer_pane.split(view1, view2, Qt::Horizontal)[0]
873
+ label = pane.instance_variable_get(:@label)
874
+ orig_text = 'abc'
875
+ label.text = orig_text
876
+ flexmock(label).should_receive(:visible=).never
877
+ text = 'xyz'
878
+ pane.set_view_label view3, text
879
+ label.text.should == orig_text
880
+ end
881
+
882
+ it 'changes the label text but doesn\'t display the label if the pane is a top-level pane' do
883
+ view = @doc.create_view
884
+ parent = Qt::Widget.new
885
+ pane = Ruber::Pane.new view, parent
886
+ pane.set_view_label view, 'text'
887
+ label = pane.instance_variable_get(:@label)
888
+ flexmock(label).should_receive(:visible=).never
889
+ text = 'xyz'
890
+ pane.set_view_label view, text
891
+ label.text.should == text
892
+ end
893
+
894
+ it 'returns true if the view argument is the same view contained in the pane' do
895
+ view1 = @doc.create_view
896
+ view2 = @doc.create_view
897
+ outer_pane = Ruber::Pane.new view1
898
+ pane = outer_pane.split(view1, view2, Qt::Horizontal)[0]
899
+ text = 'xyz'
900
+ pane.set_view_label( view1, text).should be_true
901
+ pane = Ruber::Pane.new view1
902
+ pane.set_view_label(view1, text).should be_true
903
+ end
904
+
905
+ it 'returns false if the view argument is different from the view contained in the pane' do
906
+ view1 = @doc.create_view
907
+ view2 = @doc.create_view
908
+ outer_pane = Ruber::Pane.new view1
909
+ pane = outer_pane.split(view1, view2, Qt::Horizontal)[0]
910
+ text = 'xyz'
911
+ pane.set_view_label( view2, text).should be_false
912
+ pane = Ruber::Pane.new view1
913
+ pane.set_view_label(view2, text).should be_false
914
+ end
915
+
916
+ end
917
+
918
+ context 'when the pane is in multiple view mode' do
919
+
920
+ it 'calls the same method on all child panes until one of them returns true' do
921
+ views = 3.times.map{@doc.create_view}
922
+ outer_pane = Ruber::Pane.new views[0]
923
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
924
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
925
+ text = 'xyz'
926
+ flexmock(panes[0]).should_receive(:set_view_label).with(views[1], text).once.and_return false
927
+ flexmock(panes[1]).should_receive(:set_view_label).with(views[1], text).once.and_return true
928
+ flexmock(panes[2]).should_receive(:set_view_label).never
929
+ outer_pane.set_view_label views[1], text
930
+ end
931
+
932
+ it 'returns true if one of the child panels\' set_view_label methods returns true' do
933
+ views = 3.times.map{@doc.create_view}
934
+ outer_pane = Ruber::Pane.new views[0]
935
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
936
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
937
+ text = 'xyz'
938
+ flexmock(panes[0]).should_receive(:set_view_label).with(views[1], text).once.and_return false
939
+ flexmock(panes[1]).should_receive(:set_view_label).with(views[1], text).once.and_return true
940
+ flexmock(panes[2]).should_receive(:set_view_label).never
941
+ outer_pane.set_view_label(views[1], text).should be_true
942
+ end
943
+
944
+ it 'returns false if all the child panels\'s set_view_label methods return false' do
945
+ views = 4.times.map{@doc.create_view}
946
+ outer_pane = Ruber::Pane.new views[0]
947
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
948
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
949
+ text = 'xyz'
950
+ flexmock(panes[0]).should_receive(:set_view_label).with(views[3], text).once.and_return false
951
+ flexmock(panes[1]).should_receive(:set_view_label).with(views[3], text).once.and_return false
952
+ flexmock(panes[2]).should_receive(:set_view_label).with(views[3], text).once.and_return false
953
+ outer_pane.set_view_label(views[3], text).should be_false
954
+ end
955
+
956
+ end
957
+
958
+ end
959
+
960
+ describe '#label=' do
961
+
962
+ context 'when the pane is in single view mode' do
963
+
964
+ it 'sets the label to the given value' do
965
+ view = @doc.create_view
966
+ pane = Ruber::Pane.new view
967
+ text = 'xyz'
968
+ pane.label = text
969
+ pane.instance_variable_get(:@label).text.should == text
970
+ end
971
+
972
+ it 'shows the label if the text is not empty and the pane is not top level' do
973
+ views = 2.times.map{@doc.create_view}
974
+ outer_pane = Ruber::Pane.new views[0]
975
+ pane = outer_pane.split( views[0], views[1], Qt::Vertical)[0]
976
+ text = 'xyz'
977
+ label = pane.instance_variable_get(:@label)
978
+ flexmock(label).should_receive(:visible=).with(true).once
979
+ pane.label = text
980
+ label.text.should == text
981
+ end
982
+
983
+ it 'doesn\'t show the label if the pane is top-level' do
984
+ view = @doc.create_view
985
+ pane = Ruber::Pane.new view
986
+ text = 'xyz'
987
+ label = pane.instance_variable_get(:@label)
988
+ flexmock(label).should_receive(:visible=).never
989
+ pane.label = text
990
+ end
991
+
992
+ it 'hides the label if the text is empty' do
993
+ views = 2.times.map{@doc.create_view}
994
+ outer_pane = Ruber::Pane.new views[0]
995
+ pane = outer_pane.split( views[0], views[1], Qt::Vertical)[0]
996
+ label = pane.instance_variable_get(:@label)
997
+ label.text = 'xyz'
998
+ flexmock(label).should_receive(:visible=).with(false).once
999
+ pane.label = ''
1000
+ label.text.should == ''
1001
+ end
1002
+
1003
+ end
1004
+
1005
+ context 'when the pane is in multiple view mode' do
1006
+
1007
+ it 'does nothing' do
1008
+ views = 2.times.map{@doc.create_view}
1009
+ pane = Ruber::Pane.new views[0]
1010
+ pane.split( views[0], views[1], Qt::Vertical)[0]
1011
+ text = 'xyz'
1012
+ label = pane.instance_variable_get(:@label)
1013
+ flexmock(label).should_receive(:visible=).never
1014
+ flexmock(label).should_receive(:text=).never
1015
+ pane.label = text
1016
+ end
1017
+
1018
+ end
1019
+
1020
+ end
1021
+
1022
+ describe '#label' do
1023
+
1024
+ it 'returns the text of the label if the pane is in single view mode' do
1025
+ view = @doc.create_view
1026
+ pane = Ruber::Pane.new view
1027
+ pane.label = 'xyz'
1028
+ pane.label.should == 'xyz'
1029
+ end
1030
+
1031
+ it 'returns an empty string if the label hasn\'t been set' do
1032
+ view = @doc.create_view
1033
+ pane = Ruber::Pane.new view
1034
+ pane.label.should == ''
1035
+ end
1036
+
1037
+ it 'returns an empty string if the label has been set to an empty string' do
1038
+ view = @doc.create_view
1039
+ pane = Ruber::Pane.new view
1040
+ pane.label = ''
1041
+ pane.label.should == ''
1042
+ end
1043
+
1044
+ it 'returns nil if the pane is in multiple view mode' do
1045
+ views = 2.times.map{@doc.create_view}
1046
+ pane = Ruber::Pane.new views[0]
1047
+ pane.label = 'xyz'
1048
+ pane.split( views[0], views[1], Qt::Vertical)[0]
1049
+ pane.label.should be_nil
1050
+ end
1051
+
1052
+ end
1053
+
1054
+ describe '#replace_view' do
1055
+
1056
+ context 'if the pane is in single view mode' do
1057
+
1058
+ context 'and the view in the pane is the one given as first argument' do
1059
+
1060
+ it 'replaces the view contained in the pane with the one given as second argument' do
1061
+ views = 2.times.map{@doc.create_view}
1062
+ pane = Ruber::Pane.new views[0]
1063
+ pane.replace_view views[0], views[1]
1064
+ pane.view.should == views[1]
1065
+ pane.view.parent.should == pane
1066
+ pane.layout.should include(views[1])
1067
+ end
1068
+
1069
+ it 'makes the old view parentless and removes it from the layout' do
1070
+ views = 2.times.map{@doc.create_view}
1071
+ pane = Ruber::Pane.new views[0]
1072
+ pane.replace_view views[0], views[1]
1073
+ views[0].parent.should be_nil
1074
+ pane.layout.should_not include(views[0])
1075
+ end
1076
+
1077
+ it 'returns true' do
1078
+ views = 2.times.map{@doc.create_view}
1079
+ pane = Ruber::Pane.new views[0]
1080
+ pane.replace_view(views[0], views[1]).should be_true
1081
+ end
1082
+
1083
+ it 'emits the view_replaced(QWidget*,QWidget*,QWidget*) signal passing self, the original view and the replacement view as arguments' do
1084
+ views = 2.times.map{@doc.create_view}
1085
+ pane = Ruber::Pane.new views[0]
1086
+ mk = flexmock{|m| m.should_receive(:view_replaced).with(pane, views[0], views[1]).once}
1087
+ pane.connect(SIGNAL('view_replaced(QWidget*,QWidget*,QWidget*)')){|pn, v1, v2| mk.view_replaced pn, v1, v2}
1088
+ pane.replace_view(views[0], views[1])
1089
+ end
1090
+
1091
+ end
1092
+
1093
+ context 'and the view in the pane is not the one given as first argument' do
1094
+
1095
+ it 'does nothing' do
1096
+ views = 3.times.map{@doc.create_view}
1097
+ pane = Ruber::Pane.new views[0]
1098
+ pane.replace_view views[2], views[1]
1099
+ pane.view.should == views[0]
1100
+ views[0].parent.should == pane
1101
+ views[1].parent.should be_nil
1102
+ pane.layout.should include(views[0])
1103
+ pane.layout.should_not include(views[1])
1104
+ end
1105
+
1106
+ it 'returns false' do
1107
+ views = 3.times.map{@doc.create_view}
1108
+ pane = Ruber::Pane.new views[0]
1109
+ pane.replace_view(views[2], views[1]).should be_false
1110
+ end
1111
+
1112
+ end
1113
+
1114
+ end
1115
+
1116
+ context 'if the pane is in multiple view mode' do
1117
+
1118
+ it 'calls the same method on all child panes until one of them returns true' do
1119
+ views = 4.times.map{@doc.create_view}
1120
+ outer_pane = Ruber::Pane.new views[0]
1121
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
1122
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
1123
+ flexmock(panes[0]).should_receive(:replace_view).with(views[1], views[3]).once.and_return false
1124
+ flexmock(panes[1]).should_receive(:replace_view).with(views[1], views[3]).once.and_return true
1125
+ flexmock(panes[2]).should_receive(:replace_view).never
1126
+ outer_pane.replace_view views[1], views[3]
1127
+ end
1128
+
1129
+ it 'returns true if one of the child panes\' replace_view methods returns true' do
1130
+ views = 4.times.map{@doc.create_view}
1131
+ outer_pane = Ruber::Pane.new views[0]
1132
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
1133
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
1134
+ flexmock(panes[0]).should_receive(:replace_view).with(views[1], views[3]).once.and_return false
1135
+ flexmock(panes[1]).should_receive(:replace_view).with(views[1], views[3]).once.and_return true
1136
+ flexmock(panes[2]).should_receive(:replace_view).never
1137
+ outer_pane.replace_view(views[1], views[3]).should be_true
1138
+ end
1139
+
1140
+ it 'emits the view_replaced(QWidget*,QWidget*,QWidget*) signal passing the pane containing the view, the original view and the replacement view as arguments if one of the child panes\' replace_view methods returns true' do
1141
+ views = 4.times.map{@doc.create_view}
1142
+ outer_pane = Ruber::Pane.new views[0]
1143
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
1144
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
1145
+ mk = flexmock{|m| m.should_receive(:view_replaced).with(views[1].parent, views[1], views[3]).once}
1146
+ outer_pane.connect(SIGNAL('view_replaced(QWidget*,QWidget*,QWidget*)')){|pn, v1, v2| mk.view_replaced pn, v1, v2}
1147
+ outer_pane.replace_view(views[1], views[3])
1148
+ end
1149
+
1150
+ it 'returns true if all of the child panes\' replace_view methods return false' do
1151
+ views = 5.times.map{@doc.create_view}
1152
+ outer_pane = Ruber::Pane.new views[0]
1153
+ panes = outer_pane.split(views[0], views[1], Qt::Horizontal)
1154
+ panes << outer_pane.split(views[1], views[2], Qt::Horizontal)[1]
1155
+ flexmock(panes[0]).should_receive(:replace_view).with(views[4], views[3]).once.and_return false
1156
+ flexmock(panes[1]).should_receive(:replace_view).with(views[4], views[3]).once.and_return false
1157
+ flexmock(panes[2]).should_receive(:replace_view).with(views[4], views[3]).once.and_return false
1158
+ outer_pane.replace_view(views[4], views[3]).should be_false
1159
+ end
1160
+
1161
+ end
1162
+
1163
+ end
1164
+
1165
+ end