vision-0.0.2.2: src/Properties/Editor/UI.hs
-- -*-haskell-*-
-- Vision (for the Voice): an XMMS2 client.
--
-- Author: Oleg Belozeorov
-- Created: 6 Jul. 2010
--
-- Copyright (C) 2010 Oleg Belozeorov
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License as
-- published by the Free Software Foundation; either version 3 of
-- the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- General Public License for more details.
--
module Properties.Editor.UI
( initEditorUI
, showPropertyEditor
) where
import Control.Concurrent.MVar
import Control.Monad
import Data.IORef
import Graphics.UI.Gtk hiding (add, remove)
import Context
import Utils
import Handler
import UI
import XMMS
import Medialib
import Properties.Editor.Model
import Properties.Editor.View
data UI
= UI { uLock :: MVar ()
, uDialog :: Dialog
, uPrevB :: Button
, uNextB :: Button
, uPtrkB :: ToggleButton
, uPBar :: ProgressBar
, uCancel :: IORef (Maybe (IO ()))
}
tryLock f =
maybe (return False) (const $ f >> return True)
=<< (tryTakeMVar $ uLock context)
unlock = tryPutMVar (uLock context) () >> return ()
dialog = uDialog context
prevB = uPrevB context
nextB = uNextB context
ptrkB = uPtrkB context
pBar = uPBar context
setRetrievalCancel = writeIORef (uCancel context) . Just
cancelRetrieval = do
cancel' <- readIORef (uCancel context)
fmaybeM_ cancel' id
writeIORef (uCancel context) Nothing
initEditorUI = do
context <- initContext
let ?context = context
hideOnDeleteEvent dialog
windowSetModal dialog False
windowSetTitle dialog "Edit properties"
windowSetDefaultSize dialog 800 600
dialogSetHasSeparator dialog False
dialogAddButton dialog stockApply ResponseApply
dialogAddButton dialog stockCancel ResponseCancel
dialogAddButtonCR dialog stockOk ResponseOk
box <- vBoxNew False 0
containerSetBorderWidth box 7
upper <- dialogGetUpper dialog
boxPackStartDefaults upper box
hbox <- hBoxNew False 15
boxPackStart box hbox PackNatural 7
bbox <- hButtonBoxNew
buttonBoxSetLayout bbox ButtonboxStart
boxSetSpacing bbox 7
boxPackStart hbox bbox PackNatural 0
boxPackStartDefaults hbox pBar
prevB `onClicked` (prevTrack >> updateNavButtons)
widgetSetCanFocus prevB False
containerAdd bbox prevB
nextB `onClicked` (nextTrack >> updateNavButtons)
widgetSetCanFocus nextB False
containerAdd bbox nextB
ptrkB `onToggled` (togglePerTrack >> updateNavButtons)
widgetSetCanFocus ptrkB False
containerAdd bbox ptrkB
scroll <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy scroll PolicyAutomatic PolicyAutomatic
scrolledWindowSetShadowType scroll ShadowIn
containerAdd scroll view
boxPackStartDefaults box scroll
onPropertyEdited $ \[n] t -> do
prop <- listStoreGetValue store n
chok <- changeProperty n prop t
when chok $ do
dialogSetResponseSensitive dialog ResponseApply True
updateTitle True False
dialog `onResponse` \resp ->
case resp of
ResponseApply -> do
doWriteProperties
dialogSetResponseSensitive dialog ResponseOk True
widgetGrabFocus view
ResponseOk -> do
doWriteProperties
hideEditor
_ -> do
cancelRetrieval
hideEditor
onServerConnection . add . ever $ \conn ->
unless conn $ do
cancelRetrieval
widgetSetSensitive prevB False
widgetSetSensitive nextB False
widgetSetSensitive ptrkB False
dialogSetResponseSensitive dialog ResponseApply False
dialogSetResponseSensitive dialog ResponseOk False
progressBarSetFraction pBar 0
progressBarSetText pBar "Disconnected"
updateTitle False False
unlock
widgetShowAll box
return ?context
doWriteProperties = do
dialogSetResponseSensitive dialog ResponseApply False
dialogSetResponseSensitive dialog ResponseOk False
writeProperties
updateTitle False False
hideEditor = do
widgetHide dialog
resetModel
unlock
updateTitle m r = do
c <- connected
windowSetTitle dialog $ case c of
False -> "Edit properties (disconnected)"
True | m -> "Edit properties (modified)"
_ | r -> "Edit properties (retrieving)"
_ -> "Edit properties"
showPropertyEditor ids = do
retr <- tryLock $ do
dialogSetResponseSensitive dialog ResponseApply False
dialogSetResponseSensitive dialog ResponseOk False
widgetSetSensitive ptrkB False
updateNavButtons
widgetShow pBar
resetView
setRetrievalCancel =<< do
progressBarSetFraction pBar 0
progressBarSetText pBar "Retrieving properties"
retrieveProperties ids $ \prog ->
case prog of
Left frac ->
progressBarSetFraction pBar frac
Right list -> do
toggleButtonSetActive ptrkB True
widgetSetSensitive ptrkB True
populateModel list
dialogSetResponseSensitive dialog ResponseApply False
dialogSetResponseSensitive dialog ResponseOk True
updateNavButtons
widgetHide pBar
updateTitle False False
widgetHide dialog
windowSetTransientFor dialog window
updateTitle False retr
windowPresent dialog
initContext = do
lock <- newMVar ()
dialog <- dialogNew
prevB <- buttonNewWithMnemonic "_Previous track"
nextB <- buttonNewWithMnemonic "_Next track"
ptrkB <- toggleButtonNewWithMnemonic "Per _track"
pBar <- progressBarNew
cancel <- newIORef Nothing
return $ augmentContext
UI { uLock = lock
, uDialog = dialog
, uPrevB = prevB
, uNextB = nextB
, uPtrkB = ptrkB
, uPBar = pBar
, uCancel = cancel
}
updateNavButtons = do
(ep, en) <- getNavEnables
widgetSetSensitive prevB ep
widgetSetSensitive nextB en