#!/usr/local/bin/ruby

require "qt2"
include Qt2
#If you install qtimageio(see qtimageio directory)
# you can load jpg file.
#require "qtimageio"
#include Qtimageio
#qInitImageIO

	COLOR_MENU_ID_BLACK = 0
	COLOR_MENU_ID_RED = 1
	COLOR_MENU_ID_BLUE = 2
	COLOR_MENU_ID_GREEN = 3
	COLOR_MENU_ID_YELLOW = 4
        Load = 1
	Save = 2
	Quit = 3
        About = 4
        AboutQt = 5
        Help = 6
=begin
/**
  * A class that lets the user draw scribbles with the mouse. The
  * window knows how to redraw itself.
  */
=end



class ScribbleArea < QWidget
Clear = 0
=begin
/**
  * The constructor. Initializes the member variables and creates a
  * popup menu that will be popped up when the right mouse button is
  * clicked.
  */
=end
   def initialize
  @_buffer = QPixmap.new(nil)
#  // initialize member variables
  @_currentcolor = QColor("black")

#  // don't blank the window before repainting
  setBackgroundMode( QWidget::NoBackground )

#  // create a popup menu
  @_popupmenu = QPopupMenu.new
  @_popupmenu.insertItem( "&Clear", Clear, -1)
  Qt::connect(@_popupmenu,QSIGNAL("activated(int)"),self,"slotClearArea")
# Necessary to catch event functions in Ruby/Qt
  catchEvent
end


=begin
/**
  * This slot sets the current color for the scribble area. It will be
  * connected with the colorChanged( QColor* ) signal from the
  * ScribbleWindow.
  */
=end

def setColor( new_color )

  @_currentcolor = new_color
end

=begin
/**
  * This slot clears the scribble area by filling the off-screen buffer with
  * white and copying it over to the window.
  */
=end
def slotClearArea dum

#  // fill the off-screen buffer with plain white
  @_buffer.fill( QColor("white") )

#  // and copy it over to the window
  bitBlt( self, 0, 0, @_buffer )
end

=begin
/**
  * This method does the actual loading. It relies on QPixmap (and the
  * underlying I/O machinery) to determine the filetype.
  */
=end

def slotLoad( filename )

  if( !@_buffer.load( filename ) )
	QMessageBox::warning( nil, "Load error", "Could not load file",1 ,0)
  end
  self.resizeQSize(@_buffer.size)
  repaintAll
end

=begin
/**
  * This method does the actual saving. We hardcode the file type as
  * BMP. Unix users might want to replace self with something more usual
  * on Unix like XPM.
  */
=end

def slotSave( filename )

  if( !@_buffer.save( filename, "XPM" ) )
	QMessageBox::warning( 0, "Save error", "Could not save file" )
  end
end

=begin
/**
  * This virtual method gets called whenever the users presses the
  * mouse over the window. When the right mouse button is pressed, it
  * pops up synchronously a previously constructed popup
  * menu. Otherwise, it just records the position of the mouse
  * at the time of the click.
  */
=end
def mousePressEvent(  event )
  newpos = QPoint.new(event.pos.x,event.pos.y) #necessary to deepcopy?
  if( event.button == RightButton )
	@_popupmenu.execQPoint( QCursor::pos )
  else
	@_last = newpos #// retrieve the coordinates from the event
  end
end

=begin
/**
  * This virtual method gets called whenever the user moves the mouse
  * while the mouse button is pressed (self is also known as
  * "dragging"). If we had called setMouseTracking( true ) before,
  * self method would also be called when the mouse was moved without
  * any button pressed. We know that we haven't, and thus don't have
  * to check whether any buttons are pressed.
  */
=end

def mouseMoveEvent( event )
  newpos = QPoint.new(event.pos.x,event.pos.y)
#   newpos = event.pos
#  // create a QPainter object for drawing onto the window
  windowpainter = QPainter.new(nil)
#  // and another QPainter object for drawing into an off-screen pixmap
  bufferpainter = QPainter.new(nil)

#  // start painting
  windowpainter.begin( self )    #// self painter paints onto the window
  bufferpainter.begin( @_buffer ) #// and self one in the buffer

#  // set a standard pen with the currently selected color
  windowpainter.setPen( @_currentcolor )
  bufferpainter.setPen( @_currentcolor )

#  // draw a line in both the window and the buffer
#   if (!@_last.nil?)
   windowpainter.drawLine( @_last, newpos )
   bufferpainter.drawLine( @_last, newpos )
#   end
#  // done with painting
  windowpainter.end
  bufferpainter.end

#  // remember the current mouse position
  @_last = newpos
end


=begin
/**
  *	This virtual method gets called whenever the widget needs
  * painting, e.g., when it has been obscured and unhidden again.
  */
=end
def paintEvent( event )

#  // copy the image from the buffer pixmap to the window
  bitBlt( self, 0, 0, @_buffer )
end

=begin
/**
  * This virtual method gets called whenever the window is resized. We
  * use it to make sure that the off-screen buffer always has the same
  * size as the window.
  * In order not to lose the original scribbling, it is first copied
  * to a temporary buffer. After the main buffer has been resized and
  * filled with white, the image is copied from the temporary buffer to
  * the main buffer.
  */
=end
def resizeEvent( event )

  save=QPixmap.new( @_buffer )
  @_buffer.resize( event.size )
  @_buffer.fill( Qt::white )
  bitBlt( @_buffer, 0, 0, save )
end
end

class ScribbleWindow < QWidget

