Class: JSON::Editor::PopUpMenu

Inherits:
Object
  • Object
show all
Includes:
MenuExtension
Defined in:
lib/json/editor.rb

Overview

This class creates the popup menu, that opens when clicking onto the treeview.

Instance Attribute Summary

Attributes included from MenuExtension

#menu, #treeview

Instance Method Summary collapse

Methods included from MenuExtension

#add_item, #add_separator, #initialize, #method_missing

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class JSON::Editor::MenuExtension

Instance Method Details

#append_new_node(item) ⇒ Object

Append a new node to the selected Hash or Array.



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'lib/json/editor.rb', line 357

def append_new_node(item)
  if parent = selection.selected
    parent_type = parent.type
    case parent_type
    when 'Hash'
      key, type, content = ask_for_hash_pair(parent)
      key or return
      iter = create_node(parent, 'Key', key)
      iter = create_node(iter, type, content)
      toplevel.display_status(
        "Added a (key, value)-pair to '#{parent_type}'.")
      window.change
    when 'Array'
      type, content = ask_for_element(parent)
      type or return
      iter = create_node(parent, type, content)
      window.change
      toplevel.display_status("Appendend an element to '#{parent_type}'.")
    else
      toplevel.display_status("Cannot append to '#{parent_type}'!")
    end
  else
    type, content = ask_for_element
    type or return
    iter = create_node(nil, type, content)
    window.change
  end
end

#change_node(item) ⇒ Object

Change the type or content of the selected node.



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/json/editor.rb', line 234

def change_node(item)
  if current = selection.selected
    parent = current.parent
    old_type, old_content = current.type, current.content
    if ALL_TYPES.include?(old_type)
      @clipboard_data = Editor.model2data(current)
      type, content = ask_for_element(parent, current.type,
        current.content)
      if type
        current.type, current.content = type, content
        current.remove_subtree(model)
        toplevel.display_status("Changed a node in tree.")
        window.change
      end
    else
      toplevel.display_status(
        "Cannot change node of type #{old_type} in tree!")
    end
  end
end

#collapse_expand(item) ⇒ Object

Recursively collapse/expand a subtree starting from the selected node.



413
414
415
416
417
418
419
420
421
422
423
# File 'lib/json/editor.rb', line 413

def collapse_expand(item)
  if current = selection.selected
    if row_expanded?(current.path)
      collapse_row(current.path)
    else
      expand_row(current.path, true)
    end
  else
      toplevel.display_status("Append a node into the root first!")
  end
end

#copy_node(item) ⇒ Object

Copy the selected node and its subtree, and save it into the clipboard.



274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/json/editor.rb', line 274

def copy_node(item)
  if current = selection.selected
    if current and current.type == 'Key'
      @clipboard_data = {
        current.content => Editor.model2data(current.first_child)
      }
    else
      @clipboard_data = Editor.model2data(current)
    end
    window.change
    toplevel.display_status("Copied a node from tree.")
  end
end

#createObject

Create the menu.



426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'lib/json/editor.rb', line 426

def create
  add_item("Change node", &method(:change_node))
  add_separator
  add_item("Cut node", &method(:cut_node))
  add_item("Copy node", &method(:copy_node))
  add_item("Paste node (appending)", &method(:paste_node_appending))
  add_item("Paste node (inserting before)",
    &method(:paste_node_inserting_before))
  add_separator
  add_item("Append new node", &method(:append_new_node))
  add_item("Insert new node before", &method(:insert_new_node))
  add_separator 
  add_item("Collapse/Expand node (recursively)",
    &method(:collapse_expand))

  menu.show_all
  signal_connect(:button_press_event) do |widget, event|
    if event.kind_of? Gdk::EventButton and event.button == 3
      menu.popup(nil, nil, event.button, event.time)
    end
  end
  signal_connect(:popup_menu) do
    menu.popup(nil, nil, 0, Gdk::Event::CURRENT_TIME)
  end
end

#cut_node(item) ⇒ Object

Cut the selected node and its subtree, and save it into the clipboard.



257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/json/editor.rb', line 257

def cut_node(item)
  if current = selection.selected
    if current and current.type == 'Key'
      @clipboard_data = {
        current.content => Editor.model2data(current.first_child)
      }
    else
      @clipboard_data = Editor.model2data(current)
    end
    model.remove(current)
    window.change
    toplevel.display_status("Cut a node from tree.")
  end
end

#insert_new_node(item) ⇒ Object

Insert a new node into an Array before the selected element.



387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# File 'lib/json/editor.rb', line 387

def insert_new_node(item)
  if current = selection.selected
    parent = current.parent or return
    parent_parent = parent.parent
    parent_type = parent.type
    if parent_type == 'Array'
      selected_index = parent.each_with_index do |c, i|
        break i if c == current
      end
      type, content = ask_for_element(parent)
      type or return
      iter = model.insert_before(parent, current)
      iter.type, iter.content = type, content
      toplevel.display_status("Inserted an element to " +
        "'#{parent_type}' before index #{selected_index}.")
      window.change
    else
      toplevel.display_status(
        "Cannot insert node below '#{parent_type}'!")
    end
  else
      toplevel.display_status("Append a node into the root first!")
  end
end

#paste_node_appending(item) ⇒ Object

Paste the data in the clipboard into the selected Array or Hash by appending it.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/json/editor.rb', line 290

def paste_node_appending(item)
  if current = selection.selected
    if @clipboard_data
      case current.type
      when 'Array'
        Editor.data2model(@clipboard_data, model, current)
        expand_collapse(current)
      when 'Hash'
        if @clipboard_data.is_a? Hash
          parent = current.parent
          hash = Editor.model2data(current)
          model.remove(current)
          hash.update(@clipboard_data)
          Editor.data2model(hash, model, parent)
          if parent
            expand_collapse(parent)
          elsif @expanded
            expand_all
          end
          window.change
        else
          toplevel.display_status(
            "Cannot paste non-#{current.type} data into '#{current.type}'!")
        end
      else
        toplevel.display_status(
          "Cannot paste node below '#{current.type}'!")
      end
    else
      toplevel.display_status("Nothing to paste in clipboard!")
    end
  else
      toplevel.display_status("Append a node into the root first!")
  end
end

#paste_node_inserting_before(item) ⇒ Object

Paste the data in the clipboard into the selected Array inserting it before the selected element.



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/json/editor.rb', line 328

def paste_node_inserting_before(item)
  if current = selection.selected
    if @clipboard_data
      parent = current.parent or return
      parent_type = parent.type
      if parent_type == 'Array'
        selected_index = parent.each_with_index do |c, i|
          break i if c == current
        end
        Editor.data2model(@clipboard_data, model, parent) do |m|
          m.insert_before(parent, current)
        end
        expand_collapse(current)
        toplevel.display_status("Inserted an element to " +
          "'#{parent_type}' before index #{selected_index}.")
        window.change
      else
        toplevel.display_status(
          "Cannot insert node below '#{parent_type}'!")
      end
    else
      toplevel.display_status("Nothing to paste in clipboard!")
    end
  else
      toplevel.display_status("Append a node into the root first!")
  end
end