manatee-core-0.1.0: Manatee/Toolkit/Widget/Tooltip.hs
-- Author: Andy Stewart <lazycat.manatee@gmail.com>
-- Maintainer: Andy Stewart <lazycat.manatee@gmail.com>
--
-- Copyright (C) 2010 ~ 2011 Andy Stewart, all rights reserved.
--
-- 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
-- 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.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
module Manatee.Toolkit.Widget.Tooltip where
import Control.Applicative
import Control.Monad.Trans
import Data.Maybe
import Graphics.UI.Gtk hiding (Tooltip)
import Manatee.Toolkit.Gtk.Gtk
data Tooltip =
Tooltip {tooltipWindow :: Window -- window for contain widget
,tooltipDependWindow :: Window -- depend window for control display
,tooltipLabel :: Label -- label to container text
,tooltipTimeout :: Int -- timeout for display (in millisecond)
,tooltipFocusInConnectId :: ConnectId Window
,tooltipFocusOutConnectId:: ConnectId Window
}
-- | Align size.
tooltipAlignSize :: Int
tooltipAlignSize = 10
-- | Default tooltip timeout.
tooltipDefaultTimeout :: Int
tooltipDefaultTimeout = 3000
-- | Default foreground color.
tooltipDefaultForegroundColor :: Color
tooltipDefaultForegroundColor = Color 0 0 0
-- | Default background color.
tooltipDefaultBackgroundColor :: Color
tooltipDefaultBackgroundColor = Color 65335 65335 0
-- | New tooltip.
tooltipNew :: WidgetClass widget
=> widget -- ^ top-level parent window
-> String -- ^ text
-> Maybe Point -- ^ point, 'Nothing' will set right-top corner of screen
-> Maybe Int -- ^ timeout
-> Maybe Color -- ^ foreground color
-> Maybe Color -- ^ background color
-> IO Tooltip
tooltipNew widget text position time fColor bColor = do
-- Get window.
win <- castToWindow <$> widgetGetToplevel widget
let timeout = case time of
Just t -> t
Nothing -> tooltipDefaultTimeout
-- Set color.
let foregroundColor = fromMaybe tooltipDefaultForegroundColor fColor
backgroundColor = fromMaybe tooltipDefaultBackgroundColor bColor
-- Create tooltip window.
window <- windowNewPopup
windowSetDecorated window False
windowSetOpacity window 0.8 -- this function need window-manager support Alpha channel in X11
widgetModifyBg window StateNormal backgroundColor
-- Create frame.
frame <- frameNew
set frame [frameShadowType := ShadowEtchedIn]
-- Create alignment.
alignment <- alignmentNew 0.5 0.5 1 1
alignmentSetPadding alignment tooltipAlignSize tooltipAlignSize tooltipAlignSize tooltipAlignSize
-- Create label.
label <- labelNew $ Just text
labelSetAttributes label [AttrForeground 0 (length text) foregroundColor
,AttrBackground 0 (length text) backgroundColor]
-- Wrap line with word bound.
labelSetLineWrap label True
labelSetLineWrapMode label WrapPartialWords
-- Show tooltip.
alignment `containerAdd` label
frame `containerAdd` alignment
window `containerAdd` frame
widgetShowAll window
-- Adjust tooltip position.
(screenWidth, screenHeight) <- widgetGetScreenSize win
(Rectangle _ _ width height) <- widgetGetAllocation window
let (tooltipX, tooltipY) =
case position of
Just (x, y) ->
let adjustX
-- Set screen right when x bigger than screen width.
| x > screenWidth
= screenWidth - width - tooltipAlignSize
-- Set left of x when tooltip width bigger than screen width.
| x + width > screenWidth
= x - width - tooltipAlignSize
| otherwise
= x
adjustY
-- Set screen bottom when y bigger than screen height.
| y > screenHeight
= screenHeight - height - tooltipAlignSize
-- Set up of y when tooltip height bigger than screen height.
| y + height > screenHeight
= y - height - tooltipAlignSize
| otherwise
= y
in (adjustX, adjustY)
Nothing -> (screenWidth - width - tooltipAlignSize, tooltipAlignSize)
-- Move window.
windowMove window tooltipX tooltipY
-- Show tooltip when parent window show.
focusInConnectId <-
win `on` focusInEvent $ tryEvent $ do
liftIO $ do
widgetShowAll window
windowMove window tooltipX tooltipY
stopEvent
-- Hide tooltip when parent window hide.
focusOutConnectId <-
win `on` focusOutEvent $ tryEvent $ do
liftIO $ widgetHideAll window
stopEvent
-- Create tooltip.
let tooltip = Tooltip window win label timeout focusInConnectId focusOutConnectId
-- Destroy tooltip when out of timeout.
timeoutAdd (tooltipExit tooltip >> return False) timeout
return tooltip
-- | Exit tooltip.
tooltipExit :: Tooltip -> IO ()
tooltipExit Tooltip {tooltipWindow = window
,tooltipFocusInConnectId = focusInConnectId
,tooltipFocusOutConnectId = focusOutConnectId
}
= do
-- Disconnect signal first.
signalDisconnect focusInConnectId
signalDisconnect focusOutConnectId
-- Destroy tooltip.
widgetDestroy window