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.



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

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.



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/json/editor.rb', line 264

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.



443
444
445
446
447
448
449
450
451
452
453
# File 'lib/json/editor.rb', line 443

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.



304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/json/editor.rb', line 304

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.



456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# File 'lib/json/editor.rb', line 456

def create
  add_item("Change node", ?n, &method(:change_node))
  add_separator
  add_item("Cut node", ?X, &method(:cut_node))
  add_item("Copy node", ?C, &method(:copy_node))
  add_item("Paste node (appending)", ?A, &method(:paste_node_appending))
  add_item("Paste node (inserting before)", ?I,
    &method(:paste_node_inserting_before))
  add_separator
  add_item("Append new node", ?a, &method(:append_new_node))
  add_item("Insert new node before", ?i, &method(:insert_new_node))
  add_separator
  add_item("Collapse/Expand node (recursively)", ?e,
    &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.



287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/json/editor.rb', line 287

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.



417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/json/editor.rb', line 417

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.



320
321
322
323
324
325
326
327
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 320

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.



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 358

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