module HTk.Toolkit.DialogWin (
Dialog,
dialog,
createAlertWin,
createErrorWin,
createWarningWin,
createConfirmWin,
createMessageWin,
createAlertWin',
createErrorWin',
createWarningWin',
createConfirmWin',
createMessageWin',
createDialogWin,
createDialogWin',
loadHTkImages,
questionImg,
useHTk,
) where
import Data.Maybe(fromMaybe)
import System.IO.Unsafe
import Util.Messages
import Util.ExtendedPrelude (newFallOut,mkBreakFn)
import Util.Computation
import Events.Events
import HTk.Kernel.Core
import qualified HTk.Toplevel.HTk as HTk (font)
import HTk.Toplevel.HTk hiding (font)
import HTk.Widgets.Space
import HTk.Toolkit.SelectBox
import HTk.Toolkit.ModalDialog
import HTk.Toolkit.MarkupText
import HTk.Toolkit.Separator
type Choice a = (String,a)
data Dialog a = Dialog {
fWindow :: Toplevel,
fEditor :: Maybe Editor,
fMsg :: Maybe Message,
fLabel :: Label,
fSelectBox :: SelectBox,
fEvents :: (Event a)
}
instance GUIObject (Dialog a) where
toGUIObject dlg = toGUIObject (fWindow dlg)
cname dlg = cname (fWindow dlg)
instance HasPhoto (Dialog a) where
photo p dlg = do {fLabel dlg # photo p; return dlg}
instance HasMarkupText (Dialog a) where
new t dlg =
case fEditor dlg of
Just e -> do {e # new t; return dlg}
_ -> return dlg
insertAt _ _ _ = error
"HTk.Toolkit.DialogWin.instance HasMarkupText (Dialog a) insertAt"
clear = error
"HTk.Toolkit.DialogWin.instance HasMarkupText (Dialog a) clear"
instance GUIValue v=> HasText (Dialog a) v where
text t dlg =
case fMsg dlg of
Just l -> do {l # text t; return dlg}
_ -> return dlg
scrollText :: String -> (Config (Dialog a),Bool)
scrollText = scrollText1 (60,6)
scrollText1 :: Size -> String -> (Config (Dialog a),Bool)
scrollText1 size str =
if biggerThan size str
then
(new [scrollMarkupText (39,6) [prose str]],True)
else
(text str,False)
where
biggerThan (xMax,yMax) str =
let
strl = lines str
in
length strl > fromIntegral yMax
|| any (\ line -> length line > fromIntegral xMax) strl
createAlertWin :: String
-> [Config Toplevel]
-> IO ()
createAlertWin str wol =
do
catchDestroyedFallOut (createFn choices Nothing confs (defs ++ wol))
done
where
choices = [("Continue",())]
defs = [text "Alert Window"]
(scrollConf,complex) = scrollText str
confs = [scrollConf,photo warningImg]
createFn = if complex then createDialogWin' else createDialogWin
createAlertWin' :: [MarkupText]
-> [Config Toplevel]
-> IO ()
createAlertWin' str wol =
do
catchDestroyedFallOut (
createDialogWin' choices Nothing (confs++[photo warningImg])
(defs ++ wol)
)
done
where choices = [("Continue",())]
defs = [text "Alert Window"]
confs = [new str]
createErrorWin :: String
-> [Config Toplevel]
-> IO ()
createErrorWin str wol =
do
catchDestroyedFallOut (createFn choices Nothing confs (defs++wol))
done
where
choices = [("Continue",())]
defs = [text "Error Message"]
(scrollConf,complex) = scrollText str
confs = [scrollConf,photo errorImg]
createFn = if complex then createDialogWin' else createDialogWin
createErrorWin' :: [MarkupText]
-> [Config Toplevel]
-> IO ()
createErrorWin' str wol =
do
catchDestroyedFallOut (
createDialogWin' choices Nothing (confs++[photo errorImg]) (defs++wol)
)
done
where choices = [("Continue",())]
defs = [text "Error Message"]
confs = [new str]
createWarningWin :: String
-> [Config Toplevel]
-> IO ()
createWarningWin str confs = createAlertWin str (text "Warning Message": confs)
createWarningWin' :: [MarkupText]
-> [Config Toplevel]
-> IO ()
createWarningWin' str confs =
createAlertWin' str (text "Warning Message": confs)
createConfirmWin :: String
-> [Config Toplevel]
-> IO Bool
createConfirmWin str wol =
do
bOpt <- catchDestroyedFallOut (
createFn choices (Just 0) confs (defs ++ wol)
)
return (fromMaybe False bOpt)
where
choices = [("Ok",True),("Cancel",False)]
defs = [text "Confirm Window"]
(scrollConf,complex) = scrollText str
confs = [scrollConf,photo questionImg]
createFn = if complex then createDialogWin' else createDialogWin
createConfirmWin' :: [MarkupText]
-> [Config Toplevel]
-> IO Bool
createConfirmWin' str wol =
do
bOpt <- catchDestroyedFallOut (
createDialogWin' choices (Just 0) (confs++[photo questionImg])
(defs ++ wol)
)
return (fromMaybe False bOpt)
where choices = [("Ok",True),("Cancel",False)]
defs = [text "Confirm Window"]
confs = [new str]
createMessageWin' :: [MarkupText]
-> [Config Toplevel]
-> IO ()
createMessageWin' str wol =
do
catchDestroyedFallOut (
createDialogWin' [("Dismiss", ())] Nothing
[new str, photo infoImg]
(text "Information": wol)
)
done
createMessageWin :: String
-> [Config Toplevel]
-> IO ()
createMessageWin str wol =
do
catchDestroyedFallOut (
createFn [("Dismiss", ())] Nothing confs (text "Information": wol)
)
done
where
(scrollConf,complex) = scrollText str
confs = [scrollConf,photo infoImg]
createFn = if complex then createDialogWin' else createDialogWin
createDialogWin :: [Choice a]
-> Maybe Int
-> [Config (Dialog a)]
-> [Config Toplevel]
-> IO a
createDialogWin choices def confs wol =
do
dlg <- dialog True choices def confs wol
result <- modalInteraction (fWindow dlg) True True (fEvents dlg)
return result
createDialogWin' :: [Choice a]
-> Maybe Int
-> [Config (Dialog a)]
-> [Config Toplevel]
-> IO a
createDialogWin' choices def confs wol =
do
dlg <- dialog False choices def confs wol
result <- modalInteraction (fWindow dlg) True True (fEvents dlg)
return result
dialog :: Bool
-> [Choice a]
-> Maybe Int
-> [Config (Dialog a)]
-> [Config Toplevel]
-> IO (Dialog a)
dialog plain choices def confs tpconfs =
do
(tp, emsg, lmsg, lbl, sb, ev) <- delayWish $
do
tp <- createToplevel tpconfs
pack tp [Expand On, Fill Both]
b <- newVBox tp []
pack b [Expand On, Fill Both]
b2 <- newHBox b []
pack b2 [Expand On, Fill Both]
lbl <- newLabel b2 []
pack lbl [Expand On, Fill Both, PadX (cm 0.5), PadY (cm 0.5)]
(lmsg, emsg) <-
if plain then
do l <- newMessage b2 [borderwidth 0,
justify JustCenter,
aspect 750,
HTk.font (Helvetica, Roman, 18::Int)]
pack l [Expand On, Fill Both, PadX (cm 0.5), PadY (cm 0.5)]
return (Just l, Nothing)
else do msg <- newEditor b2 [size (30,5), borderwidth 0,
state Disabled, wrap WordWrap,
HTk.font (Helvetica, Roman, 18::Int)]
pack msg [Expand On, Fill Both, PadX (cm 0.5),
PadY (cm 0.5)]
return (Nothing, Just msg)
sp1 <- newSpace b (cm 0.15) []
pack sp1 [Expand Off, Fill X, Side AtBottom]
newHSeparator b
sp2 <- newSpace b (cm 0.15) []
pack sp2 [Expand Off, Fill X, Side AtBottom]
sb <- newSelectBox b Nothing []
pack sb [Expand Off, Fill X, Side AtBottom]
events0 <- mapM (createChoice sb) choices
let ev0 = choose events0
(destroyEvent,unbindAction) <- bindSimple tp Destroy
let
ev =
(do
result <- ev0
always unbindAction
return result
)
+> (do
destroyEvent
always unbindAction
destroyedFallOut
)
return (tp, emsg, lmsg, lbl,sb,ev)
dlg <- configure (Dialog tp emsg lmsg lbl sb ev) confs
return dlg
where createChoice :: SelectBox -> Choice a -> IO (Event a)
createChoice sb (str,val) =
do
but <- addButton sb [text str] [Expand On, Side AtRight]
clickedbut <- clicked but
return (clickedbut >> (always (return val)))
destroyedFallOutPair :: (ObjectID,IO a -> IO (Either String a))
destroyedFallOutPair = unsafePerformIO newFallOut
destroyedFallOut :: a
destroyedFallOut = mkBreakFn (fst destroyedFallOutPair) "DESTROYED"
catchDestroyedFallOut :: IO a -> IO (Maybe a)
catchDestroyedFallOut act =
do
strOrA <- (snd destroyedFallOutPair) act
return (case strOrA of
Left "DESTROYED" -> Nothing
Right a -> Just a
)
htkMessFns :: MessFns
htkMessFns = MessFns {
alertFn = (\ mess -> createAlertWin mess []),
errorFn = (\ mess -> createErrorWin mess []),
warningFn = (\ mess -> createWarningWin mess []),
confirmFn = (\ mess -> createConfirmWin mess []),
messageFn = (\ mess -> createMessageWin mess []),
htkPres = True
}
useHTk :: IO ()
useHTk = setMessFns htkMessFns
loadHTkImages :: ()
loadHTkImages = foldr seq () [errorImg,warningImg,questionImg,infoImg]
errorImg :: Image
errorImg = unsafePerformIO (newImage [imgData GIF "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"])
warningImg :: Image
warningImg = unsafePerformIO (newImage [imgData GIF "R0lGODlhMAAwAPU3AAAAABYKAhoUARQUFCcIBiUdAz0MCCsiAzUpBSsrK0YNCE0QDFIOB1wSC0U1BlE/B2kTC3QVDXgYEVJAB2hRCnNZC3thC4gYDYcbEpQbD5weFKQdDqEdEbMfD7IfELkgD7khEatCFrFAELpbEr9vFpJPSMkjEdYlE+opFPUqE8JtFMd+FbmTDr2TEsyHFMObD8ebE9GKE9uqFt+xEuCuEuCyE4CAgP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAFkADcALAAAAAAwADAAAAb+wNvtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73YC32+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrsBb7fb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12A95ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Qa83W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9v+7Xa73W632+12u91ut9vtdrvdbrfbDXi73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa7oVKmjO12u91utxvwdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa7oVKnzQUAuN1ut9vtdrvdbrfb7Xa73W434O12u91ut9vtdrvdbrfb7Xa7bVKnzSYDAQBut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbsDb7Xa7bVKoz2bDuRAGgNvtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa7pVKdzQa0yUCAAMDtdrvdbrfb7Xb+u91ut9vtdrvdbrfb7Xa73W632+12u21Sps1mRNpsMgYA4Ha73W632+12uwFvt9vtdrvdbrfb7Xa73W632+12u21Sp81mM5ttNhsJAAC43W632+12u91ut9vtdrvdbrfb7XYD3m632+12u91QqM5mM5vNYhtOZgEA3G632+12u91ut9vtdrvdbrfb7Xa73W632+12u21Sps1GBZzNZjMOhxMBAAC32+12u91ut9vtdrvdbrfb7Xa73W632+12u21SqM1mQ5uxZDLXRpNZAAC32w14u91ut9vtdrvdbrfb7Xa73W632+12u91Qqc5mE3sBAo6ZbLPRSAAAwO12u93+brfb7Xa73W63G/B2u91ut9vtdrvdNqnTZrOZWQABwIzm2mgwCwDgdrvdbrfb7Xa73W632+12u91ut9vtdrvdUCigZ7OZzQ4AgGBGk2k2GgkAALjdbrfb7Xa73W632+12u91ut9vtdrvdNinTZhOj0Q4AQIEmk7k2QI1mAQDcbrfb7Xa73W632+12u91ut9vtdrvdNqnTZrOh0WgFgMAhk8lkGo1GAgAAbrfb7Xa73YC32+12u91ut9vtdrvdbhFUZ7OJ0Wi0B8DhkMlkMpdGg1kAALfb7Xa73W632+12u91ut9vtdrsBb5vUabPZ0Gi0mQBQcMhoMplMo9FAAAD+wO12u91ut9vtdrvdbrfb7Xa73W4oFGizqdVmslkAEAAWZDKZTObSaCQEAOB2u91ut9vtdrvdbrfb7Xa73W4b1GmzidFqspkMEAAgZDKZTCbTaDQNwAAAvN1ut9vtdrvdbrfb7Xa73W43FArE2cxqsplsBggAJjKZTCaTuTQayQAAuN1ut9vtdrvdbrfbDXi73W63DerE4cRmNBlNNkNMBBWZTCaTyWQaDWYBANxut9vtdrvdbrfb7Xa73W43FOqz2cxmMxlwJpO1KIeWTCaTyWQyl0YjAQAAt9vtdrvdbrfb7Xa73W63Deq02cRmMtlMJpPJZDKZTCaTyWQyoAz+o8EsAIDb7Xa73W632+12u91utxsKBdJsZjIaTSaTyWCHQksmk8lkMpmMpNE0AADA7Xa73W7A2+12u91ut9sGddpsYjSajCaTyWQPAIAik8lkMplM5tJoJAQA4Ha73W632+12u91ut1sJBeJsgDJajSaTyWQyBCBQkclkMplMJpNpNJgFAHC73W632+12u91ut9sGddpwXDVaTSaTyWSyFsIikwFlMplMJpPJSBoNBDAA3G632+12u91ut9stggJtOBsOh8PhjFQul0wmk8lkMplMJpPBSCWNhAAAJm632+12u91ut9vtpjBtOBwOh8PhcDQcDkej0Wg0Go1Go9H+aDQajQazAAAAt9vtdrvdbrfb7QYMSBqRSOSCyWg0Go1Go+FoNBqNRqPRaDQajUajaQAAgNvtdrvdbrfb7XYDAACAAIFgWDQaDYgEKJFgMBgMBoPBSCQYDAYjkSwAA8Dtdrvdbrfb7Xa7AQAAAAAAAAAAAECAQCAQFAaDQmEwJAwGA9BgMBAGAADgdrvdbrfb7Xa73QAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAGAAAAwAAADgdrvdbjfg7Xa73W43AAAAGAQAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAcLvdbrfb7Xa73W632+12AwAAQAAAAAAAAIPAAAAAAAD+AAAAAAAAAAAAAAC43W632+12u91ut9vtdrvdbrfb7Xa7AQAAAAAAAACAAAAAAAAAAAAAAHC73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa7AW+32+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdgPebrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+0GvN1ut9vtdrvdbrfb7Xa73W632+12u91ut9vtdrvdbrfb7Xa73W632+12u91ut9sT7Xa73W632w14u91ut9vtdrsFAQA7"])
questionImg :: Image
questionImg = unsafePerformIO (newImage [imgData GIF "R0lGODlhMAAwAPUxAAAAABkVDRYWFiIcEjk5OSs9YTVFZGVPJG1VJ3FYKHNfO3xiLX9pQWNjY35+f4FlLopsMZZ2N6J/O5J8UqeDPKaHSKSMWbONQL2URL6bU7+iZ76icsCXRcOfVsmkW9eqTtisWtixX8WmaMmsc9e0a9m6effDWvfJbffPfqqqqti+htzElPfUjPfYmfferffiuPflwP///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAFkADIALAAAAAAwADAAAAb+QJlMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyYAymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpMBZTKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmA8pkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTAaUyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMpn+TCaTyWQymUwmk8lkMplMJpPJZDKZDCiTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMhlQJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZLIAAAAAAAAAAEAmk8lkMplMJpPJZDKZTCaTyWQyoEwmk8lkMplMJpPJZDIAAEDBfCKUBQAAAMhkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZEAA4NNqvVqlUilDAQAAMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZACA6QVrsUwmE6pEoiCAAIBMJpPJZDKZTCb+k8lkMplMJpPJZDKZTCaTyWQBgMnlMlUiEYrJhCKFKAAAQCaTyWQymUwmkwFlMplMJpPJZDKZTCaTyWQygKb1MkUAAAAgYjKdQqEHACCQyWQymUwmk8lkMplMJpPJZDKZTCYDymSyAOD0QkUAAEABAOiYUJ8QBQAAyGQymUwmk8lkMplMJpPJZDKZTCaTyWQygIX1+gAAAIPDAQRYTKfQhwIAAGIymUwmk8lkMplMJpPJZDKZTCaTyWQyGeDDMlEAAIMjFgNYTifS5wEAAFIxmQwok8lkMplMJpPJZDKZTCaTyWQymQxgYpkoAIAjFpMBLCYS6XMAAACpmEwmk8n+ZDKZTCaTyWQyGVAmk8lkMplMBiCRMA8AwBGTAQCiU+lTAQAAjlRMJpPJZDKZTCaTyWQymUwmk8lkMplMBgAAAAAgAOCIyQAQkir0SQAAAEcqJpPJZDKZTCaTyWQymUwmk8lkMplMJgMAAAAAQOCIAQAYlurDAQAAQIAjJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJABOHxeFwAACXk+rzAQAAAEcqJpPJZDKZTCaTyYAymUwmk8lkMplMJpPJZDKAw+FwxAAAE4sEigAAAEEqJpPJZDKZTCaTyWQymUwmk8lkMplMJpMBZTKZTCaTyQCIzqo0EgUAAIEjFZPJZDL+mUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8kADxLJIwJOAACAIxWTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkgEiJBNoAAABHKiaTyWQymUwGlMlkMplMJpPJZDKZTCaTyWQymUwmk8lkMgCnRAJNAACAIyaTyWQymUwmk8lkMplMJpPJZDKZDCiTyWQymUwmk8lkMhngoyJ9FACAIxWTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMhkQkCl9MAAAIBWTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMpkMUKlQFgAAIBWTyWQyoEz+JpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTAYQEAAAACCVislkMplMJpPJZDKZTCaTyWRAmUwmk8lkMplMJpPJZDKZTCYDAAAAAADgiMlkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJgDKZTCaTyQAWR8PhSMVkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyQYAAAAAiAFlMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyQAlFAsDAABkMplMJpPJZDKZTCYDymQymUwmk8lkMplMJpPJZDKZTCaTyWQAVKsFAgAAMplMJpP+yWQymUwmk8lkMplMJpPJZDKZTAaUyWQymUwmk8lkMgCLFcIAAIBUTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMgALSPpgAABAKiaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMhngQ+IkAABAKiaTyWQyGVAmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMBgAAAAAAIBWTyWQymUwmk8lkMplMJpPJZDKgTCaTyWQymUwmk8lkMplMJgMAAAAAwJGKyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkQJlMJpPJAAAAIOVIxWT+MplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQAh8ORismAMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTAWUymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJgPKZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwGlMlkMplMJpPJZDKZTCaTyWQymUwmk8lkMplMJpPJZDKZTCaTyWQymUwmk8lkMpkTTCaTyWQymQwok8lkMplMJpMFAQA7"])
infoImg :: Image
infoImg = unsafePerformIO (newImage [imgData GIF "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"])