#include <qdatetime.h>
#include <qmainwindow.h>
#include <qstatusbar.h>
#include <qmessagebox.h>
#include <qmenubar.h>
#include <qapplication.h>
#include <qkeycode.h>
#include <qpainter.h>
#include <qlabel.h>
#include <qimage.h>
#include <qprogressdialog.h>
#include "canvas.h"

#include <stdlib.h>

require "qt2"
include Qt2
require "qt2canvas"
include Qt2canvas

#// We use a global variable to save memory - all the brushes and pens in
#// the mesh are shared.
$tb = nil
$tp = nil


class EdgeItem < QCanvasLine
@@c = 0
def initialize(canvas)
   super(canvas)
   @@c += 1
    setPen( $tp )
    setBrush( $tb )
    #from.addOutEdge( self )
    #to.addInEdge( self )
    #setPoints( int(from.x()), int(from.y()), int(to.x()), int(to.y()) )
    #setZ( 127 )
end
def fromTo(from, to)
    from.addOutEdge( self )
    to.addInEdge( self )
    setPoints( (from.x().to_i), (from.y().to_i), (to.x().to_i), (to.y().to_i) )
    setZ( 127 )
    self
end
def moveBy(double1, double2)
    #//nothing
end

def setFromPoint( x, y )
    setPoints( x,y, endPoint().x(), endPoint().y() )
end
def setToPoint( x, y )
    setPoints( startPoint().x(), startPoint().y(), x, y )
end
def count()
   @@c
end

end

ImageRTTI = 984376


class ImageItem < QRCanvasRectangle

def initialize(canvas )
    super( canvas )
    #@image = img

    #setSize( @image.width(), @image.height() )
end
def setImage(img)
   @image = img
    setSize( @image.width(), @image.height() )
#ifndef _WS_QWS_
    @pixmap = QPixmap.new(nil)
    @pixmap.convertFromImage(@image, Qt::OrderedAlphaDither)
#endif
end
def drawShape( p )
#// On Qt/Embedded, we can paint a QImage as fast as a QPixmap,
#// but on other platforms, we need to use a QPixmap.
#ifdef _WS_QWS_
    #p.drawImage( (x().to_i), (y().to_i), @image, 0, 0, -1, -1) #, OrderedAlphaDither )
#else
    p.drawPixmap( (x().to_i), (y().to_i), @pixmap )
#endif
end

def hit( p )

    ix = p.x()-int(x())
    iy = p.y()-int(y())
    if ( !@image.valid( ix , iy ) )
	return FALSE
    end
    pixel = image.pixel( ix, iy )
    return qAlpha( pixel ) != 0
end

end


class NodeItem <  QCanvasEllipse
#QCanvasEllipse

def initialize ( x,y,canvas )
    super( 6,6,canvas )
    @inList = []
    @outList = []
    setPen( $tp )
    setBrush( $tb )
   #setBrush( QBrush.new(QColor.new(z,z,z,QColor::Rgb)) )
   #setPen( QPen.new(QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8, QColor::Rgb), 6) )
   # i.setZ(z)
   # i.show()
    setZ( 128 )
    show()
end
def moveBy(dx, dy)
    super( dx, dy )

    #QListIterator<EdgeItem> it1( inList )
    it1 = 0
    #EdgeItem *edge
    while (!((edge = @inList[it1]).nil?) )
	it1 += 1
	edge.setToPoint( (x().to_i), (y().to_i) )
    end
    #QListIterator<EdgeItem> it2( outList )
    it2 = 0
    while (!(( edge = @outList[it2]).nil? ))
	it2 += 1
	edge.setFromPoint( (x().to_i), (y().to_i) )
    end
end

def addInEdge( edge)
   @inList.push(edge)
end
def addOutEdge( edge)
   @outList.push( edge)
end
def center
   boundingRect().center()
end

end

class FigureEditor < QRCanvasView
    #Q_OBJECT
   @@canvasItems = []
def initialize( c, parent=nil, name="", f=0)
      #super( c, parent, name, f)
      #@m = MyWidget.new
      #addChild(@m)
       #@m.show
      catchEvent
end
def itemList
   @@canvasItems
end

def contentsMousePressEvent( e )

    l=canvas().collisions(e.pos())
    larray = l.asArray
    larray.each { |it|
        if(it.rtti() != ImageRTTI)
           item = it
           #if(item.hit(e.pos()))
              #next
           #end
            it.setSelected(TRUE)
           @moving = checkItems
            it.setSelected(FALSE)
           @moving_start = e.pos()
           return
        end
     }
        @moving = nil