def initialize

  #/* The next few lines build up the menubar. We first create the menus
  #* one by one and add them afterwards to the menubar. */
  @_filemenu = QPopupMenu.new  #// create a file menu
  @_filemenu.insertItem( "&Load", Load)
  @_filemenu.insertItem( "&Save", Save)
  @_filemenu.insertSeparator
  @_filemenu.insertItem( "&Quit", QApplication::qApp, "quit()" )
  Qt::connect(@_filemenu, QSIGNAL( "activated( int )"),
					self, "fileMenuActivated")
													
  @_colormenu = QPopupMenu.new  #// create a color menu
  @_colormenu.insertItem( "B&lack", COLOR_MENU_ID_BLACK )
  @_colormenu.insertItem( "&Red", COLOR_MENU_ID_RED )
  @_colormenu.insertItem( "&Blue", COLOR_MENU_ID_BLUE )
  @_colormenu.insertItem( "&Green", COLOR_MENU_ID_GREEN )
  @_colormenu.insertItem( "&Yellow", COLOR_MENU_ID_YELLOW )
  Qt::connect( @_colormenu, QSIGNAL( "activated( int )" ),
					self, "slotColorMenu"  )

  @_helpmenu = QPopupMenu.new   #// create a help menu
  @_helpmenu.insertItem( "&About QtScribble", About)
  @_helpmenu.insertItem( "About &Qt", AboutQt)
  Qt::connect(@_helpmenu, QSIGNAL( "activated( int )"),
					self, "helpMenuActivated")
  @_menubar = QMenuBar.new( self )   # // create a menu bar
  @_menubar.insertItem( "&File", @_filemenu )
  @_menubar.insertItem( "&Color", @_colormenu )
  @_menubar.insertSeparator
  @_menubar.insertItem( "&Help", @_helpmenu )

  #/* We create a QScrollView and a ScribbleArea. The ScribbleArea will
  #* be managed by the scroll view.*/
  @_scrollview = QScrollView.new( self )
  @_scrollview.setGeometry( 0, @_menubar.height,width, height - @_menubar.height )
  @_scribblearea = ScribbleArea.new
  @_scribblearea.setGeometry( 0, 0, 800, 600 )
  @_scrollview.addChild( @_scribblearea )
  @colorChanged = RSignal.new("Object")
  Qt::connect( @colorChanged,
                    @_scribblearea, "setColor"  )
  @save = RSignal.new("const char*")
  Qt::connect( @save,
		@_scribblearea, "slotSave"  )
  @load = RSignal.new("const char*")
  Qt::connect( @load,
		@_scribblearea, "slotLoad" )
  catchEvent
end

def quit()
   QApplication::qApp.quit()
end


def resizeEvent( event )

  #/* When the whole window is resized, we have to rearrange the geometry
  #* in the ScribbleWindow as well. Note that the ScribbleArea does not need
  #* to be changed. */
  @_scrollview.setGeometry( 0, @_menubar.height,
			width, height - @_menubar.height )
end


def slotAbout

  QMessageBox::information( self, "About QtScribble 5",
			"This is the Scribble application\n" + "originaly written by Matthias Kalle Dalheimer\n" + "in \"Programming with Qt\" by O'Relilly & Assoc. Inc.\n"+ "(C) 2000 translated to Ruby/Qt by Nobuyuki Horie\n")
end


def slotAboutQt

  QMessageBox::aboutQt( self, "About Qt" )
end

def fileMenuActivated( item )

  case item
      when Load
	slotLoad
      when Save
        slotSave
   end
end

def helpMenuActivated( item )
   case item
      when About
         slotAbout
      when AboutQt
         slotAboutQt
   end
end

def slotColorMenu( item )

  case item
	when COLOR_MENU_ID_BLACK
	   @colorChanged.sendWith( QColor("black") )	
	when COLOR_MENU_ID_RED
	   @colorChanged.sendWith( QColor("dark red") )
	when COLOR_MENU_ID_BLUE
	   @colorChanged.sendWith( QColor("dark blue") )
	when COLOR_MENU_ID_GREEN
	   @colorChanged.sendWith( QColor("dark green") )
	when COLOR_MENU_ID_YELLOW
	   @colorChanged.sendWith( QColor("yellow") )
	end
end

=begin
/**
  * This is the slot for the menu item File/Load. It opens a
  * QFileDialog to ask the user for a filename and emits a save()
  * signal with the filename as a parameter afterwards.
  */
=end

def slotLoad

  #/* Open a file dialog for loading. The default directory is the
   #* current directory, the filter *.bmp.
   #*/
#  filename = QFileDialog::getOpenFileName( ".", "*.xpm", self )
  fd = QFileDialog.new(".","*.xpm",nil,"fd",true)
  fd.setMode( QFileDialog::ExistingFile )
  ql =QStringList.new
  ql.append("*.xpm")
  ql.append("*.bmp")
  ql.append("*.gif")
  ql.append("*.*")
  fd.setFiltersQStringList(ql)
  fd.show
  filename = fd.selectedFile
  if( !filename.isEmpty )
	@load.sendWith( filename.to_str )
  end
end

=begin
/**
  * This is the save equivalent to slotLoad(). Again we just ask for a
  * filename and emit a signal.
  */
=end
def slotSave

  #/* Open a file dialog for saving. The default directory is the
   #* current directory, the filter *.bmp.
   #*/
  filename = QFileDialog::getSaveFileName( ".", "*.xpm", self )
  if( !filename.isEmpty  )
	@save.sendWith( filename.to_str )
  end
end
end


  QApplication::setStyle(QWindowsStyle.new)
  myapp = QApplication.new( [$0]+ARGV )

  mywidget = ScribbleWindow.new
  mywidget.setGeometry( 50, 50, 400, 400 )

  myapp.setMainWidget( mywidget )
  mywidget.show
  myapp.exec
