nun hat es doch etwas gedauert und an dem eigentlichen Problem habe ich nicht allzuviel gemacht
- Verschieben ist nun ohne vorherige Auswahl möglich. (Der Mittlere Anfasser ist z. Zt. nur Zierde)
Ansonsten habe ich geändert, dass nun die Grafiken nicht während dem Verschieben etc. gezeichnet werden und die Testgrafik automatisch erstellt wird.
Beim Skalieren passieren noch seltsame Dinge, wenn man die Ecken übereinander zieht...
Würde mich freuen, wenn es jemand testet und bin für jeden guten Rat dankbar.
Code: Alles auswählen
; ------------------------------------------------------------
;
; Layout Software - Canvas Vector Test
;
; (c) Phil
;
; ------------------------------------------------------------
;
;- ToDo Liste
; Resize begrenzen bei Übergang zu 0 Breite oder Höhe
; kein Testbild laden, sondern einen Screenshot der Fenster als Testimage verwenden.
; Nur gefüllte Rahmen zeichnen in DrawAll() ermöglichen, ohne Images.besser nur selObj zeichnen.
; wenn kein mousemove, nach 500ms neu ganz zeichnen, sonst nur Rahmen.
; Textdraw testen in Objekt. Evtl mit Bild im Hintergrund.
; Ausdruck ermöglichen in PrintAll()
; Linien hinter Text setzen.
; Erledigt:
; Mausposition global direct bei Draw abfragen. vorallem bei flgCheck.
; Bei RedrawAll Check statt Blank als Zusatzoption auswählen können, nicht alternativ, also flgQuick.b=#False, flgCheck.b=#True
; Bei RedrawSelection check von drawing trennen.
; Bei Resize die Position der Maus auf dem Handle beibehalten.
EnableExplicit
UsePNGImageDecoder()
;- Constants
#TestObjCnt=10
#FlgDrawImages=#True
#testImage = 7
#Handle_Radius=3.0
#Paper_Width=210
#Paper_Height=297
Enumeration DrawMode
#DrawMode_Blank
#DrawMode_NoImages
#DrawMode_OnlySelection
#DrawMode_All
EndEnumeration
Enumeration Mode
#Mode_None
#Mode_Move
#Mode_Resize
#Mode_Pan
#Mode_Zoom
EndEnumeration
;- Gadgets
#G_Canvas=5
;- Structures
Structure Object
name.s
image.i
text.s
x.f
y.f
w.f
h.f
flgMouseover.b
flgSelected.b
EndStructure
;- Global
Global Event.i
Global EventGadget.i
Global EventType.i
Global EventTimer.i
Global gWidth.f
Global gHeight.f
Global gViewWidth.f
Global gViewHeight.f
Global gOldViewMiddleX.f
Global gOldViewMiddleY.f
Global gViewMiddleX.f
Global gViewMiddleY.f
Global gMouseX.f
Global gMouseY.f
Global gOldMouseX.f
Global gOldMouseY.f
Global gRelativeSelObjMouseX.f
Global gRelativeSelObjMouseY.f
Global gScaleKoords.f = 1.0
Global gPanKoordsX.f = 0.0
Global gPanKoordsY.f = 0.0
Global gRelPanKoordsX.f = 0.0
Global gRelPanKoordsY.f = 0.0
Global gCurHandleX.f
Global gCurHandleY.f
Global gRelHandleX.f = 0.0
Global gRelHandleY.f = 0.0
Global gMode.i
Global NewList objList.Object()
Global *gHighestMouseOverObj
Global *gOldSelectedObj.Object ; Hier wird die Adresse des ListenElements gespeichert.
Global *gSelectedObject.Object ; Hier wird die Adresse des ListenElements gespeichert.
Global gFlgSelectedObj.b
Global gFlgMouseOverSelectedObj.b
Global gFlgMouseOverAnyObj.b
Global gFlgMouseOverHandleNb.b
Global gFlgGridSnap.i=#False
Global gOldObj.Object
;- Procedures
Procedure CreateObject()
AddElement(objList())
With objList()
\name = "test"
\image = #testImage
\x = Random(100,10)
\y = Random(100,10)
\w = Random(100,10)
\h = Random(100,10)
EndWith
EndProcedure
Procedure MoveObj()
Protected x.f, y.f
x = gMouseX
y = gMouseY
With objList()
\x=x-gRelativeSelObjMouseX
\y=y-gRelativeSelObjMouseY
If gFlgGridSnap
;Make it eventually snap to a grid??
\x=Round(\x,#PB_Round_Nearest)
\y=Round(\y,#PB_Round_Nearest)
EndIf
EndWith
EndProcedure
Procedure ResizeObj(HandleNb.i)
Protected x.f, y.f
x = gMouseX-gRelHandleX
y = gMouseY-gRelHandleY
With objList()
Select HandleNb
Case 1
\x = x
\y = y
\w = (gOldObj\x - x + gOldObj\w)
\h = (gOldObj\y - y + gOldObj\h)
If \w < 10: \w = 10 :EndIf
Case 2
\x = gOldObj\x
\y = y
\w = (x-gOldObj\x)
\h = (gOldObj\y - y + gOldObj\h)
Case 3
\x = gOldObj\x
\y = gOldObj\y
\w = (x-gOldObj\x)
\h = (y-gOldObj\y)
Case 4
\x = x
\y = gOldObj\y
\w = (gOldObj\x - x + gOldObj\w)
\h = (y-gOldObj\y)
EndSelect
EndWith
EndProcedure
Procedure RedrawBackground(drawMode.b)
Select drawMode
Case #DrawMode_All,#DrawMode_OnlySelection,#DrawMode_NoImages
;Clear whole Canvas and draw sheet of Paper.
VectorSourceColor(RGBA(100,100,100, 255))
FillVectorOutput()
VectorSourceColor(RGBA(50,50,50, 255))
AddPathBox(1.5,1.5,#Paper_Width,#Paper_Height)
FillPath()
VectorSourceColor(RGBA(240,240,240, 255))
AddPathBox(0,0,#Paper_Width,#Paper_Height)
FillPath()
Case #DrawMode_Blank
EndSelect
EndProcedure
Procedure RedrawObjects(drawMode.b, flgCheck.b)
Protected x.f, y.f, result.b
Protected colorNorm.l, colorMO.l, colorHigh.l,curColor.l
colorNorm=RGBA(0, 255, 0, 255)
colorMO = RGBA(255, 255, 0, 255)
colorHigh= RGBA(255, 50, 0, 255)
x = gMouseX
y = gMouseY
;Here starts checking.
If flgCheck
gFlgMouseOverAnyObj = #False
;Check all Objects for MouseOver by silently drawing the frames.
ForEach objList()
With objList()
AddPathBox(\x, \y,\w ,\h)
;If Mode_Move, set new position of selObj
If @objList()=*gSelectedObject
Select gMode
Case #Mode_Move
MoveObj()
Case #Mode_Resize
ResizeObj(gFlgMouseOverHandleNb)
EndSelect
EndIf
If IsInsidePath(x, y, #PB_Coordinate_User)
\flgMouseover=#True
*gHighestMouseOverObj=@objList()
gFlgMouseOverAnyObj=#True
Else
\flgMouseover=#False
EndIf
ResetPath(); No drawing, just checking.
EndWith
Next
EndIf
;Here starts real drawing.
If DrawMode<>#DrawMode_Blank
ForEach objList()
With objList()
;Draw frame around Object according to Mouseover state.
AddPathBox(\x, \y,\w ,\h)
If \flgMouseover
If @objList()=*gHighestMouseOverObj ; If Object is highest, colour differently.
curColor=colorHigh
Else
curColor=colorMO
EndIf
Else
curColor=colorNorm
EndIf
VectorSourceColor(RGBA(200,200,200,255))
FillPath(#PB_Path_Preserve)
VectorSourceColor(curColor)
StrokePath(ConvertCoordinateX(0.4,0,#PB_Coordinate_Output,#PB_Coordinate_User)-ConvertCoordinateX(0,0,#PB_Coordinate_Output,#PB_Coordinate_User))
;Draw Image and PathBox
If DrawMode=#DrawMode_All
MovePathCursor(\x,\y)
DrawVectorImage(ImageID(\image),255,Abs(\w),Abs(\h))
EndIf
EndWith
Next
EndIf
EndProcedure
Procedure RedrawSelection(DrawMode.b,flgCheck.b)
Protected hR.f
Protected x.f, y.f
PushListPosition(objList())
x = gMouseX
y = gMouseY
hR = ConvertCoordinateX(#Handle_Radius,0,#PB_Coordinate_Output,#PB_Coordinate_User)-ConvertCoordinateX(0,0,#PB_Coordinate_Output,#PB_Coordinate_User)
gFlgMouseOverHandleNb=#False
If gFlgSelectedObj
ChangeCurrentElement(objList(),*gSelectedObject)
With objList()
If flgCheck
;BlankDraw HandleCircles around selectedObject and check for MouseOver.
AddPathCircle(\x,\y,hR)
If Not gFlgMouseOverHandleNb And IsInsidePath(x, y, #PB_Coordinate_User) : gFlgMouseOverHandleNb=1 : EndIf
AddPathCircle(\x+\w,\y,hR)
If Not gFlgMouseOverHandleNb And IsInsidePath(x, y, #PB_Coordinate_User) : gFlgMouseOverHandleNb=2 : EndIf
AddPathCircle(\x+\w,\y+\h,hR)
If Not gFlgMouseOverHandleNb And IsInsidePath(x, y, #PB_Coordinate_User) : gFlgMouseOverHandleNb=3 : EndIf
AddPathCircle(\x,\y+\h,hR)
If Not gFlgMouseOverHandleNb And IsInsidePath(x, y, #PB_Coordinate_User) : gFlgMouseOverHandleNb=4 : EndIf
AddPathCircle(\x+\w/2,\y+\h/2,hR)
If Not gFlgMouseOverHandleNb And IsInsidePath(x, y, #PB_Coordinate_User) : gFlgMouseOverHandleNb=5 : EndIf
ResetPath()
EndIf
If DrawMode<>#DrawMode_Blank
;Draw frame around Object.
AddPathBox(\x,\y,\w,\h)
VectorSourceColor(RGBA(50,50,255,100))
DashPath(ConvertCoordinateX(0.6,0,#PB_Coordinate_Output,#PB_Coordinate_User)-ConvertCoordinateX(0,0,#PB_Coordinate_Output,#PB_Coordinate_User),2.0)
;Draw HandleCircles round selectedObject and check for MouseOver.
AddPathCircle(\x,\y,hR)
AddPathCircle(\x+\w,\y,hR)
AddPathCircle(\x+\w,\y+\h,hR)
AddPathCircle(\x,\y+\h,hR)
AddPathCircle(\x+\w/2,\y+\h/2,hR)
VectorSourceColor(RGBA(50,50,255,150))
FillPath()
EndIf
EndWith
EndIf
PopListPosition(objList())
EndProcedure
Procedure.b RedrawAll(drawMode=#DrawMode_All,flgCheck.b=#True); Gives #True, if Changes were made while checking.
Protected x.f,y.f,result.b = #False, start.i
start = ElapsedMilliseconds()
x=GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseX)
y=GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseY)
If StartVectorDrawing(CanvasVectorOutput(#G_Canvas,#PB_Unit_Millimeter))
Protected i.i, imgWidth.f, imgHeight.f
;Scale everything according to ScaleKoords (by Mousewheel).
ScaleCoordinates(gScaleKoords,gScaleKoords)
; Prepare to pan, so the middle of the Canvas stays where it is, when zooming.
If gMode=#Mode_Zoom
gPanKoordsX=(ConvertCoordinateX(450,450,#PB_Coordinate_Device,#PB_Coordinate_User)-gViewMiddleX) ;neue gviewMiddle - alte gviewMiddle
gPanKoordsY=(ConvertCoordinateY(450,450,#PB_Coordinate_Device,#PB_Coordinate_User)-gViewMiddleY)
gMode=#Mode_None
EndIf
;Pan to the right spot.
TranslateCoordinates(gPanKoordsX+gRelPanKoordsX,gPanKoordsY+gRelPanKoordsY)
;Refresh the mousePos in mm on the canvas.
gMouseX = ConvertCoordinateX(x,y,#PB_Coordinate_Device,#PB_Coordinate_User)
gMouseY = ConvertCoordinateY(x,y,#PB_Coordinate_Device,#PB_Coordinate_User)
If gMode=#Mode_Pan
gRelPanKoordsX=gMouseX-ConvertCoordinateX(gOldMouseX,gOldMouseY,#PB_Coordinate_Device,#PB_Coordinate_User)
gRelPanKoordsY=gMouseY-ConvertCoordinateY(gOldMouseX,gOldMouseY,#PB_Coordinate_Device,#PB_Coordinate_User)
EndIf
; gWidth = VectorOutputWidth()
; gHeight = VectorOutputHeight()
;Refresh the new middle of the Canvas in mm.
gViewMiddleX = ConvertCoordinateX(450,450,#PB_Coordinate_Device,#PB_Coordinate_User)
gViewMiddleY = ConvertCoordinateY(450,450,#PB_Coordinate_Device,#PB_Coordinate_User)
RedrawBackground(drawMode)
;Draw objects and check for mouseover.
RedrawObjects(drawMode,flgCheck)
RedrawSelection(drawMode,flgCheck)
StopVectorDrawing()
EndIf
;If changes there, then result is #True.
If flgCheck
Static NewList oldObjList.Object()
ResetList(oldObjList())
If ListSize(objList())<>ListSize(oldObjList())
; Debug "ungleiche Listsize"
Else
ForEach objList()
With objList()
NextElement(oldObjList())
If \flgMouseover<>oldObjList()\flgMouseover Or \x<>oldObjList()\x Or \y<>oldObjList()\y Or \w<>oldObjList()\w Or \h<>oldObjList()\h
result=#True
Break
EndIf
EndWith
Next
EndIf
If *gSelectedObject<>*gOldSelectedObj
result=#True
; Debug "selObj"
EndIf
*gOldSelectedObj=*gSelectedObject
CopyList(objList(),oldObjList())
EndIf
Debug "DrawZeit: " + Str(ElapsedMilliseconds()-start)
ProcedureReturn result
EndProcedure
Procedure SetRelHandle()
ChangeCurrentElement(objList(),*gSelectedObject)
With objList()
Select gFlgMouseOverHandleNb
Case 1
gRelHandleX=gMouseX-\x
gRelHandleY=gMouseY-\y
Case 2
gRelHandleX=gMouseX-\x-\w
gRelHandleY=gMouseY-\y
Case 3
gRelHandleX=gMouseX-\x-\w
gRelHandleY=gMouseY-\y-\h
Case 4
gRelHandleX=gMouseX-\x
gRelHandleY=gMouseY-\y-\h
EndSelect
EndWith
EndProcedure
Procedure SetRelMousePos()
ChangeCurrentElement(objList(),*gSelectedObject)
gRelativeSelObjMouseX = gMouseX- objList()\x
gRelativeSelObjMouseY = gMouseY- objList()\y
EndProcedure
Procedure PrintAll()
Debug "PrintAll"
EndProcedure
;- Main
Define file.s
Define i.i
If OpenWindow(0, 0, 0, 900, 900, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered|#PB_Window_MaximizeGadget)
CanvasGadget(#G_Canvas, 0, 0, 900, 900,#PB_Canvas_Keyboard|#PB_Canvas_Container)
AddWindowTimer(0,0,500)
; file = OpenFileRequester("Wähle Bilddatei (.png) aus.",GetCurrentDirectory(),"png-Image|*.png",0)
; file = "image.png"
; If Not LoadImage(#testImage, file):MessageRequester("Fehler", "Ohne Bild kein Programm! ;-)"):End:EndIf
; ResizeImage(#testImage,500,700)
;
gMode = #Mode_None
CreateImage(#testImage,500,700,24,RGB(255,255,255))
For i=0 To #TestObjCnt-1
CreateObject()
Next
RedrawAll()
StartDrawing(ImageOutput(#testImage))
DrawImage(GetGadgetAttribute(#G_Canvas,#PB_Canvas_Image),0,0)
StopDrawing()
;Initial drawing
RedrawAll()
;- Event-Loop
Repeat
Event = WaitWindowEvent()
EventGadget = EventGadget()
EventType = EventType()
EventTimer= EventTimer()
; If Event=#PB_Event_Timer
; Select EventTimer
; Case 0
; RedrawAll(GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseX),GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseY),#True,#False)
; RedrawAll(GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseX),GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseY),#False,#False)
;
; EndSelect
; EndIf
;
If Event=#PB_Event_Gadget
Select EventGadget
Case #G_Canvas ;CanvasGadget Event
Select EventType
Case #PB_EventType_MouseMove
;Refresh Canvas on every move. and check for MouseOver!
If RedrawAll(#DrawMode_Blank,#True)
; Debug FormatDate("%hh:%ii:%ss", Date())
; RedrawAll(#DrawMode_All,#False)
EndIf
; RedrawAll(#DrawMode_NoImages)
;If Handle MouseOver, show hand symbol.
If gFlgMouseOverHandleNb
SetGadgetAttribute(#G_Canvas,#PB_Canvas_Cursor,#PB_Cursor_Hand)
Else
SetGadgetAttribute(#G_Canvas,#PB_Canvas_Cursor,#PB_Cursor_Default)
EndIf
;If MouseLeftButton, redrawAll for moved object
If GetGadgetAttribute(#G_Canvas,#PB_Canvas_Buttons) = #PB_Canvas_LeftButton
RedrawAll(#DrawMode_NoImages)
EndIf
;If MouseMiddleButton, redrawAll for panned view
If GetGadgetAttribute(#G_Canvas,#PB_Canvas_Buttons) = #PB_Canvas_MiddleButton
RedrawAll(#DrawMode_NoImages)
EndIf
Case #PB_EventType_LeftButtonDown
;Only set new selected Object if LeftClick was not on selObj or Handle!
If Not gFlgSelectedObj Or Not(gFlgMouseOverHandleNb Or *gSelectedObject\flgMouseOver)
*gSelectedObject=*gHighestMouseOverObj
gFlgSelectedObj=#True
EndIf
;If clicked outside of Objects and Handles, unselect Objects.
If gFlgSelectedObj And Not gFlgMouseOverAnyObj And Not gFlgMouseOverHandleNb
*gSelectedObject=0
gFlgSelectedObj=#False
EndIf
;If clicked on selObj, start move and register rel pos of Cursor.
If gFlgSelectedObj And *gSelectedObject\flgMouseOver
gMode = #Mode_Move
SetRelMousePos()
EndIf
If gFlgMouseOverHandleNb And gFlgSelectedObj
ChangeCurrentElement(objList(),*gSelectedObject)
gOldObj=objList(); alte Pos und Dim merken für Resize
SetRelHandle()
gMode = #Mode_Resize
EndIf
Case #PB_EventType_LeftButtonUp
gMode = #Mode_None
RedrawAll()
Case #PB_EventType_MiddleButtonDown
gMode = #Mode_Pan
gRelPanKoordsX=0
gRelPanKoordsY=0
gOldMouseX=GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseX)
gOldMouseY=GetGadgetAttribute(#G_Canvas,#PB_Canvas_MouseY)
Case #PB_EventType_MiddleButtonUp
gMode = #Mode_None
gPanKoordsX+gRelPanKoordsX
gRelPanKoordsX=0
gPanKoordsY+gRelPanKoordsY
gRelPanKoordsY=0
RedrawAll()
Case #PB_EventType_MouseWheel
Define delta.i
delta =GetGadgetAttribute(#G_Canvas,#PB_Canvas_WheelDelta)
If GetGadgetAttribute(#G_Canvas,#PB_Canvas_Modifiers) = #PB_Canvas_Control
gMode = #Mode_Zoom
gScaleKoords*(1.0+delta*0.2)
If gScaleKoords<0.3: gScaleKoords=0.3:EndIf
If gScaleKoords>3.0: gScaleKoords=3.0:EndIf
RedrawAll();#DrawMode_NoImages)
EndIf
Case #PB_EventType_KeyDown
If GetGadgetAttribute(#G_Canvas,#PB_Canvas_Modifiers) = #PB_Canvas_Control And GetGadgetAttribute(#G_Canvas,#PB_Canvas_Key) = #PB_Shortcut_P
PrintAll()
EndIf
EndSelect
EndSelect
EndIf
Delay(5)
Until Event = #PB_Event_CloseWindow
EndIf