ruber 0.0.5 → 0.0.7

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