516 lines
14 KiB
Rexx
Executable File
516 lines
14 KiB
Rexx
Executable File
/*----------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Copyright (c) 2011-2014 Rexx Language Association. All rights reserved. */
|
|
/* */
|
|
/* This program and the accompanying materials are made available under */
|
|
/* the terms of the Common Public License v1.0 which accompanies this */
|
|
/* distribution. A copy is also available at the following address: */
|
|
/* https://www.oorexx.org/license.html */
|
|
/* */
|
|
/* Redistribution and use in source and binary forms, with or */
|
|
/* without modification, are permitted provided that the following */
|
|
/* conditions are met: */
|
|
/* */
|
|
/* Redistributions of source code must retain the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer. */
|
|
/* Redistributions in binary form must reproduce the above copyright */
|
|
/* notice, this list of conditions and the following disclaimer in */
|
|
/* the documentation and/or other materials provided with the distribution. */
|
|
/* */
|
|
/* Neither the name of Rexx Language Association nor the names */
|
|
/* of its contributors may be used to endorse or promote products */
|
|
/* derived from this software without specific prior written permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
|
/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
|
|
/* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
|
|
/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
|
|
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
|
|
/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
|
|
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
|
|
/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
|
|
/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
|
/* */
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* This example program demonstrates one approach to adding drag-and-drop to an
|
|
* ooDialog program using the .Mouse class.
|
|
*/
|
|
|
|
sd = locate()
|
|
.application~setDefaults('O', sd'dragNdrop.h', .false)
|
|
|
|
dlg = .DreamTeamDlg~new(sd'dragNdrop.rc', IDD_NFL_DLG)
|
|
|
|
if dlg~initCode == 0 then do
|
|
dlg~execute("SHOWTOP", IDI_DLG_OOREXX)
|
|
end
|
|
|
|
::requires "ooDialog.cls"
|
|
|
|
::class 'DreamTeamDlg' subclass RcDialog
|
|
|
|
::method init
|
|
expose dropOkCursor noDropCursor cursorIsNoDrop dragging
|
|
forward class (super) continue
|
|
|
|
-- This will load a cursor from a file. The file has to actually be a cursor
|
|
-- or the method will fail. The operating system will refuse to load anything
|
|
-- but an actual cursor. The return is an .Image object.
|
|
dropOkCursor = .Mouse~loadCursorFromFile(.application~srcDir"dragging.cur")
|
|
if dropOkCursor == 0 then do
|
|
say 'Error loading Drop Ok Cursor system error code:' .SystemErrorCode
|
|
self~initCode = 1
|
|
return self~initCode
|
|
end
|
|
|
|
-- This loads the system's predefined NO cursor. Again the return is a .Image
|
|
-- object.
|
|
noDropCursor = .Mouse~loadCursor("NO")
|
|
if noDropCursor == 0 then do
|
|
say 'Error loading No Drop Cursor, system error code:' .SystemErrorCode
|
|
self~initCode = 1
|
|
return self~initCode
|
|
end
|
|
|
|
cursorIsNoDrop = .false
|
|
dragging = .false
|
|
|
|
return 0
|
|
|
|
::method initDialog
|
|
expose lvNFL lvWest lvEast noDropCursor dragItem nfl2west nfl2east
|
|
|
|
lvNFL = self~newListView(IDC_LV_NFL)
|
|
self~setUpListView(lvNFL)
|
|
|
|
lvWest = self~newListView(IDC_LV_WEST)
|
|
self~setUpListView(lvWest)
|
|
|
|
lvEast = self~newListView(IDC_LV_EAST)
|
|
self~setUpListView(lvEast)
|
|
|
|
self~setMice
|
|
|
|
self~mapDropTargets
|
|
|
|
dragItem = .nil
|
|
|
|
|
|
/** mapDropTargets()
|
|
*
|
|
*/
|
|
::method mapDropTargets private
|
|
expose lvNFL lvWest lvEast nfl2west nfl2east west2nfl west2east east2nfl east2west
|
|
|
|
nfl2west = lvWest~clientRect
|
|
lvWest~mapWindowPoints(lvNFL~hwnd, nfl2west)
|
|
|
|
nfl2east = lvEast~clientRect
|
|
lvEast~mapWindowPoints(lvNFL~hwnd, nfl2east)
|
|
|
|
west2nfl = lvNFL~clientRect
|
|
lvNFL~mapWindowPoints(lvWest~hwnd, west2nfl)
|
|
|
|
west2east = lvEast~clientRect
|
|
lvEast~mapWindowPoints(lvWest~hwnd, west2east)
|
|
|
|
east2nfl = lvNFL~clientRect
|
|
lvNFL~mapWindowPoints(lvEast~hwnd, east2nfl)
|
|
|
|
east2west = lvWest~clientRect
|
|
lvWest~mapWindowPoints(lvEast~hwnd, east2west)
|
|
|
|
|
|
::method doDrag private
|
|
expose oldCursor noDropCursor cursorIsNoDrop dragging
|
|
use arg lv, index, p, mouse
|
|
|
|
mouse~capture
|
|
oldCursor = mouse~setCursor(noDropCursor)
|
|
|
|
di = .DragItem~new(lv, index, p, mouse)
|
|
|
|
cursorIsNoDrop = .true
|
|
dragging = .true
|
|
|
|
return di
|
|
|
|
|
|
::method nflOnLBdown unguarded
|
|
expose lvNFL dragItem
|
|
use arg keyState, p, mouse
|
|
|
|
index = lvNFL~hitTestInfo(p)
|
|
|
|
if keyState \== 'lButton' | index = -1 then return .false
|
|
|
|
lvNFL~assignFocus
|
|
lvNFL~focus(index)
|
|
lvNFL~select(index)
|
|
|
|
if mouse~dragDetect(p) then do
|
|
dragItem = self~doDrag(lvNFL, index, p, mouse)
|
|
return .true
|
|
end
|
|
|
|
return .false
|
|
|
|
::method nflOnLBup unguarded
|
|
expose oldCursor cursorIsNoDrop dragging lvNFL lvWest lvEast dragItem nfl2west nfl2east
|
|
use arg keyState, p, mouse
|
|
|
|
if dragging then do
|
|
okayToDrop = (cusorIsNoDrop \== .true)
|
|
|
|
dragging = .false
|
|
cursorIsNoDrop = .false
|
|
mouse~releaseCapture
|
|
mouse~setCursor(oldCursor)
|
|
|
|
if okayToDrop & dragItem \== .nil then do
|
|
if p~inRect(nfl2west) then do
|
|
dragItem~target = lvWest
|
|
end
|
|
else if p~inRect(nfl2east) then do
|
|
dragItem~target = lvEast
|
|
end
|
|
else do
|
|
-- Theoretically this can not happen, but just to be sure...
|
|
dragItem = .nil
|
|
return 0
|
|
end
|
|
|
|
-- The point p is in client coordinates of the NFL list view. We are
|
|
-- going to map that point back to the client coordinates of the list view
|
|
-- where the row is being dropped. Then the drag item can determine where
|
|
-- the insertion poing for the row should be in the target list view.
|
|
lvNFL~mapWindowPoints(dragItem~target~hwnd, p)
|
|
|
|
dragItem~drop(p)
|
|
dragItem = .nil
|
|
end
|
|
end
|
|
|
|
return 0
|
|
|
|
|
|
::method nflOnMove unguarded
|
|
expose dragging dropOkCursor noDropCursor cursorIsNoDrop nfl2west nfl2east
|
|
use arg keyState, p, mouse
|
|
|
|
if dragging then do
|
|
if p~inRect(nfl2west) then do
|
|
if cursorIsNoDrop then do
|
|
mouse~setCursor(dropOkCursor)
|
|
cursorIsNoDrop = .false
|
|
end
|
|
end
|
|
else if p~inRect(nfl2east) then do
|
|
if cursorIsNoDrop then do
|
|
mouse~setCursor(dropOkCursor)
|
|
cursorIsNoDrop = .false
|
|
end
|
|
end
|
|
else do
|
|
if \ cursorIsNoDrop then do
|
|
mouse~setCursor(noDropCursor)
|
|
cursorIsNoDrop = .true
|
|
end
|
|
end
|
|
end
|
|
|
|
return 0
|
|
|
|
::method westOnLBdown unguarded
|
|
expose lvWest dragItem
|
|
use arg keyState, p, mouse
|
|
|
|
index = lvWest~hitTestInfo(p)
|
|
|
|
if keyState \== 'lButton' | index = -1 then return .false
|
|
|
|
lvWest~assignFocus
|
|
lvWest~focus(index)
|
|
lvWest~select(index)
|
|
|
|
if mouse~dragDetect(p) then do
|
|
dragItem = self~doDrag(lvWest, index, p, mouse)
|
|
return .true
|
|
end
|
|
|
|
return .false
|
|
|
|
|
|
::method westOnLBup unguarded
|
|
expose oldCursor cursorIsNoDrop dragging lvNFL lvWest lvEast dragItem west2nfl west2east
|
|
use arg keyState, p, mouse
|
|
|
|
if dragging then do
|
|
okayToDrop = (cusorIsNoDrop \== .true)
|
|
|
|
dragging = .false
|
|
cursorIsNoDrop = .false
|
|
mouse~releaseCapture
|
|
mouse~setCursor(oldCursor)
|
|
|
|
if okayToDrop & dragItem \== .nil then do
|
|
if p~inRect(west2nfl) then do
|
|
dragItem~target = lvNFL
|
|
end
|
|
else if p~inRect(west2east) then do
|
|
dragItem~target = lvEast
|
|
end
|
|
else do
|
|
-- Theoretically this can not happen, but just to be sure...
|
|
dragItem = .nil
|
|
return 0
|
|
end
|
|
|
|
-- The point p is in client coordinates of the West list view. We are
|
|
-- going to map that point back to the client coordinates of the list view
|
|
-- where the row is being dropped. Then the drag item can determine where
|
|
-- the insertion poing for the row should be in the target list view.
|
|
lvWest~mapWindowPoints(dragItem~target~hwnd, p)
|
|
|
|
dragItem~drop(p)
|
|
dragItem = .nil
|
|
end
|
|
end
|
|
|
|
return 0
|
|
|
|
|
|
::method westOnMove unguarded
|
|
expose dragging dropOkCursor noDropCursor cursorIsNoDrop west2nfl west2east
|
|
use arg keyState, p, mouse
|
|
|
|
if dragging then do
|
|
if p~inRect(west2nfl) then do
|
|
if cursorIsNoDrop then do
|
|
mouse~setCursor(dropOkCursor)
|
|
cursorIsNoDrop = .false
|
|
end
|
|
end
|
|
else if p~inRect(west2east) then do
|
|
if cursorIsNoDrop then do
|
|
mouse~setCursor(dropOkCursor)
|
|
cursorIsNoDrop = .false
|
|
end
|
|
end
|
|
else do
|
|
if \ cursorIsNoDrop then do
|
|
mouse~setCursor(noDropCursor)
|
|
cursorIsNoDrop = .true
|
|
end
|
|
end
|
|
end
|
|
|
|
return 0
|
|
|
|
::method eastOnLBdown unguarded
|
|
expose lvEast dragItem
|
|
use arg keyState, p, mouse
|
|
|
|
index = lvEast~hitTestInfo(p)
|
|
|
|
if keyState \== 'lButton' | index = -1 then return .false
|
|
|
|
lvEast~assignFocus
|
|
lvEast~focus(index)
|
|
lvEast~select(index)
|
|
|
|
if mouse~dragDetect(p) then do
|
|
dragItem = self~doDrag(lvEast, index, p, mouse)
|
|
return .true
|
|
end
|
|
|
|
return .false
|
|
|
|
|
|
::method eastOnLBup unguarded
|
|
expose oldCursor cursorIsNoDrop dragging lvNFL lvWest lvEast dragItem east2nfl east2west
|
|
use arg keyState, p, mouse
|
|
|
|
if dragging then do
|
|
okayToDrop = (cusorIsNoDrop \== .true)
|
|
|
|
dragging = .false
|
|
cursorIsNoDrop = .false
|
|
mouse~releaseCapture
|
|
mouse~setCursor(oldCursor)
|
|
|
|
if okayToDrop & dragItem \== .nil then do
|
|
if p~inRect(east2nfl) then do
|
|
dragItem~target = lvNFL
|
|
end
|
|
else if p~inRect(east2west) then do
|
|
dragItem~target = lvWest
|
|
end
|
|
else do
|
|
-- Theoretically this can not happen, but just to be sure...
|
|
dragItem = .nil
|
|
return 0
|
|
end
|
|
|
|
-- The point p is in client coordinates of the East list view. We are
|
|
-- going to map that point back to the client coordinates of the list view
|
|
-- where the row is being dropped. Then the drag item can determine where
|
|
-- the insertion poing for the row should be in the target list view.
|
|
lvEast~mapWindowPoints(dragItem~target~hwnd, p)
|
|
|
|
dragItem~drop(p)
|
|
dragItem = .nil
|
|
end
|
|
end
|
|
|
|
return 0
|
|
|
|
|
|
::method eastOnMove unguarded
|
|
expose dragging dropOkCursor noDropCursor cursorIsNoDrop east2nfl east2west
|
|
use arg keyState, p, mouse
|
|
|
|
if dragging then do
|
|
if p~inRect(east2nfl) then do
|
|
if cursorIsNoDrop then do
|
|
mouse~setCursor(dropOkCursor)
|
|
cursorIsNoDrop = .false
|
|
end
|
|
end
|
|
else if p~inRect(east2west) then do
|
|
if cursorIsNoDrop then do
|
|
mouse~setCursor(dropOkCursor)
|
|
cursorIsNoDrop = .false
|
|
end
|
|
end
|
|
else do
|
|
if \ cursorIsNoDrop then do
|
|
mouse~setCursor(noDropCursor)
|
|
cursorIsNoDrop = .true
|
|
end
|
|
end
|
|
end
|
|
|
|
return 0
|
|
|
|
|
|
|
|
::method setMice private
|
|
expose mLVnfl mLVwest mLVeast lvNFL lvWest lvEast
|
|
|
|
mLVnfl = .Mouse~new(lvNFL)
|
|
mLVwest = .Mouse~new(lvWest)
|
|
mLVeast = .Mouse~new(lvEast)
|
|
|
|
mLVnfl~connectEvent('LBUTTONDOWN', nflOnLBdown)
|
|
mLVnfl~connectEvent('LBUTTONUP', nflOnLBup)
|
|
mLVnfl~connectEvent('MOUSEMOVE', nflOnMove)
|
|
|
|
mLVwest~connectEvent('LBUTTONDOWN', westOnLBdown)
|
|
mLVwest~connectEvent('LBUTTONUP', westOnLBup)
|
|
mLVwest~connectEvent('MOUSEMOVE', westOnMove)
|
|
|
|
mLVeast~connectEvent('LBUTTONDOWN', eastOnLBdown)
|
|
mLVeast~connectEvent('LBUTTONUP', eastOnLBup)
|
|
mLVeast~connectEvent('MOUSEMOVE', eastOnMove)
|
|
|
|
::method setUpListView private
|
|
use strict arg lv
|
|
|
|
lv~addExtendedStyle("GRIDLINES DOUBLEBUFFER FULLROWSELECT")
|
|
lv~insertColumnPX(0, 'Player', 105, 'LEFT')
|
|
lv~insertColumnPX(1, 'Team', 115, 'CENTER')
|
|
lv~insertColumnPX(2, 'Position', 65, 'CENTER')
|
|
lv~insertColumnPX(3, 'Rating', 65, 'CENTER')
|
|
|
|
if lv~id == .constDir[IDC_LV_NFL] then do
|
|
playerRows = self~getPlayers
|
|
do l over playerRows
|
|
lv~addRow( , , l~player, l~team, l~pos, l~rating)
|
|
end
|
|
end
|
|
|
|
::method getPlayers private
|
|
|
|
rows = .Array~new
|
|
|
|
fileObj = .stream~new(.application~srcDir"nflPlayers.txt")
|
|
players = fileObj~makeArray
|
|
|
|
do line over players
|
|
line = line~strip
|
|
if line~length == 0 | line~abbrev("#") | line~abbrev("/*") then iterate
|
|
|
|
parse var line name', 'team', 'p', 'rating .
|
|
|
|
r = .Directory~new
|
|
r~player = name
|
|
r~team = team
|
|
r~pos = p
|
|
r~rating = rating
|
|
rows~append(r)
|
|
end
|
|
|
|
fileObj~close
|
|
|
|
return rows
|
|
|
|
|
|
/* Class: DragItem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*\
|
|
|
|
Drag items are an encapsulation of the data needed to drag and drop one row
|
|
of a list view to another.
|
|
\* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
|
|
::class 'DragItem'
|
|
|
|
::attribute target
|
|
|
|
::method init
|
|
expose lv index row target
|
|
use arg lv, index, p, mouse
|
|
|
|
row = .Directory~new
|
|
lv~getItemInfo(index, row)
|
|
row~player = row~text
|
|
|
|
lv~getItemInfo(index, row, 1)
|
|
row~team = row~text
|
|
|
|
lv~getItemInfo(index, row, 2)
|
|
row~pos = row~text
|
|
|
|
lv~getItemInfo(index, row, 3)
|
|
row~rating = row~text
|
|
|
|
target = .nil
|
|
|
|
::method drop
|
|
expose lv index row target
|
|
use strict arg pt = 0
|
|
|
|
if target \== .nil then do
|
|
-- Drop the row at the end of the list by default.
|
|
targetIndex = target~items
|
|
|
|
if pt~isA(.Point) then do
|
|
i = target~hitTestInfo(pt)
|
|
if i <> -1 then targetIndex = i
|
|
end
|
|
|
|
target~addRow(targetIndex, , row~player, row~team, row~pos, row~rating)
|
|
|
|
lv~delete(index)
|
|
|
|
count = lv~items
|
|
if count <> 0 then do
|
|
if index == count then lv~select(index - 1)
|
|
else lv~select(index)
|
|
end
|
|
end
|
|
|
|
|