end

def checkItems

@@canvasItems.each {|i|
   if(i.selected())
#      i.setSelected(FALSE)
      return i
   end
}

end

def clear()
GC.disable
@@canvasItems.each{|i|
   i.hide()
   #deleteQtObj(i)
   i = nil
}
@@canvasItems = []
BouncyLogo.clearAll

GC.enable
GC.start
GC.disable

    list = canvas().allItems()
    larray = list.asArray()
    larray.each {|it|
     #deleteQtObj(it)
     it = nil
     }

GC.enable
GC.start
end


def contentsMouseMoveEvent( e )

    if ( !@moving.nil? )
              pos = QPoint.new(e.pos().x(), e.pos().y())
              mx = pos.x() - @moving_start.x()
              my = pos.y() - @moving_start.y()
	@moving.moveBy(mx, my)
             @moving_start = pos
	#@moving.moveBy(e.pos().x() - @moving_start.x(),
		       #e.pos().y() - @moving_start.y())
	#@moving_start = e.pos()
	canvas().update()
    end
end
end


class BouncyLogo < QCanvasSprite
@@logo_rtti = 1234
@@bouncyLogos = []

def BouncyLogo.clearAll
   @@bouncyLogos.each {|b|
       b = nil
    }
   @@bouncyLogos = []
end

def initialize (parent, canvas )
    super(nil,canvas)

    @@logo = QCanvasPixmapArray.new("qt-trans.xpm")
    setSequence(@@logo)
    setAnimated(TRUE)
    initPos()
    @timer = QTimer.new(nil)
    @timer.start(50)
    connect( @timer, QSIGNAL("timeout()"), self, "timeout" )
    @@bouncyLogos.push(self)
end

def checkItems
  @@bouncyLogos.each {|i|
   if(i.selected())
#      i.setSelected(FALSE)
      return i
   end
  }
  nil
end

def timeout
   advance(0)
end


def rtti()

    return @@logo_rtti
end

def initPos()

    initSpeed()
    trial=1000
    begin
	move(rand(1000)%canvas().width(),rand(1000)%canvas().height())
	advance(0)
    end while (0 == (trial = trial - 1) && xVelocity()==0.0 && yVelocity()==0.0)
end

def initSpeed()

    @speed = 4.0
    d = (rand(1000)%1024) / 1024.0
    setVelocity( d*@speed*2-@speed, (1-d)*@speed*2-@speed )
end

def advance( stage)

    case ( stage )
      when 0

	vx = xVelocity()
	vy = yVelocity()

	if ( vx == 0.0 && vy == 0.0 )
	    #// stopped last turn
	    initSpeed()
	    vx = xVelocity()
	    vy = yVelocity()
	end

	nx = x() + vx
	ny = y() + vy
	if ( nx < 0 || nx >= canvas().width() )
	    vx = -vx
             end
	if ( ny < 0 || ny >= canvas().height() )
	    vy = -vy
             end

	for bounce in 0..3 #(int bounce=0 bounce<4 bounce++)
	    l=collisions(FALSE).asArray
	    #for (QCanvasItemList::Iterator it=l.begin() it!=l.end() ++it)
                 l.each {|it|
                          it.setSelected(TRUE)
		hit = checkItems
                          it.setSelected(FALSE)
		if ( !(hit.nil?) && hit.rtti()== @@logo_rtti && hit.collidesWith(self) )
		    case ( bounce )
		      when 0
			vx = -vx
			
		      when 1
			vy = -vy
			vx = -vx
			
		      when 2
			vx = -vx
			
		      when 3
			#// Stop for self turn
			vx = 0
			vy = 0
			
		    end
		    setVelocity(vx,vy)
		
		end
	    }
	end

	if ( x()+vx < 0 || x()+vx >= canvas().width() )
	    vx = 0
             end
	if ( y()+vy < 0 || y()+vy >= canvas().height() )
	    vy = 0
             end

	setVelocity(vx,vy)


      when 1
	QCanvasItem::advance(stage)

    end
end

end

class Main < QMainWindow
    #Q_OBJECT
     @@about = nil
     $tb = nil
     $tp = nil
