983 lines
27 KiB
Plaintext
Executable File
983 lines
27 KiB
Plaintext
Executable File
-- Rockstar Dialog
|
|
-- Rockstar North
|
|
-- 1/3/2005
|
|
-- by Greg Smith
|
|
|
|
-- Some useful dialogs
|
|
|
|
filein "pipeline/util/SaveDecisionMgr.ms"
|
|
|
|
fn RsQueryBox message edittext:"" =
|
|
(
|
|
global RsDialogReturnVal = ""
|
|
global RsDialogInVal = edittext
|
|
|
|
rollout RsTheQueryBox message
|
|
(
|
|
edittext edtItem "" text:RsDialogInVal
|
|
button btnOK "OK" width:100 pos:[90,40]
|
|
button btnCancel "Cancel" width:100 pos:[210,40]
|
|
|
|
on btnOK pressed do
|
|
(
|
|
RsDialogReturnVal = edtItem.text
|
|
DestroyDialog RsTheQueryBox
|
|
)
|
|
|
|
on btnCancel pressed do
|
|
(
|
|
DestroyDialog RsTheQueryBox
|
|
)
|
|
)
|
|
|
|
CreateDialog RsTheQueryBox width:300 modal:true
|
|
|
|
RsDialogReturnVal
|
|
)
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------
|
|
-- RsQueryBoxMultiBtn
|
|
-----------------------------------------------------------------------------------------------------------------------
|
|
-- Modal query-box offers an n-button set of custom buttons, with optional timeout, tooltips
|
|
-- DefaultBtn is focused by default, and is clicked after countdown.
|
|
-- Timeout is in seconds, and is inactive if <= 0, .
|
|
-- CancelBtn is pressed if dialog is closed or Escape is pressed.
|
|
-- - Set to last button by default.
|
|
-- - Can be disabled by choosing invalid button-number.
|
|
-- checkLabels/Values allows for option-tickyboxes to be added too.
|
|
-- listItems adds a list-control, with optional columns. Has rightclick menu with clipboard-copy command.
|
|
-- - If bitArray listCheckStates is supplied, then listItems will be given optional checkboxes
|
|
fn RsQueryBoxMultiBtn_run message title:"Query" timeout:60 width:360 modal:True \
|
|
labels:#("Yes", "No", "Cancel") tooltips:#() defaultBtn:1 cancelBtn: \
|
|
checkLabels:#() checkStates:#{} \
|
|
listItems:#() listTitles: listCheckStates: listDoubleClickFunc: \
|
|
optionsStruct: =
|
|
(
|
|
-- Expand generator-options, if function is being called indirectly:
|
|
if (optionsStruct != unsupplied) do
|
|
(
|
|
message = optionsStruct.message
|
|
title = optionsStruct.title
|
|
timeout = optionsStruct.timeout
|
|
width = optionsStruct.width
|
|
labels = optionsStruct.labels
|
|
tooltips = optionsStruct.tooltips
|
|
defaultBtn = optionsStruct.defaultBtn
|
|
cancelBtn = optionsStruct.cancelBtn
|
|
checkLabels = optionsStruct.checkLabels
|
|
checkStates = optionsStruct.checkStates
|
|
listItems = optionsStruct.listItems
|
|
listTitles = optionsStruct.listTitles
|
|
listCheckStates = optionsStruct.listCheckStates
|
|
listDoubleClickFunc = optionsStruct.listDoubleClickFunc
|
|
modal = optionsStruct.modal
|
|
)
|
|
|
|
local padding = 10
|
|
|
|
if gRsSaveDecMgr.IsEnabledAndRecorded message then
|
|
return gRsSaveDecMgr.Trigger message
|
|
|
|
if (cancelBtn == unsupplied) do
|
|
(
|
|
cancelBtn = labels.count
|
|
)
|
|
|
|
-- Define form:
|
|
local queryForm = dotNetObject "MaxCustomControls.MaxForm"
|
|
queryForm.tag = cancelBtn -- Choose cancel-button value by default
|
|
queryForm.Text = title
|
|
queryForm.Width = width
|
|
queryForm.Height = 100
|
|
|
|
-- Form is fixed-size by default:
|
|
queryForm.FormBorderStyle = queryForm.FormBorderStyle.FixedDialog
|
|
|
|
queryForm.MinimizeBox = false
|
|
queryForm.MaximizeBox = false
|
|
queryForm.StartPosition = queryForm.StartPosition.CenterScreen
|
|
|
|
-- Button-press event transfers button-tag id to parent-form tag, allowing us to extract our return-value:
|
|
fn buttonPressed Sender Args =
|
|
(
|
|
sender.Parent.Tag = Sender.Tag
|
|
sender.Parent.Close()
|
|
)
|
|
|
|
-- Function used by control-events to stop timer.
|
|
-- (Finds and clicks timer-stop button, if found)
|
|
fn eventStopsTimer Sender Args =
|
|
(
|
|
local queryForm = if (Sender.Parent == undefined) then (Sender) else (Sender.Parent)
|
|
local dialogCtrls = queryForm.Controls
|
|
local notFound = True
|
|
|
|
for n = 0 to (dialogCtrls.Count - 1) while notFound do
|
|
(
|
|
local ctrl = dialogCtrls.Item[n]
|
|
|
|
if (ctrl.name == "Button_StopTimer") do
|
|
(
|
|
notFound = False
|
|
ctrl.PerformClick()
|
|
)
|
|
)
|
|
|
|
return OK
|
|
)
|
|
|
|
-- Set up label-text:
|
|
local lblMsg = dotNetObject "Label"
|
|
(
|
|
lblMsg.Name = "Label"
|
|
lblMsg.Font = lblMsg.DefaultFont
|
|
lblMsg.Location.x = padding
|
|
lblMsg.Location.y = padding
|
|
|
|
lblMsgWidth = queryForm.Width - (2 * padding)
|
|
lblMsg.Width = lblMsgWidth + 200 -- Allow for bits where our wrapping doesn't match label's auto-wrapping
|
|
lblMsg.Height = 400
|
|
lblMsg.Anchor = dotnet.combineEnums lblMsg.Anchor.Top lblMsg.Anchor.Left
|
|
|
|
local wrappedMsg = RsWordwrap message lblMsgWidth font:lblMsg.Font delimiters:#(" ","\t","/")
|
|
lblMsg.text = wrappedMsg
|
|
|
|
local textSize = RsGetTextExtent wrappedMsg font:lblMsg.font
|
|
lblMsg.Height = textSize.y
|
|
|
|
queryForm.Controls.Add lblMsg
|
|
)
|
|
|
|
-- Add list, if requested:
|
|
local checkColNum, itemList
|
|
if (listItems != unsupplied) and (listItems.count != 0) do
|
|
(
|
|
-- Make list-dialog resizable:
|
|
queryForm.FormBorderStyle = queryForm.FormBorderStyle.Sizable
|
|
|
|
-- Make sure "RsCustomDataGridView" is defined:
|
|
RS_CustomDataGrid()
|
|
|
|
local itemList = dotNetObject "RsCustomDataGridView"
|
|
itemList.name = "ItemList"
|
|
|
|
if (not isKindOf listItems[1] array) do
|
|
(
|
|
listItems = for item in listItems collect #(item)
|
|
)
|
|
local textColCount = listItems[1].count
|
|
|
|
itemList.Location.X = padding
|
|
itemList.Location.Y = lblMsg.Bottom + padding
|
|
itemList.Width = queryForm.Width - (2 * padding) - 16
|
|
itemList.Height = 160
|
|
|
|
itemList.ReadOnly = false
|
|
itemList.SelectionMode = itemList.SelectionMode.FullRowSelect
|
|
itemList.AllowUserToAddRows = false
|
|
itemList.AllowUserToDeleteRows = false
|
|
itemList.AllowUserToOrderColumns = false
|
|
itemList.AllowUserToResizeColumns = false
|
|
itemList.AllowUserToResizeRows = false
|
|
itemList.AllowDrop = false
|
|
itemList.MultiSelect = true
|
|
|
|
itemList.DefaultCellStyle.WrapMode = itemList.DefaultCellStyle.WrapMode.True
|
|
itemList.AutoSizeRowsMode = itemList.AutoSizeRowsMode.AllCells
|
|
|
|
local textClr = (colorMan.getColor #windowText) * 255
|
|
local windowClr = (colorMan.getColor #window) * 255
|
|
itemList.DefaultCellStyle.backColor = (dotNetClass "System.Drawing.Color").FromArgb windowClr[1] windowClr[2] windowClr[3]
|
|
itemList.DefaultCellStyle.foreColor = (dotNetClass "System.Drawing.Color").FromArgb textClr[1] textClr[2] textClr[3]
|
|
itemList.AutoSizeColumnsMode = itemList.AutoSizeColumnsMode.Fill
|
|
|
|
local doTitles = (listTitles != unsupplied)
|
|
itemList.ColumnHeadersVisible = doTitles
|
|
|
|
-- Add checkbox-column, if required:
|
|
if (listCheckStates != unsupplied) do
|
|
(
|
|
local checkCol = dotNetObject "DataGridViewCheckBoxColumn"
|
|
checkCol.name = "CheckBoxCol"
|
|
checkCol.tag = (dotNetMXSValue listCheckStates)
|
|
|
|
checkCol.AutoSizeMode = checkCol.AutoSizeMode.None
|
|
checkColNum = itemList.Columns.Add checkCol
|
|
|
|
checkCol.width = 0
|
|
|
|
if doTitles do
|
|
(
|
|
local headerText = listTitles[checkColNum + 1]
|
|
|
|
if isKindOf headerText string do
|
|
(
|
|
checkCol.HeaderText = headerText
|
|
checkCol.width = ((dotNetClass "TextRenderer").MeasureText headerText itemList.font).width + 8
|
|
checkCol.SortMode = checkCol.SortMode.Automatic
|
|
)
|
|
)
|
|
|
|
if (checkCol.width < 20) do
|
|
(
|
|
checkCol.width = 20
|
|
)
|
|
|
|
-- Add state-booleans to row-builder list:
|
|
listItems = for n = 1 to listItems.count collect
|
|
(
|
|
local newItem = #(listCheckStates[n])
|
|
join newItem listItems[n]
|
|
newItem
|
|
)
|
|
)
|
|
|
|
-- Add text-columns:
|
|
for n = 1 to textColCount do
|
|
(
|
|
local textCol = dotNetObject "DataGridViewTextBoxColumn"
|
|
textCol.ReadOnly = true
|
|
|
|
-- Set last column-size to fit to text:
|
|
if (n != 1) and (n == textColCount) do
|
|
(
|
|
textCol.AutoSizeMode = textCol.AutoSizeMode.AllCells
|
|
)
|
|
|
|
local newColNum = itemList.Columns.Add textCol
|
|
|
|
if doTitles do
|
|
(
|
|
textCol.HeaderText = listTitles[newColNum + 1]
|
|
)
|
|
)
|
|
|
|
-- Add list-rows:
|
|
for item in listItems do
|
|
(
|
|
local rowIdx = itemList.Rows.Add item
|
|
|
|
-- Add number to row's tag, so it remembers it if reordered:
|
|
itemList.Rows.Item[rowIdx].tag = (rowIdx + 1)
|
|
)
|
|
|
|
-- Stop timer if itemList is scrolled:
|
|
if (timeOut > 0) do
|
|
(
|
|
dotNet.addEventHandler itemList "Scroll" eventStopsTimer
|
|
)
|
|
|
|
-- Called when itemList is clicked:
|
|
fn listClicked Sender Args =
|
|
(
|
|
-- Press timer-deactivate button, if found:
|
|
(
|
|
local dialogCtrls = Sender.Parent.Controls
|
|
local notFound = True
|
|
|
|
for n = 0 to (dialogCtrls.Count - 1) while notFound do
|
|
(
|
|
local ctrl = dialogCtrls.Item[n]
|
|
|
|
if (ctrl.name == "Button_StopTimer") do
|
|
(
|
|
notFound = False
|
|
ctrl.PerformClick()
|
|
)
|
|
)
|
|
)
|
|
|
|
if (args.RowIndex < 0) do return false
|
|
|
|
local rightClick = args.button.equals args.button.right
|
|
|
|
if rightClick do
|
|
(
|
|
-- Make sure that ItemList can be accessed by RCMenu:
|
|
global RsQueryBoxMultiBtn_itemList = Sender
|
|
|
|
-- Exclusive-select row if it's not currently selected:
|
|
local clickRow = sender.Rows.Item[args.RowIndex]
|
|
if not clickRow.Selected do
|
|
(
|
|
sender.ClearSelection()
|
|
clickRow.Selected = true
|
|
)
|
|
|
|
-- Rightclick menu:
|
|
rcmenu RSmenu_dialogList
|
|
(
|
|
local itemList, selRows, hasCheckboxes
|
|
fn hasChecksFilter = hasCheckboxes
|
|
fn hasSel = (selRows.count != 0)
|
|
fn hasSelAndChecks = (hasSel() and hasChecksFilter())
|
|
|
|
menuItem itmStatesAll "Check All" filter:hasChecksFilter
|
|
menuItem itmStatesNone "Check None" filter:hasChecksFilter
|
|
menuItem itmStatesInvert "Check Invert" filter:hasChecksFilter
|
|
seperator sepA filter:hasChecksFilter
|
|
|
|
menuItem itmSetSelStates "Check Selected" filter:hasSelAndChecks
|
|
menuItem itmUnsetSelStates "Uncheck Selected" filter:hasSelAndChecks
|
|
seperator sepB filter:hasSelAndChecks
|
|
|
|
menuItem itmCopy "Copy selected to clipboard" filter:hasSel
|
|
|
|
on itmStatesAll picked do
|
|
(
|
|
-- CurrentCell (last user-checked) can't be set programatically, so we clear this value:
|
|
itemList.CurrentCell = undefined
|
|
selRows.Selected = true
|
|
|
|
for rowId = 0 to (itemList.rowCount - 1) do
|
|
(
|
|
local cell = itemList.rows.item[rowId].cells.item[0]
|
|
cell.value = True
|
|
)
|
|
)
|
|
|
|
on itmStatesNone picked do
|
|
(
|
|
itemList.CurrentCell = undefined
|
|
selRows.Selected = true
|
|
|
|
for rowId = 0 to (itemList.rowCount - 1) do
|
|
(
|
|
local cell = itemList.rows.item[rowId].cells.item[0]
|
|
cell.value = False
|
|
)
|
|
)
|
|
|
|
on itmStatesInvert picked do
|
|
(
|
|
itemList.CurrentCell = undefined
|
|
selRows.Selected = true
|
|
|
|
for rowId = 0 to (itemList.rowCount - 1) do
|
|
(
|
|
local cell = itemList.rows.item[rowId].cells.item[0]
|
|
cell.value = not cell.value
|
|
)
|
|
)
|
|
|
|
fn setSelState val:true =
|
|
(
|
|
itemList.CurrentCell = undefined
|
|
selRows.Selected = true
|
|
|
|
for rowId = 0 to (itemList.rowCount - 1) do
|
|
(
|
|
local row = itemList.rows.item[rowId]
|
|
|
|
if row.selected do
|
|
(
|
|
local cell = row.cells.item[0]
|
|
cell.value = val
|
|
)
|
|
)
|
|
)
|
|
|
|
on itmSetSelStates picked do
|
|
(
|
|
setSelState val:true
|
|
)
|
|
|
|
on itmUnsetSelStates picked do
|
|
(
|
|
setSelState val:false
|
|
)
|
|
|
|
on itmCopy picked do
|
|
(
|
|
-- Build text-list for copying to clipboard:
|
|
local copyText = stringStream ""
|
|
|
|
for selRowNum = 1 to selRows.count do
|
|
(
|
|
local row = selRows[selRowNum]
|
|
|
|
local colNums = #{1..row.cells.Count}
|
|
|
|
if hasCheckboxes do (colNums[1] = false)
|
|
|
|
for colNum in colNums do
|
|
(
|
|
format "%" row.cells.item[colNum - 1].value to:copyText
|
|
|
|
if colNum != row.cells.count do
|
|
(
|
|
format ", " to:copyText
|
|
)
|
|
)
|
|
|
|
if selRowNum != selRows.count do
|
|
(
|
|
format "\n" to:copyText
|
|
)
|
|
)
|
|
|
|
setclipboardText (copyText as string)
|
|
)
|
|
|
|
on RSmenu_dialogList open do
|
|
(
|
|
itemList = RsQueryBoxMultiBtn_itemList
|
|
|
|
selRows = for n = 0 to (itemList.SelectedRows.count - 1) collect itemList.SelectedRows.Item[n]
|
|
|
|
hasCheckboxes = isKindOf itemList.rows.item[0].cells.item[0].value booleanClass
|
|
)
|
|
)
|
|
popUpMenu RSmenu_dialogList
|
|
)
|
|
)
|
|
|
|
dotNet.addEventHandler itemList "CellMouseUp" listClicked
|
|
|
|
-- Double-click function can be supplied:
|
|
if (listDoubleClickFunc != unsupplied) do
|
|
(
|
|
dotNet.addEventHandler itemList "CellMouseDoubleClick" listDoubleClickFunc
|
|
)
|
|
|
|
-- Add callback that clears list-selection when the form is activated:
|
|
fn clearSel sender args =
|
|
(
|
|
for n = 0 to (sender.Controls.Count - 1) do
|
|
(
|
|
local ctrl = sender.Controls.Item[n]
|
|
|
|
if (ctrl.name == "ItemList") do
|
|
(
|
|
ctrl.clearSelection()
|
|
)
|
|
)
|
|
)
|
|
dotNet.addEventHandler queryForm "Activated" clearSel
|
|
|
|
queryForm.Controls.Add itemList
|
|
)
|
|
|
|
-- Define buttons:
|
|
local lastBtn, timedBtn, timedBtnInfo
|
|
for btnNum = 1 to labels.count do
|
|
(
|
|
local newBtn = dotNetObject "Button"
|
|
newBtn.FlatStyle = newBtn.FlatStyle.System
|
|
newBtn.AutoSize = True
|
|
newBtn.text = labels[btnNum]
|
|
newBtn.tag = btnNum
|
|
|
|
newBtn.name = ("Button_" + (btnNum as string))
|
|
|
|
-- Add tooltip to button, if specified:
|
|
local btnTooltip = tooltips[btnNum]
|
|
if (btnTooltip != undefined) do
|
|
(
|
|
local tooltipObj = dotnetobject "System.Windows.Forms.ToolTip"
|
|
tooltipObj.SetToolTip newBtn btnTooltip
|
|
)
|
|
|
|
-- Set button-focus order, so that default button has it first:
|
|
local tabIdx = btnNum - defaultBtn
|
|
if (tabIdx < 0) do (tabIdx += labels.count)
|
|
newBtn.TabIndex = tabIdx
|
|
newBtn.TabStop = True
|
|
|
|
if (lastBtn == undefined) then
|
|
(
|
|
local lastCtrl = queryForm.Controls.Item[queryForm.Controls.Count - 1]
|
|
|
|
newBtn.Location.x = padding
|
|
newBtn.Location.y = lastCtrl.Bottom + padding
|
|
)
|
|
else
|
|
(
|
|
newBtn.Location = lastBtn.location
|
|
newBtn.Location.x += lastBtn.width + padding
|
|
)
|
|
|
|
-- Collect default/timed button's info, if this is that:
|
|
if (timeout > 0) and (btnNum == defaultBtn) do
|
|
(
|
|
timedBtn = newBtn
|
|
timedBtnInfo = #(newBtn, newBtn.text, timeout)
|
|
newBtn.text += " (XX)"
|
|
)
|
|
|
|
-- If escape is pressed, the cancel-button's value is returned by form:
|
|
if (btnNum == cancelBtn) then
|
|
(
|
|
queryForm.CancelButton = newBtn
|
|
)
|
|
|
|
-- Add button-press event:
|
|
dotnet.addEventHandler newBtn "Click" buttonPressed
|
|
|
|
lastBtn = newBtn
|
|
queryForm.Controls.Add newBtn
|
|
)
|
|
|
|
-- Define tickyboxes:
|
|
local checkPadding = 8
|
|
for checkNum = 1 to checkLabels.count do
|
|
(
|
|
local newBtn = dotNetObject "CheckBox"
|
|
newBtn.FlatStyle = newBtn.FlatStyle.System
|
|
newBtn.name = ("CheckBox_" + (checkNum as string))
|
|
|
|
newBtn.AutoSize = True
|
|
newBtn.text = checkLabels[checkNum]
|
|
newBtn.checked = checkStates[checkNum]
|
|
newBtn.tag = dotNetMXSValue checkStates
|
|
|
|
-- Stop timer if itemList is scrolled:
|
|
if (timeOut > 0) do
|
|
(
|
|
dotNet.addEventHandler newBtn "CheckedChanged" eventStopsTimer
|
|
)
|
|
|
|
newBtn.Location.x = padding
|
|
newBtn.Location.y = lastBtn.Location.y + lastBtn.Height + checkPadding
|
|
checkPadding = -4
|
|
|
|
lastBtn = newBtn
|
|
queryForm.Controls.Add newBtn
|
|
)
|
|
|
|
-- Set up countdown timer, if used:
|
|
local closeTimer
|
|
if (timeOut > 0) and (timedBtn != undefined) do
|
|
(
|
|
closeTimer = dotNetObject "Timer"
|
|
|
|
-- Timer has 1-second tick:
|
|
closeTimer.interval = 1000
|
|
|
|
-- timedBtnInfo is array: #(button, buttonLabel, timeout)
|
|
closeTimer.tag = dotNetMXSValue timedBtnInfo
|
|
|
|
-- Stops timer on timer-stop button-click:
|
|
fn timerStop sender args =
|
|
(
|
|
sender.text = ""
|
|
local closeTimer = sender.Tag
|
|
|
|
-- Reset button's text, and kill timer:
|
|
if (closeTimer != undefined) do
|
|
(
|
|
local timerInfo = closeTimer.tag.value
|
|
local timedBtn = timerInfo[1]
|
|
timedBtn.text = timerInfo[2]
|
|
closeTimer.dispose()
|
|
)
|
|
)
|
|
|
|
-- Move buttons after timed-button sideways, to make room for the timer-cancel button:
|
|
local stopBtnWidth = 20
|
|
local timedBtnFound = False
|
|
for n = 0 to (queryForm.Controls.Count - 1) do
|
|
(
|
|
local ctrl = queryForm.Controls.Item[n]
|
|
|
|
if timedBtnFound then
|
|
(
|
|
if (matchPattern ctrl.name pattern:"Button*") do
|
|
(
|
|
ctrl.Location.X += stopBtnWidth
|
|
)
|
|
)
|
|
else
|
|
(
|
|
if (ctrl == timedBtn) do
|
|
(
|
|
timedBtnFound = True
|
|
)
|
|
)
|
|
)
|
|
|
|
local stopTimerBtn = dotNetObject "Button"
|
|
stopTimerBtn.name = "Button_StopTimer"
|
|
stopTimerBtn.text = "X"
|
|
stopTimerBtn.FlatStyle = stopTimerBtn.FlatStyle.System
|
|
stopTimerBtn.Location = timedBtn.Location
|
|
stopTimerBtn.Location.X += timedBtn.Width
|
|
stopTimerBtn.Width = stopBtnWidth
|
|
stopTimerBtn.Height = timedBtn.Height
|
|
stopTimerBtn.Tag = closeTimer
|
|
queryForm.Controls.Add stopTimerBtn
|
|
dotNet.addEventHandler stopTimerBtn "Click" timerStop
|
|
|
|
local toolTipObj = dotnetobject "ToolTip"
|
|
toolTipObj.SetToolTip stopTimerBtn "Stop countdown"
|
|
toolTipObj.Active = True
|
|
|
|
fn tickFunc sender arg =
|
|
(
|
|
local timerInfo = sender.tag.value
|
|
|
|
local tickTime = timerInfo[3]
|
|
local timedBtn = timerInfo[1]
|
|
|
|
-- Update timed-button's text:
|
|
timedBtn.text = timerInfo[2] + " (" + (tickTime as string) + ")"
|
|
|
|
if (tickTime == 0) then
|
|
(
|
|
-- Close form, leaving it with timer's return-value:
|
|
timedBtn.Parent.Tag = timedBtn.Tag
|
|
timedBtn.Parent.Close()
|
|
sender.Dispose()
|
|
)
|
|
else
|
|
(
|
|
timerInfo[3] -= 1
|
|
)
|
|
)
|
|
|
|
dotnet.addEventHandler closeTimer "Tick" tickFunc
|
|
|
|
closeTimer.Start()
|
|
|
|
tickFunc closeTimer 0
|
|
)
|
|
|
|
-- Get max control-bounds:
|
|
-- (ignores label, as that's extra-wide)
|
|
local maxCtrlSize = [0,0]
|
|
for ctrlNum = 1 to (queryForm.controls.count - 1) do
|
|
(
|
|
local ctrl = queryForm.Controls.Item[ctrlNum]
|
|
|
|
if (ctrl.Right > maxCtrlSize.X) do
|
|
(
|
|
maxCtrlSize.X = ctrl.Right
|
|
)
|
|
if (ctrl.Bottom > maxCtrlSize.Y) do
|
|
(
|
|
maxCtrlSize.Y = ctrl.Bottom
|
|
)
|
|
)
|
|
|
|
-- Final form-resize:
|
|
local newWidth = maxCtrlSize.X + padding + 15
|
|
if (newWidth > width) do
|
|
(
|
|
queryForm.Width = newWidth
|
|
)
|
|
queryForm.Height = maxCtrlSize.Y + padding + 38
|
|
queryForm.MinimumSize = queryForm.Size
|
|
|
|
-- Anchor button/checkbox controls to form's new size:
|
|
for n = 0 to (queryForm.Controls.Count - 1) do
|
|
(
|
|
local ctrl = queryForm.Controls.Item[n]
|
|
|
|
if (matchPattern ctrl.name pattern:"Button*") or (matchPattern ctrl.name pattern:"CheckBox*") do
|
|
(
|
|
ctrl.Anchor = dotnet.combineEnums ctrl.Anchor.Bottom ctrl.Anchor.Left
|
|
)
|
|
)
|
|
|
|
-- Anchor the ItemList:
|
|
if (itemList != undefined) do
|
|
(
|
|
itemList.Anchor = dotnet.combineEnums itemList.Anchor.Top itemList.Anchor.Left itemList.Anchor.Bottom itemList.Anchor.Right
|
|
)
|
|
|
|
-- Form-close event:
|
|
fn formClosed Sender Arg =
|
|
(
|
|
-- Clear temp globals:
|
|
globalVars.remove "RsQueryBoxMultiBtn_itemList"
|
|
|
|
local dialogCtrls = Sender.Controls
|
|
|
|
-- Find specific controls, if used:
|
|
local btnTimerStop, itemList, cancelNum
|
|
local chkButtons = #()
|
|
|
|
for n = 0 to (dialogCtrls.Count - 1) do
|
|
(
|
|
local ctrl = dialogCtrls.Item[n]
|
|
local ctrlName = ctrl.name
|
|
|
|
case of
|
|
(
|
|
(matchPattern ctrlName pattern:"ItemList"):(itemList = ctrl)
|
|
(matchPattern ctrlName pattern:"Button_StopTimer"):(btnTimerStop = ctrl)
|
|
(matchPattern ctrlName pattern:"CheckBox_*"):(append chkButtons ctrl)
|
|
)
|
|
|
|
-- Make note of the cancel-button number, to compare against chosen value:
|
|
if (ctrl == Sender.CancelButton) do
|
|
(
|
|
cancelNum = ctrl.Tag
|
|
)
|
|
)
|
|
|
|
-- Dispose of timer (linked as StopTimer-button's tag)
|
|
if (btnTimerStop != undefined) do
|
|
(
|
|
-- The actual Timer control is linked to the button's tag:
|
|
if (btnTimerStop.Tag != undefined) do
|
|
(
|
|
btnTimerStop.Tag.dispose()
|
|
btnTimerStop.Tag = undefined
|
|
)
|
|
)
|
|
|
|
-- Don't do these bits if cancelling:
|
|
if (Sender.Tag != cancelNum) do
|
|
(
|
|
-- Finalise item-list bits:
|
|
if (ItemList != undefined) do
|
|
(
|
|
-- Find checkbox column in list:
|
|
local checkColNum, listCheckStates
|
|
for colIdx = 0 to (itemList.Columns.Count - 1) while (checkColNum == undefined) do
|
|
(
|
|
local thisCol = itemList.Columns.Item[colIdx]
|
|
if (thisCol.name == "CheckBoxCol") do
|
|
(
|
|
checkColNum = colIdx
|
|
listCheckStates = thisCol.Tag.Value
|
|
)
|
|
)
|
|
|
|
-- Transfer list's checkbox-states out of form, if used:
|
|
if (checkColNum != undefined) do
|
|
(
|
|
local rows = ItemList.rows
|
|
|
|
for rowIdx = 0 to (rows.count - 1) do
|
|
(
|
|
local row = rows.Item[rowIdx]
|
|
local rowNum = row.tag
|
|
local rowChecked = row.cells.item[checkColNum].value
|
|
|
|
listCheckStates[rowNum] = rowChecked
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Update check-button values:
|
|
if (chkButtons.count != 0) do
|
|
(
|
|
local chkButtonArray = chkButtons[1].Tag.Value
|
|
|
|
for n = 1 to chkButtons.count do
|
|
(
|
|
chkButtonArray[n] = chkButtons[n].checked
|
|
)
|
|
)
|
|
)
|
|
|
|
return OK
|
|
)
|
|
|
|
dotNet.addEventHandler queryForm "FormClosed" formClosed
|
|
|
|
-- Don't allow events to be removed by Max garbage-collection:
|
|
local ctrls = #(queryForm)
|
|
for ctrlIdx = 0 to (queryForm.Controls.Count - 1) do
|
|
(
|
|
append ctrls queryForm.Controls.Item[ctrlIdx]
|
|
)
|
|
for ctrl in ctrls do
|
|
(
|
|
dotNet.setLifetimeControl ctrl #dotnet
|
|
)
|
|
|
|
-- Show form and wait for input:
|
|
if modal then
|
|
(
|
|
queryForm.ShowModal()
|
|
)
|
|
else
|
|
(
|
|
queryForm.ShowModeless()
|
|
)
|
|
|
|
if gRsSaveDecMgr.IsRecording() do
|
|
(
|
|
gRsSaveDecMgr.registerDecision message queryForm.tag optionLabels:labels
|
|
)
|
|
|
|
|
|
if modal then
|
|
(
|
|
-- Return integer value if modal querybox:
|
|
return queryForm.tag
|
|
)
|
|
else
|
|
(
|
|
-- Return form if non-modal:
|
|
return queryForm
|
|
)
|
|
)
|
|
|
|
-- Call dotnet query-box function indirectly via a hidden rollout, as workaround for bug:954913
|
|
-- (dotnet forms don't work properly when called from an object rollout)
|
|
fn RsQueryBoxMultiBtn message title:"Query" timeout:60 width:360 \
|
|
labels:#("Yes", "No", "Cancel") tooltips:#() defaultBtn:1 cancelBtn: \
|
|
checkLabels:#() checkStates:#{} \
|
|
listItems:#() listTitles: listCheckStates: listDoubleClickFunc: modal:True =
|
|
(
|
|
-- Encapsulate generator-options:
|
|
struct RsQueryBoxOptionsStruct (message, title, timeout, width, labels, tooltips, defaultBtn, cancelBtn, checkLabels, checkStates, listItems, listTitles, listCheckStates, listDoubleClickFunc, modal)
|
|
global RsQueryBoxMultiBtn_options = RsQueryBoxOptionsStruct message:message title:title timeout:timeout width:width labels:labels tooltips:tooltips defaultBtn:defaultBtn \
|
|
cancelBtn:cancelBtn checkLabels:checkLabels checkStates:checkStates listItems:listItems listTitles:listTitles listCheckStates:listCheckStates listDoubleClickFunc:listDoubleClickFunc modal:modal
|
|
|
|
rollout RsQueryBoxMultiBtn_RunRoll "" width:0 height:0
|
|
(
|
|
timer ticker "" interval:0
|
|
on ticker tick do
|
|
(
|
|
destroydialog RsQueryBoxMultiBtn_RunRoll
|
|
global RsQueryBoxMultiBtn_OutVal = RsQueryBoxMultiBtn_run "" optionsStruct:RsQueryBoxMultiBtn_options
|
|
)
|
|
)
|
|
|
|
createDialog RsQueryBoxMultiBtn_RunRoll pos:[-20,-20] modal:true
|
|
globalVars.remove "RsQueryBoxMultiBtn_options"
|
|
|
|
local retVal = RsQueryBoxMultiBtn_OutVal
|
|
globalVars.remove "RsQueryBoxMultiBtn_OutVal"
|
|
|
|
return retVal
|
|
)
|
|
|
|
-- Test-queries:
|
|
--if RsQueryBoxTimeOut != undefined do
|
|
--global blah = #{1..2}
|
|
-- RsQueryBoxMultiBtn "test" modal:False timeout:10 checkLabels:#("Something", "Something else") checkStates:#{2} listTitles:#("Sync", "B", "C") listItems:#(#("somethings sdiofjpiod dfjigpd jiopgdfjig gfoipds gsp[g gdfjiopg jpdpfgsj po","status"), #("blargfs","spatus")) listCheckStates:#{2}
|
|
-- RsQueryBoxMultiBtn "test" modal:True timeout:10 checkLabels:#("Something", "Something else") checkStates:blah listTitles:#("Sync", "B", "C") listItems:#(#("somethings sdiofjpiod dfjigpd jiopgdfjig gfoipds gsp[g gdfjiopg jpdpfgsj po","status"), #("blargfs","spatus")) listCheckStates:#{2}
|
|
-- RsQueryBoxMultiBtn "testy testy test, \nlalala" timeout:10 listItems:#(#("somethings sdiofjpiod dfjigpd jiopgdfjig gfoipds gsp[g gdfjiopg jpdpfgsj po","status"), #("blargfs","spatus")) listCheckStates:#{2}
|
|
|
|
fn RsQueryBoxTimeOut message title:"Query" timeout:60 yesToAll:false defaultBtn:1 cancel:false yesText:"Yes" noText:"No" =
|
|
(
|
|
global RsDialogYesToAll, RsDialogFirstYesToAll, RsMapExportCancelled
|
|
local retVal = false
|
|
|
|
if (RsDialogYesToAll == undefined) do
|
|
(
|
|
RsDialogYesToAll = false
|
|
RsDialogFirstYesToAll = true
|
|
)
|
|
|
|
if yesToAll and RsDialogYesToAll then
|
|
(
|
|
retVal = true
|
|
)
|
|
else
|
|
(
|
|
local btnLabels = #()
|
|
local yesToAllBtn = -1
|
|
local yesBtn = 1
|
|
local noBtn = 2
|
|
local cancelBtn = -1
|
|
|
|
if yesToAll do
|
|
(
|
|
append btnLabels "Yes To All"
|
|
yesToAllBtn = 1
|
|
yesBtn += 1
|
|
noBtn += 1
|
|
|
|
-- Only default to first "Yes To All" seen, the rest will default to just "Yes"
|
|
defaultBtn = if RsDialogFirstYesToAll then yesToAllBtn else yesBtn
|
|
)
|
|
join btnLabels #(yesText, noText)
|
|
if cancel do
|
|
(
|
|
append btnLabels "Cancel"
|
|
cancelBtn = btnLabels.count
|
|
)
|
|
|
|
local queryVal = RsQueryBoxMultiBtn message title:title timeout:timeout labels:btnLabels defaultBtn:defaultBtn cancelBtn:cancelBtn
|
|
|
|
case queryVal of
|
|
(
|
|
yesToAllBtn:
|
|
(
|
|
retVal = true
|
|
RsDialogYesToAll = true
|
|
)
|
|
yesBtn:
|
|
(
|
|
retVal = true
|
|
)
|
|
noBtn:
|
|
(
|
|
retVal = false
|
|
)
|
|
cancelBtn:
|
|
(
|
|
retVal = false
|
|
RsMapExportCancelled = true
|
|
)
|
|
)
|
|
|
|
-- Only show the timer on "Yes To All" once per export-session:
|
|
RsDialogFirstYesToAll = false
|
|
)
|
|
|
|
return retVal
|
|
)
|
|
|
|
--RsDialogYesToAll = false
|
|
--RsDialogFirstYesToAll = true
|
|
--RsQueryBoxTimeOut "testy" timeout:50 yesToAll:true cancel:true
|
|
--RsQueryBoxTimeOut "testy" timeout:-1 yesToAll:false cancel:true yesText:"Checkout/Add" noText:"Make Writable"
|
|
|
|
fn RsQueryBoxAll message title:"Query" timeout:-1 defaultBtn:1 cancelBtn: =
|
|
(
|
|
local queryVal = RsQueryBoxMultiBtn message title:title labels:#("Yes", "Yes To All", "No", "No To All") timeout:timeout defaultBtn:defaultBtn cancelBtn:cancelBtn
|
|
|
|
return case queryVal of
|
|
(
|
|
1:#yes
|
|
2:#yesAll
|
|
3:#no
|
|
4:#noAll
|
|
)
|
|
)
|
|
|
|
-- Create a Notepad-like text-window:
|
|
fn RScreateTextWindow text:"" title:"" wordWrap:false width:600 height:300 position: readonly:true =
|
|
(
|
|
local showText = replace_LF_with_CRLF text
|
|
|
|
local newDialog = dotNetObject "MaxCustomControls.MaxForm" width:width height:height
|
|
newDialog.text = title
|
|
newDialog.width = width
|
|
newDialog.height = height
|
|
|
|
local textCtrl = dotNetObject "MaxCustomControls.MaxTextBox"
|
|
textCtrl.readOnly = true
|
|
textCtrl.multiline = true
|
|
textCtrl.scrollbars = textCtrl.ScrollBars.both
|
|
textCtrl.wordWrap = wordWrap
|
|
textCtrl.text = showText
|
|
textCtrl.SelectionStart = 0
|
|
textCtrl.SelectionLength = 0
|
|
textCtrl.size = newDialog.ClientSize
|
|
textCtrl.readonly = readonly
|
|
|
|
local anchorStyles = dotnetclass "System.Windows.Forms.AnchorStyles"
|
|
textCtrl.Anchor = dotNet.combineEnums anchorStyles.left anchorStyles.right anchorStyles.top anchorStyles.bottom
|
|
|
|
newDialog.controls.add textCtrl
|
|
newDialog.ShowModeless()
|
|
|
|
if (position != unsupplied) do
|
|
(
|
|
newDialog.top = position.y
|
|
newDialog.left = position.x
|
|
)
|
|
|
|
-- Retuns the textbox, allowing for easy text-changing later:
|
|
return textCtrl
|
|
)
|