module Manatee.Plugin.Anything.AnythingView where
import Control.Applicative hiding (empty)
import Control.Concurrent.STM
import Control.Monad
import DBus.Client hiding (Signal)
import Data.List
import Data.Maybe
import GHC.Conc
import Graphics.UI.Gtk hiding (get)
import Manatee.Core.DBus
import Manatee.Core.Types
import Manatee.Plugin.Anything.AnythingList
import Manatee.Plugin.Anything.TitleWidget
import Manatee.Plugin.Anything.Types
import Manatee.Toolkit.General.Basic
import Manatee.Toolkit.General.List
import Manatee.Toolkit.General.Map
import Manatee.Toolkit.General.Maybe
import Manatee.Toolkit.General.STM
import Manatee.Toolkit.Gtk.Box
import Manatee.Toolkit.Gtk.Concurrent
import Manatee.Toolkit.Gtk.Container
import Manatee.Toolkit.Gtk.Gtk
import Manatee.Toolkit.Gtk.ModelView
import qualified Data.Map as M
import qualified Control.Exception as Exc
anythingCandidateViewLimit :: Int
anythingCandidateViewLimit = 10
anythingViewDefaultCellHeight :: Int
anythingViewDefaultCellHeight = 24
anythingCandidateTabIndex :: Int
anythingCandidateTabIndex = 0
anythingCommandTabIndex :: Int
anythingCommandTabIndex = 1
anythingViewNew :: AnythingInteractiveType -> [String] -> IO AnythingView
anythingViewNew iType names = do
notebook <- notebookNew
notebookSetTabPos notebook PosBottom
notebookSetShowTabs notebook False
candidateBox <- vBoxNew False 0
candidateTab <- (<=<) newTVarIO anythingCandidateTabNew names
currentCandidateIndex <- newTVarIO 0
candidateScrolledWindow <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy candidateScrolledWindow PolicyNever PolicyNever
scrolledWindowAddWithViewport candidateScrolledWindow candidateBox
notebookInsertPage notebook candidateScrolledWindow "Candidate Tab" anythingCandidateTabIndex
(commandView, commandStore, commandWin) <- anythingViewCommandTabNew "Command"
notebookInsertPage notebook commandWin "Command Tab" anythingCommandTabIndex
let commandTab = AnythingCommandView commandView commandStore
typ <- newTVarIO iType
widgetShowAll notebook
return $ AnythingView notebook candidateBox candidateScrolledWindow
candidateTab commandTab currentCandidateIndex typ
anythingCandidateTabNew :: [String] -> IO AnythingCandidateTab
anythingCandidateTabNew names = do
let anythings = mapMaybe (`M.lookup` anythingList) names
columnInfoList = map (\x -> zip (anythingColumnTitle x) (anythingColumnFun x)) anythings
liftM M.fromList $ zipWithIndexM columnInfoList $ \ columnInfo index -> do
let name = fst $ head columnInfo
(view, scrolledWin, store, titleWidget) <- anythingViewCandidateTabNew columnInfo
return (index, ((name, 0), AnythingCandidateView view scrolledWin store titleWidget))
anythingViewCandidateTabNew :: [(AnythingColumnTitle, AnythingColumnFun)]
-> IO (TreeView, ScrolledWindow, AnythingCandidateStore, TitleWidget)
anythingViewCandidateTabNew columnInfo = do
store <- listStoreNew []
treeView <- treeViewNewWithModel store
selection <- treeViewGetSelection treeView
treeSelectionSetMode selection SelectionBrowse
scrolledWindow <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy scrolledWindow PolicyNever PolicyAutomatic
scrolledWindow `containerAdd` treeView
titleWidget <- titleWidgetNew Nothing
zipWithIndexM_ columnInfo $ \ (columnTitle, columnFun) index -> do
treeViewColumn <- treeViewColumnNew
treeViewAppendColumn treeView treeViewColumn
if index == 0
then do
set treeViewColumn [treeViewColumnWidget := Just (titleWidgetBox titleWidget)]
titleWidgetSetTitle titleWidget columnTitle 0
else
set treeViewColumn [treeViewColumnTitle := columnTitle]
cellRenderer <- cellRendererTextNew
treeViewColumnPackStart treeViewColumn cellRenderer True
cellLayoutSetAttributes treeViewColumn cellRenderer store $ \candidates ->
[cellText := columnFun candidates]
return (treeView, scrolledWindow, store, titleWidget)
anythingViewCommandTabNew :: String -> IO (TreeView, AnythingCommandStore, ScrolledWindow)
anythingViewCommandTabNew name = do
store <- listStoreNew []
treeView <- treeViewNewWithModel store
scrolledWindow <- scrolledWindowNew Nothing Nothing
scrolledWindowSetPolicy scrolledWindow PolicyNever PolicyAutomatic
scrolledWindow `containerAdd` treeView
treeViewColumn <- treeViewColumnNew
set treeViewColumn [ treeViewColumnTitle := name]
treeViewAppendColumn treeView treeViewColumn
cellRenderer <- cellRendererTextNew
treeViewColumnPackStart treeViewColumn cellRenderer True
cellLayoutSetAttributes treeViewColumn cellRenderer store $ \text ->
[ cellText := text ]
return (treeView, store, scrolledWindow)
anythingViewSetCandidates :: AnythingView -> Client -> AnythingName -> [AnythingCandidateWrap] ->
AnythingInput -> AnythingCompletionRule -> AnythingKeyPressId -> IO ()
anythingViewSetCandidates view client name candidates input rule keyPressId = do
candidateTab <- readTVarIO $ avCandidateTab view
findMinMatch candidateTab (\ _ v -> (fst . fst) v == name)
?>= \ (index, ((candidateName, _)
,candidateView@(AnythingCandidateView {acavListStore = listStore
,acavTitleWidget = titleWidget}))) -> do
let candidateNumber = length candidates
listStoreClear listStore
unless (null candidates) $ do
forM_ candidates (listStoreAppend listStore)
titleWidgetSetTitle titleWidget name candidateNumber
modifyTVarIO (avCandidateTab view) (M.insert index ((candidateName, length candidates), candidateView))
readTVarIO (avCandidateTab view) >>= \ candidateMap -> do
let (hideList, redrawList) =
partition (\ (_, ((_, num), _)) -> num == 0) $ M.toList candidateMap
forM_ hideList $ \ (_, (_, AnythingCandidateView {acavScrolledWindow = scrolledWin})) -> do
widgetHideAll scrolledWin
containerTryRemove (avCandidateBox view) scrolledWin
zipWithIndexM_ redrawList $ \ (_, ((name, num)
,AnythingCandidateView {acavTreeView = treeView
,acavScrolledWindow = scrolledWin})) index -> do
widgetShowAll scrolledWin
let lastCandidate = index == length redrawList 1
packing = if lastCandidate then PackGrow else PackNatural
boxTryPack (avCandidateBox view) scrolledWin packing (Just index) Nothing
adjustHeight <-
if lastCandidate
then screenHeight
else do
cellHeight <- anythingViewGetCellHeight treeView
headerHeight <- treeViewGetHeaderHeight treeView
return $ headerHeight + (if num < anythingCandidateViewLimit
then num
else anythingCandidateViewLimit) * cellHeight
widgetSetSizeRequest treeView (1) adjustHeight
when (index == 0 && name == candidateName) $ do
let completions = map (\ (AnythingCandidateWrap a) -> candidateCompletionName a input) candidates
completion = anythingViewGetCompletion input completions rule
boxHeight <- anythingViewGetBoxHeight view
mkDaemonSignal client AnythingViewOutput (AnythingViewOutputArgs input completion boxHeight keyPressId)
candidateMap <- readTVarIO $ avCandidateTab view
find (\ (_, ((_, count), _)) -> count > 0) (M.toList candidateMap)
?>= \ (index, (_, AnythingCandidateView {acavTreeView = treeView})) -> do
writeTVarIO (avCurrentCandidateIndex view) index
treePath <- treeViewGetSelectedPath treeView
when (isNothing treePath) $ do
treeViewFocusFirstToplevelNode treeView
anythingViewScrollSelectionCandidateToScreen view
anythingViewFocusNextCandidateView :: AnythingView -> IO ()
anythingViewFocusNextCandidateView view =
anythingViewFindCurrentCandidateView view
>?>= \ AnythingCandidateView {acavTreeView = treeView} -> do
treeViewUnselectAll treeView
nextCandidateView <- anythingViewGetNextCandidateView view
case nextCandidateView of
Just (nextIndex, AnythingCandidateView {acavTreeView = nextTreeView}) ->
anythingViewFocusCandidate view nextTreeView treeViewFocusFirstToplevelNode nextIndex
Nothing -> anythingViewFocusFirstCandidate view False
anythingViewScrollCandidateViewToTop view
anythingViewFocusPrevCandidateView :: AnythingView -> IO ()
anythingViewFocusPrevCandidateView view =
anythingViewFindCurrentCandidateView view
>?>= \ AnythingCandidateView {acavTreeView = treeView} -> do
treeViewUnselectAll treeView
prevCandidateView <- anythingViewGetPrevCandidateView view
case prevCandidateView of
Just (prevIndex, AnythingCandidateView {acavTreeView = prevTreeView}) ->
anythingViewFocusCandidate view prevTreeView treeViewFocusFirstToplevelNode prevIndex
Nothing -> anythingViewFocusLastCandidate view FocusFirstNode False
anythingViewScrollCandidateViewToTop view
anythingViewScrollCandidateViewToTop :: AnythingView -> IO ()
anythingViewScrollCandidateViewToTop view =
anythingViewFindCurrentCandidateView view
>?>= \ AnythingCandidateView {acavTreeView = treeView} -> do
treeViewY <- rectangleY <$> widgetGetAllocation treeView
vAdjust <- scrolledWindowGetVAdjustment $ avCandidateScrolledWindow view
adjustmentSetValue vAdjust (i2d treeViewY)
anythingViewFocusFirstCandidate :: AnythingView -> Bool -> IO ()
anythingViewFocusFirstCandidate view scrollToScreen = do
candidateMap <- readTVarIO $ avCandidateTab view
find (\ (_, ((_, count), _)) -> count > 0) (M.toList candidateMap)
?>= \ (index, (_, AnythingCandidateView {acavTreeView = treeView})) -> do
treeViewFocusFirstToplevelNode treeView
writeTVarIO (avCurrentCandidateIndex view) index
when scrollToScreen $ anythingViewScrollSelectionCandidateToScreen view
anythingViewFocusLastCandidate :: AnythingView -> FocusNode -> Bool -> IO ()
anythingViewFocusLastCandidate view focusNode scrollToScreen = do
candidateMap <- readTVarIO $ avCandidateTab view
find (\ (_, ((_, count), _)) -> count > 0) (reverse $ M.toList candidateMap)
?>= \ (index, (_, AnythingCandidateView {acavTreeView = treeView})) -> do
case focusNode of
FocusFirstNode -> treeViewFocusFirstToplevelNode treeView
FocusLastNode -> treeViewFocusLastToplevelNode treeView
writeTVarIO (avCurrentCandidateIndex view) index
when scrollToScreen $ anythingViewScrollSelectionCandidateToScreen view
anythingViewFocusNextCandidate :: AnythingView -> IO ()
anythingViewFocusNextCandidate view =
anythingViewFindCurrentCandidateView view
>?>= \ AnythingCandidateView {acavTreeView = treeView} -> do
atLastNode <- treeViewAtLastToplevelNode treeView
if atLastNode
then do
treeViewUnselectAll treeView
nextCandidateView <- anythingViewGetNextCandidateView view
case nextCandidateView of
Just (nextIndex, AnythingCandidateView {acavTreeView = nextTreeView}) ->
anythingViewFocusCandidate view nextTreeView treeViewFocusFirstToplevelNode nextIndex
Nothing -> anythingViewFocusFirstCandidate view True
else treeViewFocusNextToplevelNode treeView
anythingViewScrollSelectionCandidateToScreen view
anythingViewFocusPrevCandidate :: AnythingView -> IO ()
anythingViewFocusPrevCandidate view =
anythingViewFindCurrentCandidateView view
>?>= \ AnythingCandidateView {acavTreeView = treeView} -> do
atFirstNode <- treeViewAtFirstToplevelNode treeView
if atFirstNode
then do
treeViewUnselectAll treeView
prevCandidateView <- anythingViewGetPrevCandidateView view
case prevCandidateView of
Just (prevIndex, AnythingCandidateView {acavTreeView = prevTreeView}) ->
anythingViewFocusCandidate view prevTreeView treeViewFocusLastToplevelNode prevIndex
Nothing -> anythingViewFocusLastCandidate view FocusLastNode True
else treeViewFocusPrevToplevelNode treeView
anythingViewScrollSelectionCandidateToScreen view
anythingViewScrollSelectionCandidateToScreen :: AnythingView -> IO ()
anythingViewScrollSelectionCandidateToScreen view =
anythingViewFindCurrentCandidateView view
>?>= \ AnythingCandidateView {acavTreeView = treeView} ->
treeViewGetSelectedWidgetCoordinate treeView
>?>= \(Rectangle cx cy _ ch) ->
widgetTranslateCoordinates treeView (avCandidateBox view) cx cy
>?>= \(_, by) -> do
let candidateY = i2d by
candidateH = i2d ch
scrolledWindow = avCandidateScrolledWindow view
vAdjust <- scrolledWindowGetVAdjustment scrolledWindow
currentValue <- adjustmentGetValue vAdjust
pageSize <- adjustmentGetPageSize vAdjust
if candidateY < currentValue
then do
atFirstToplevelNode <- treeViewAtFirstToplevelNode treeView
adjustValue <- if atFirstToplevelNode
then i2d <$> treeViewGetHeaderHeight treeView
else return 0
adjustmentSetValue vAdjust (candidateY adjustValue)
else
when (candidateY + candidateH > currentValue + pageSize) $
adjustmentSetValue vAdjust (candidateY + candidateH pageSize)
anythingViewGetNextCandidateView :: AnythingView -> IO (Maybe (Int, AnythingCandidateView))
anythingViewGetNextCandidateView view = do
currentIndex <- readTVarIO $ avCurrentCandidateIndex view
candidateMap <- readTVarIO $ avCandidateTab view
let (_, matchList) = splitAt currentIndex (M.toList candidateMap)
return $
case matchList of
[] -> Nothing
[_] -> Nothing
_ ->
let (_, list) = partition (\ (_, ((_, num), _)) -> num == 0) (tail matchList)
in case list of
[] -> Nothing
_ ->
let (index, (_, view)) = head list
in Just (index, view)
anythingViewGetPrevCandidateView :: AnythingView -> IO (Maybe (Int, AnythingCandidateView))
anythingViewGetPrevCandidateView view = do
currentIndex <- readTVarIO $ avCurrentCandidateIndex view
candidateMap <- readTVarIO $ avCandidateTab view
let (matchList, _) = splitAt currentIndex (M.toList candidateMap)
return $
case matchList of
[] -> Nothing
_ -> let (_, list) = partition (\ (_, ((_, num), _)) -> num == 0) (reverse matchList)
in case list of
[] -> Nothing
_ -> let (index, (_, view)) = head list
in Just (index, view)
anythingViewGetCompletion :: AnythingInput -> [String] -> AnythingCompletionRule -> AnythingCompletion
anythingViewGetCompletion input candidates rule = completion
where prefix = rule input
common = foldl1_ intersectFront candidates
completion = if prefix `isPrefixOf` common
then drop (length prefix) common
else ""
anythingViewSetCommands :: AnythingView -> [String] -> IO ()
anythingViewSetCommands view commands = do
let (AnythingCommandView treeView store) = avCommandTab view
listStoreClear store
forM_ commands (listStoreAppend store)
treeViewFocusFirstToplevelNode treeView
anythingViewFocusNextCommand :: AnythingView -> IO ()
anythingViewFocusNextCommand view = do
let (AnythingCommandView treeView _) = avCommandTab view
treeViewFocusNextToplevelNode treeView
anythingViewFocusPrevCommand :: AnythingView -> IO ()
anythingViewFocusPrevCommand view = do
let (AnythingCommandView treeView _) = avCommandTab view
treeViewFocusPrevToplevelNode treeView
anythingViewShowCandidateTab :: AnythingView -> IO ()
anythingViewShowCandidateTab view =
notebookSetCurrentPage (avNotebook view) anythingCandidateTabIndex
anythingViewShowCommandTab :: AnythingView -> IO ()
anythingViewShowCommandTab view =
notebookSetCurrentPage (avNotebook view) anythingCommandTabIndex
anythingViewIsFocusCandidateTab :: AnythingView -> IO Bool
anythingViewIsFocusCandidateTab view =
(anythingCandidateTabIndex ==) <$> notebookGetCurrentPage (avNotebook view)
anythingViewIsFocusCommandTab :: AnythingView -> IO Bool
anythingViewIsFocusCommandTab view =
(anythingCommandTabIndex ==) <$> notebookGetCurrentPage (avNotebook view)
anythingViewFindCandidateView :: AnythingView -> Int -> IO (Maybe AnythingCandidateView)
anythingViewFindCandidateView view index = do
candidateTab <- readTVarIO $ avCandidateTab view
findMinMatch candidateTab (\ i (_, _) -> i == index)
?>=> \ (_, (_, view)) -> return (Just view)
anythingViewFindCurrentAnythingName :: AnythingView -> IO (Maybe AnythingName)
anythingViewFindCurrentAnythingName view = do
currentIndex <- readTVarIO $ avCurrentCandidateIndex view
candidateTab <- readTVarIO $ avCandidateTab view
findMinMatch candidateTab (\ i (_, _) -> i == currentIndex)
?>=> \ (_, ((name, _), _)) -> return (Just name)
anythingViewFindCurrentCandidateView :: AnythingView -> IO (Maybe AnythingCandidateView)
anythingViewFindCurrentCandidateView view = do
currentIndex <- readTVarIO $ avCurrentCandidateIndex view
anythingViewFindCandidateView view currentIndex
anythingViewGetSelectedCandidate :: AnythingView -> IO (Maybe AnythingCandidateWrap)
anythingViewGetSelectedCandidate view =
anythingViewFindCurrentCandidateView view
>?>=> \ AnythingCandidateView {acavTreeView = treeView
,acavListStore = listStore} ->
treeViewGetSelection treeView
>>= \x -> treeSelectionGetSelected x
>?>=> (\x -> Just <$> listStoreGetValue listStore (listStoreIterToIndex x))
anythingViewFocusCandidate :: TreeViewClass view => AnythingView -> view -> (view -> IO ()) -> Int -> IO ()
anythingViewFocusCandidate view treeView treeFocusAction index = do
treeFocusAction treeView
writeTVarIO (avCurrentCandidateIndex view) index
anythingViewExpandSelectedCandidate :: (Int, (TVar AnythingSearchCache, (AnythingViewInput, (AnythingView, Client)))) -> IO ()
anythingViewExpandSelectedCandidate (keyPressId, (cache, (input, (view, client)))) = do
anythingViewShowCandidateTab view
anythingViewGetSelectedCandidate view
>?>= \ candidateWrap ->
case candidateWrap of
AnythingCandidateWrap a -> do
expandName <- candidateExpandName a (aviUnselectText input)
anythingViewCompletion client cache view expandName keyPressId
anythingViewToggleTab :: (AnythingView, AnythingViewInput) -> IO ()
anythingViewToggleTab (view, input) = do
isFocusCommandTab <- anythingViewIsFocusCommandTab view
if isFocusCommandTab
then anythingViewShowCandidateTab view
else
anythingViewFindCurrentAnythingName view
>?>= \name ->
M.lookup name anythingList ?>= \(Anything {anythingCommandFun = commandFun}) ->
anythingViewGetSelectedCandidate view
>?>= \candidateWrap -> do
iType <- readTVarIO $ avInteractiveType view
commandList <- commandFun (aviUnselectText input) candidateWrap iType
let commands = map fst commandList
anythingViewSetCommands view commands
anythingViewShowCommandTab view
anythingViewRunCommand :: Bool -> (AnythingView, (Client, AnythingViewInput)) -> IO ()
anythingViewRunCommand runSelected (view, (client, input)) =
anythingViewFindCurrentAnythingName view
>?>= \name ->
M.lookup name anythingList
?>= \(Anything {anythingCommandFun = commandFun}) ->
anythingViewGetSelectedCandidate view
>?>= \candidateWrap ->
(if runSelected
then treeViewGetSelectedPath (acovTreeView $ avCommandTab view)
else return $ Just [0])
>?>= \commandPath -> do
iType <- readTVarIO $ avInteractiveType view
commandList <- commandFun (aviUnselectText input) candidateWrap iType
commandList ?! head commandPath ?>= \ (_, action) -> do
action client
when (iType == GlobalSearch) $
mkDaemonSignal client LocalInteractivebarExit LocalInteractivebarExitArgs
anythingViewRunFirstCommand :: (AnythingView, (Client, AnythingViewInput)) -> IO ()
anythingViewRunFirstCommand =
anythingViewRunCommand False
anythingViewRunSelectedCommand :: (AnythingView, (Client, AnythingViewInput)) -> IO ()
anythingViewRunSelectedCommand =
anythingViewRunCommand True
anythingViewGetMatches :: AnythingName
-> AnythingInput
-> Client
-> AnythingSearch
-> AnythingFilterRule
-> IO [AnythingCandidateWrap]
anythingViewGetMatches name path client (AnythingSearch searchFun) filterRule = do
candidates <-
Exc.catch
(map AnythingCandidateWrap <$> searchFun path client)
(\ (_ :: Exc.IOException) -> do
putStrLn $ "anythingViewGetMatches: Catch exception when search candidate for `"
++ name
++ "` please report this bug to author!"
return [])
return $ filter (\ (AnythingCandidateWrap x) -> filterRule path (candidateFilterName x)) candidates
anythingViewCompletion :: Client -> TVar AnythingSearchCache -> AnythingView -> FilePath -> AnythingKeyPressId -> IO ()
anythingViewCompletion client anythingSearchCache view path keyPressId = do
anythingViewShowCandidateTab view
boxHeight <- anythingViewGetBoxHeight view
mkDaemonSignal client AnythingViewOutput (AnythingViewOutputArgs path "" boxHeight keyPressId)
cList <- liftM M.toList (readTVarIO (avCandidateTab view))
forM_ cList $ \(_, ((name, _), candidateView)) ->
M.lookup name anythingList ?>= \(Anything {anythingSearch = searchFun
,anythingCompletionRule = completionRule
,anythingFilterRule = filterRule
,anythingInputDepend = inputDepend
,anythingCalculateDelay = delay
}) -> do
searchCache <- readTVarIO anythingSearchCache
let
getMatches = do
titleWidgetStart (acavTitleWidget candidateView)
anythingViewGetMatches name path client searchFun filterRule
setCandidates name cacheTVar candidates = do
titleWidgetStop (acavTitleWidget candidateView)
anythingViewSetCandidates view client name candidates path completionRule keyPressId
modifyTVarIO cacheTVar (M.delete name)
startNewSearch name cacheTVar = do
handlerId <- timeoutAdd
(do
state <- forkGuiIO getMatches (setCandidates name cacheTVar)
modifyTVarIO cacheTVar (M.insert name (Left state))
return False)
delay
modifyTVarIO cacheTVar (M.insert name (Right handlerId))
case M.lookup name searchCache of
Nothing ->
startNewSearch name anythingSearchCache
Just (Right delayHandlerId) -> do
timeoutRemove delayHandlerId
startNewSearch name anythingSearchCache
Just (Left (signal, calcThreadId, guiThreadId)) -> do
killThread guiThreadId
tStatus <- threadStatus calcThreadId
if not inputDepend && tStatus == ThreadRunning
then do
newGuiThreadId <- onGuiSignal signal (setCandidates name anythingSearchCache)
modifyTVarIO anythingSearchCache (M.insert name (Left (signal, calcThreadId, newGuiThreadId)))
else do
killThread calcThreadId
startNewSearch name anythingSearchCache
anythingViewGetBoxHeight :: AnythingView -> IO (Maybe Int)
anythingViewGetBoxHeight view =
ifM (anythingViewIsFocusCandidateTab view)
(ifM (anythingViewHasCandidates view)
(do
candidateMap <- readTVarIO $ avCandidateTab view
find (\ (_, ((_, count), _)) -> count > 0) (reverse $ M.toList candidateMap)
?>=> \ (_, (_, AnythingCandidateView {acavTreeView = treeView})) -> do
candidateBoxHeight <- rectangleH <$> widgetGetAllocation (avCandidateBox view)
visibleHeight <- rectangleH <$> treeViewGetVisibleRect treeView
candidatesHeight <- anythingViewGetCandidatesHeight treeView
return $ Just $ candidateBoxHeight visibleHeight + candidatesHeight)
(return Nothing))
(Just <$> anythingViewGetCandidatesHeight (acovTreeView $ avCommandTab view))
anythingViewHasCandidates :: AnythingView -> IO Bool
anythingViewHasCandidates =
containerHasChildren . avCandidateBox
anythingViewGetCandidatesHeight :: TreeViewClass treeView => treeView -> IO Int
anythingViewGetCandidatesHeight treeView = do
candidateNumber <- treeViewGetToplevelNodeCount treeView
cellHeight <- anythingViewGetCellHeight treeView
headerHeight <- treeViewGetHeaderHeight treeView
return $ headerHeight + (if candidateNumber < anythingCandidateViewLimit
then candidateNumber
else anythingCandidateViewLimit) * cellHeight
anythingViewGetCellHeight :: TreeViewClass treeView => treeView -> IO Int
anythingViewGetCellHeight treeView = do
cellHeight <- treeViewGetDefaultCellHeight treeView
return $
case cellHeight of
Just height -> (if height > 1
then height
else anythingViewDefaultCellHeight)
Nothing -> anythingViewDefaultCellHeight