#!/usr/bin/env ruby
# wxRuby2 Sample Code. Copyright (c) 2004-2008 wxRuby development team
# Adapted for wxRuby3
# Copyright (c) M.J.N. Corino, The Netherlands
###

require 'wx'

# This sample demonstrates the use of the Clipboard and Drag and Drop
# classes. Whilst the functionality of these is slightly different, they
# are both based around the use of the DataObject classes to exchange
# data of various sorts between applications (i.e. into and out of
# wxRuby)

# A ListBox that collects file names dropped onto it
class FileDropList < Wx::ListBox
  def initialize(*args)
    super
    # Set the handler for drag and drop actions
    self.drop_target = ListFileDropTarget.new(self)
  end

  # The class that actually handles the dropped files; it keeps a
  # reference to the ListBox, and appends items as they are added
  class ListFileDropTarget < Wx::FileDropTarget
    def initialize(list)
      super()
      @list = list
    end

    # This method is overridden to specify what happens when a file is
    # dropped 
    def on_drop_files(x, y, files)
      files.each { | file | @list.append(file) }
      true # currently need to return boolean from this method
    end
  end
end

class FileDropPane < Wx::Panel
  LABEL = "Drag and drop files from Explorer/Finder/etc to here\n" +
          "to add them to the list."
  def initialize(parent)
    super
    sizer = Wx::BoxSizer.new(Wx::VERTICAL)
    txt = Wx::StaticText.new( self, :label => LABEL)
    sizer.add(txt, 0, Wx::ALL, 4)

    @drop = FileDropList.new(self)
    sizer.add(@drop, 1, Wx::GROW|Wx::ALL, 4)
    self.sizer = sizer
  end
end

# A canvas which can display a pasted image
class PasteCanvas < Wx::Window
  attr_accessor :bitmap
  def initialize(parent)
    super(parent, :style => Wx::SUNKEN_BORDER)
    self.size = [ 200, 200 ]
    @bitmap = Wx::NULL_BITMAP
    evt_paint :on_paint
  end

  def on_paint(evt)
    paint do | dc  | 
      dc.clear
      if bitmap.ok?
        dc.draw_bitmap(bitmap, 0, 0, false)
      end 
      dc.pen = Wx::BLACK_PEN
    end
  end
end

# A Notebook panel to hold an image-paste canvas
class PastePane < Wx::Panel
  LABEL = "Use the buttons below to paste text and images from\n" +
          "the system clipboard, and then to copy them back."
  def initialize(parent)
    super
    sizer = Wx::BoxSizer.new(Wx::VERTICAL)
    txt = Wx::StaticText.new( self, :label => LABEL)
    sizer.add(txt, 0, Wx::ALL, 4)

    # Sizer for displaying text and image from the clipboard
    paste_sizer = Wx::FlexGridSizer.new(2, 2, 2, 2)
    paste_sizer.add_growable_col(0, 1)
    paste_sizer.add_growable_col(1, 1)
    paste_sizer.add_growable_row(1)

    paste_sizer.add( Wx::StaticText.new(self, :label => 'Clipboard text') )
    paste_sizer.add( Wx::StaticText.new(self, :label => 'Clipboard image') )
    
    # Target for displaying text from the clipboard
    @text = Wx::TextCtrl.new(self, :style => Wx::TE_MULTILINE)
    paste_sizer.add(@text, 1, Wx::GROW)

    # Target for displaying images from the clipboard
    @canvas = PasteCanvas.new(self)
    paste_sizer.add(@canvas, 1, Wx::GROW)
    
    sizer.add(paste_sizer, 1, Wx::ALL|Wx::GROW, 4)
    
    button_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)

    @paste_bt    = Wx::Button.new(self, :label => 'Paste')
    evt_button @paste_bt, :on_paste
    button_sizer.add(@paste_bt, 0, Wx::ALL, 4)

    @copy_img_bt = Wx::Button.new(self, :label => 'Copy image')
    evt_button @copy_img_bt, :on_copy_image
    button_sizer.add(@copy_img_bt, 0, Wx::ALL, 4)

    @copy_txt_bt = Wx::Button.new(self, :label => 'Copy text')
    evt_button @copy_txt_bt, :on_copy_text
    button_sizer.add(@copy_txt_bt, 0, Wx::ALL, 4)

    sizer.add(button_sizer, 0)
    self.sizer = sizer
  end

  # Receive data from the clipboard
  def on_paste(evt)
    # Temporarily open the clipboard 
    Wx::Clipboard.open do | clip |
      # Test if bitmap data is available on the clipboard; if so, copy
      if clip.supported?(Wx::DF_BITMAP)
        bmp = Wx::BitmapDataObject.new
        clip.get_data(bmp) # Fill the data object with bitmap`
        @canvas.bitmap = bmp.bitmap
        @canvas.refresh
      end      
      # Test if text data is available on the clipboard; if so, copy
      if clip.supported?(Wx::DF_TEXT)
        txt = Wx::TextDataObject.new
        clip.get_data(txt) # Fill the data object with text
        @text.value = txt.text
      end
    end
  end

  # Paste an image to the clipboard
  def on_copy_image
    Wx::Clipboard.open do | clip |
      clip.data = Wx::BitmapDataObject.new(@canvas.bitmap)
    end
  end

  # Paste text to the clipboard
  def on_copy_text
    Wx::Clipboard.open do | clip |
      clip.data = Wx::TextDataObject.new(@text.value)
    end
  end
end

class DataObjectFrame < Wx::Frame
  def initialize(parent)
    super
    panel = Wx::Panel.new(self)
    panel.sizer = Wx::BoxSizer.new(Wx::VERTICAL)
    nb = Wx::Notebook.new(panel)
    panel.sizer.add(nb, 1, Wx::ALL|Wx::GROW, 8)
    fd = FileDropPane.new(nb)
    nb.add_page(fd, 'Drag and Drop')
    cv = PastePane.new(nb)
    nb.add_page(cv, 'Clipboard')
    # urldrop = URLDropList.new(self)
  end
end

module DragDropSample

  include WxRuby::Sample if defined? WxRuby::Sample

  def self.describe
    { file: __FILE__,
      summary: 'wxRuby Drag&Drop example.',
      description: <<~__TXT
        wxRuby example demonstrating the use of the Clipboard and Drag and Drop
        classes. Whilst the functionality of these is slightly different, they
        are both based around the use of the DataObject classes to exchange
        data of various sorts between applications (i.e. into and out of
        wxRuby).
        __TXT
    }
  end

  def self.activate
    frame = DataObjectFrame.new(nil)
    frame.show
    frame
  end

  if $0 == __FILE__
    Wx::App.run { DragDropSample.activate }
  end

end