def initialize (parent=nil, name="", f=0)
    super(parent,name,f)
    #@canvas = c
    @img = []
    #$butterfly_fn = "butterfly.png"
    #$logo_fn = "qtlogo.png"
    #@editor = FigureEditor.new(canvas,self)
    menu = menuBar()

    @file = QPopupMenu.new
    @file.insertItem("&Fill canvas", self, "init()", CTRL+Key_F)
    @file.insertItem("&Erase canvas", self, "clear()", CTRL+Key_E)
    @file.insertItem("&New view", self, "newView()", CTRL+Key_N)
    @file.insertSeparator()
    @file.insertItem("E&xit", QApplication::qApp, "quit()", CTRL+Key_Q)

    menu.insertItem("&File", @file)

    @edit = QPopupMenu.new
    @edit.insertItem("Add &Circle", self, "addCircle", CTRL+Key_C)
    @edit.insertItem("Add &Hexagon", self, "addHexagon()", CTRL+Key_H)
    @edit.insertItem("Add &Polygon", self, "addPolygon()", CTRL+Key_P)
    @edit.insertItem("Add &Text", self, "addText()", CTRL+Key_T)
    @edit.insertItem("Add &Line", self, "addLine()", CTRL+Key_L)
    @edit.insertItem("Add &Rectangle", self, "addRectangle()", CTRL+Key_R)
    @edit.insertItem("Add &Sprite", self, "addSprite()", CTRL+Key_S)
    @edit.insertItem("Create &Mesh", self, "addMesh()" )
    @edit.insertItem("Add &Alpha-blended image", self, "addButterfly()", CTRL+Key_A)
    @edit.insertSeparator()
    @edit.insertItem("&Enlarge", self, "enlarge()", CTRL+Key_Plus)
    @edit.insertItem("Shr&ink", self, "shrink()", CTRL+Key_Minus)
    menu.insertItem("&Edit", @edit)

    @options = QPopupMenu.new
    @dbf_id = @options.insertItem("Double buffer", self, "toggleDoubleBuffer()")
    @options.setItemChecked(@dbf_id, TRUE)
    menu.insertItem("&Options",@options)

    menu.insertSeparator()

    @help = QPopupMenu.new
    @help.insertItem("&About", self, "help", Key_F1)
    @help.setItemChecked(@dbf_id, TRUE)
    menu.insertItem("&Help",@help)

    statusBar()

    #setCentralWidget(@editor)

    #init()
    #catchEvent
end
def quit_program
   QApplication::qApp.quit
end
def setCanvas(c)
   @canvas = c
   @editor = FigureEditor.new(@canvas, self)
   setCentralWidget(@editor)
   init()
end

def newView()

    #// Open a new view... have it delete when closed.
    m = Main.new(nil, "", WDestructiveClose)
    m.setCanvas(@canvas)
    QApplication::qApp.setMainWidget(m)
    m.show()
    QApplication::qApp.setMainWidget(nil)
end

def clear()

    @editor.clear()
end

def help()
    if(@@about.nil?)
    @@about = QMessageBox.new( "Qt Canvas Example", ("<h3>The QCanvas classes example</h3>" + "<ul>" + "<li> Press CTRL-S for some sprites." + "<li> Press CTRL-C for some circles." + "<li> Press CTRL-L for some lines." + "<li> Drag the objects around." + "<li> Read the code!" + "</ul>"), QMessageBox::Information, 1, 0, 0, self, "", FALSE )
     end
    @@about.setButtonText( 1, "Dismiss" )
    @@about.show()
end

def aboutQt()

    QMessageBox::aboutQt( self, "Qt Canvas Example" )
end

def toggleDoubleBuffer()

    s = !@options.isItemChecked(@dbf_id)
    @options.setItemChecked(@dbf_id,s)
    @canvas.setDoubleBuffering(s)
end

def enlarge()

    @canvas.resize(@canvas.width()*4/3, @canvas.height()*4/3)
end

def shrink()

    @canvas.resize(@canvas.width()*3/4, @canvas.height()*3/4)
end

def addSprite()

    i = BouncyLogo.new(nil, @canvas)
    i.setZ(rand(1000)%256)
    i.show()
    @editor.itemList.push(i)
end


def addButterfly()

    if ( $butterfly_fn.size == 0 )
	return
    end
    if ( @img.size == 0 )
	#img = new QImage[4]
	@img[0] = QImage.new
             @img[0].load( $butterfly_fn )
	@img[1] = @img[0].smoothScale( (@img[0].width()*0.75).to_i,
		(@img[0].height()*0.75).to_i )
	@img[2] = @img[0].smoothScale( (@img[0].width()*0.5).to_i,
		(@img[0].height()*0.5).to_i )
	@img[3] = @img[0].smoothScale( (@img[0].width()*0.25).to_i,
		(@img[0].height()*0.25).to_i )
    end
    i = ImageItem.new(@canvas)
    ri =  rand(1000)%4
    i.setImage(@img[ri])
    i.move(rand(1000)%(@canvas.width()-@img[ri].width()),
	    rand(1000)%(@canvas.height()-@img[ri].height()))
    i.setZ(rand(1000)%256+250)
    i.show()
    @editor.itemList.push(i)
end

def addLogo()

    if ( $logo_fn.size == 0 )
	return
    end
    @img2 = []
    if ( @img2.size == 0 )
	#img = new QImage[4]
	@img2[0] = QImage.new
             @img2[0].load( $logo_fn )
	@img2[1] = @img2[0].smoothScale( (@img2[0].width()*0.75).to_i,
		(@img2[0].height()*0.75).to_i )
	@img2[2] = @img2[0].smoothScale( (@img2[0].width()*0.5).to_i,
		(@img2[0].height()*0.5).to_i )
	@img2[3] = @img2[0].smoothScale( (@img2[0].width()*0.25).to_i,
		(@img2[0].height()*0.25).to_i )
    end
    i = ImageItem.new(@canvas)
    ri = rand(1000)%4
    i.setImage(@img2[ri])
    i.move(rand(1000)%(@canvas.width()-@img2[ri].width()),
	    rand(1000)%(@canvas.height()-@img2[ri].width()))
    i.setZ(rand(1000)%256+256)
    i.show()
    @editor.itemList.push(i)
end



def addCircle()

    i = QCanvasEllipse.new(50,50,@canvas)
    i.setBrush( QBrush.new( QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8,QColor::Rgb )))
    i.move(rand(1000)%@canvas.width(),rand(1000)%@canvas.height())
    i.setZ(rand(1000)%256)

    i.show()
    @editor.itemList.push(i)
end

def addHexagon()

    i = QCanvasPolygon.new(@canvas)
    size = @canvas.width() / 25
    pa = QPointArray.new(6)
    pa.setPoint(0,QPoint.new(2*size,0))
    pa.setPoint(1,QPoint.new(size,-size*173/100))
    pa.setPoint(2,QPoint.new(-size,-size*173/100))
    pa.setPoint(3,QPoint.new(-2*size,0))
    pa.setPoint(4,QPoint.new(-size,size*173/100))
    pa.setPoint(5,QPoint.new(size,size*173/100))
    i.setPoints(pa)
#    i.setBrush( QBrush.new(QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8, QColor::Rgb)) )
    i.setBrush( QBrush.new(QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8)) )
    i.move(rand(1000)%@canvas.width(),rand(1000)%@canvas.height())
    i.setZ(rand(1000)%256)
    i.show()
    @editor.itemList.push(i)

end

def addPolygon()

    i = QCanvasPolygon.new(@canvas)
    size = @canvas.width()/2
    pa = QPointArray.new(6)
    pa.setPoint(0, QPoint.new(0,0) )
    pa.setPoint(1, QPoint.new(size,size/5) )
    pa.setPoint(2, QPoint.new(size*4/5,size) )
    pa.setPoint(3, QPoint.new(size/6,size*5/4)  )
    pa.setPoint(4, QPoint.new(size*3/4,size*3/4) )
    pa.setPoint(5, QPoint.new(size*3/4,size/4) )
    i.setPoints(pa)
    i.setBrush( QBrush.new(QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8 )) )
    i.move(rand(1000)%@canvas.width(),rand(1000)%@canvas.height())
    i.setZ(rand(1000)%256)
    i.show()
    @editor.itemList.push(i)

end

def addText()

    i = QCanvasText.new(@canvas)
    i.setText("QCanvasText")
    i.move(rand(1000)%@canvas.width(),rand(1000)%@canvas.height())
    i.setZ(rand(1000)%256)
    i.show()
    @editor.itemList.push(i)

end

def addLine()

    i = QCanvasLine.new(@canvas)
    i.setPoints( rand(1000)%@canvas.width(), rand(1000)%@canvas.height(),
                  rand(1000)%@canvas.width(), rand(1000)%@canvas.height() )
    i.setPen( QPen.new(QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8), 6) )
    i.setZ(rand(1000)%256)
    i.show()
    @editor.itemList.push(i)

end

def addMesh()

    x0 = 0
    y0 = 0

    if ( $tb.nil? )
      $tb = QBrush.new( Qt::red )
    end
    if ( $tp.nil? )
      $tp = QPen.new( Qt::black )
    end
    nodecount = 0

    w = @canvas.width()
    h = @canvas.height()

    dist = 30
    rows = h / dist
    cols = w / dist

#ifndef QT_NO_PROGRESSDIALOG
 QApplication::qApp.processEvents()
    @progress = QProgressDialog.new( "Creating mesh...", "Abort", rows, self, "progress", TRUE )
#endif
QApplication::qApp.processEvents()
    #QArray<NodeItem*> lastRow(cols)
    lastRow = []
    lastRow[0] = el = NodeItem.new(6,6,@canvas)
    @editor.itemList.push(el)
    el = nil
    prev = nil
    for j in 0..(rows - 1) #( int j = 0 j < rows j++ )
	n = j%2 ? (cols - 1) : cols
	#NodeItem *prev = 0
             prev = nil
	for i in 0..(n-1) #( int i = 0 i < n i++ )
	    el = NodeItem.new(6,6,@canvas )
	    nodecount += 1
	    r = rand(1000)
	    xrand = r % 20
	    yrand = (r/20) %20
	    el.move( xrand + x0 + i*dist + (j%2 ? dist/2 : 0 ),
		      yrand + y0 + j*dist )
                 @editor.itemList.push(el)
	    if ( j >= 0 )
		if ( i < cols-1 )
                           if(lastRow[i].nil?)
                           else
		    ne = EdgeItem.new( @canvas).fromTo(lastRow[i], el)
                              ne.show()
		    @editor.itemList.push(ne)
                           end
                          end
		if ( j%2 )
                           if(lastRow[i+1].nil?)
                           else
		    ne = EdgeItem.new(@canvas).fromTo( lastRow[i+1], el )
                              ne.show()
                              @editor.itemList.push(ne)
                           end

                           else if ( i > 0 )
                           if(lastRow[i-1].nil?)
                           else
		    ne = EdgeItem.new(@canvas).fromTo( lastRow[i-1], el)
                              ne.show()
                              @editor.itemList.push(ne)
                           end
                          end
	    end
	    if ( !prev.nil?)
		ne = EdgeItem.new( @canvas).fromTo(prev, el)
                          ne.show()
                          @editor.itemList.push(ne)
	    end
	    if ( i > 0 )
                     lastRow[i-1] = prev
                 end
	    prev = el
	    el.show()
                 #@editor.itemList.push(el)
	end
	lastRow[n-1] = prev
#ifndef QT_NO_PROGRESSDIALOG
	@progress.setProgress( j )
             QApplication::qApp.processEvents()
	if ( @progress.wasCancelled() )
	    break
             end
#endif
      end
    end

#ifndef QT_NO_PROGRESSDIALOG
    @progress.setProgress( rows )
    QApplication::qApp.processEvents()

#endif
    #// qDebug( "%d nodes, %d edges", nodecount, EdgeItem::count() )

end

def addRectangle()

    i = QCanvasRectangle.new( rand(1000)%@canvas.width(),rand(1000)%@canvas.height(),
			    @canvas.width()/5,@canvas.width()/5,@canvas)
    z = rand(1000)%256
    i.setBrush( QBrush.new(QColor.new(z,z,z)) )
    i.setPen( QPen.new(QColor.new(rand(1000)%32*8,rand(1000)%32*8,rand(1000)%32*8), 6) )
    i.setZ(z)
    i.show()
    @editor.itemList.push(i)
end

def init()

    clear()

    @r=24
    srand(@r += 1)

    for i in 0..(@canvas.width() / 56 - 1) #( i=0 i<@canvas.width() / 56 i++)
	addButterfly()
    end
    for i in 0..(@canvas.width() / 85 -1) #( i=0 i<@canvas.width() / 85 i++)
	addHexagon()
    end
    for i in 0..(@canvas.width() / 128 - 1) #( i=0 i<@canvas.width() / 128 i++)
	addLogo()
    end
end

end
