manatee-imageviewer 0.0.8 → 0.1.0
raw patch · 8 files changed
+238/−82 lines, 8 filesdep +binarydep +derivedep −gtk-serialized-eventdep ~manatee-coresetup-changedbinary-added
Dependencies added: binary, derive
Dependencies removed: gtk-serialized-event
Dependency ranges changed: manatee-core
Files
- Main.hs +1/−1
- Manatee/Extension/ImageViewer.hs +1/−1
- Manatee/Extension/ImageViewer/ImageBuffer.hs +42/−1
- Manatee/Extension/ImageViewer/ImageView.hs +173/−70
- Manatee/Extension/ImageViewer/PageMode.hs +1/−1
- Setup.hs +11/−2
- data/welcome/snapshot.png binary
- manatee-imageviewer.cabal +9/−6
Main.hs view
@@ -1,7 +1,7 @@ -- Author: Andy Stewart <lazycat.manatee@gmail.com> -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com> -- --- Copyright (C) 2010 Andy Stewart, all rights reserved.+-- 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
Manatee/Extension/ImageViewer.hs view
@@ -1,7 +1,7 @@ -- Author: Andy Stewart <lazycat.manatee@gmail.com> -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com> -- --- Copyright (C) 2010 Andy Stewart, all rights reserved.+-- 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
Manatee/Extension/ImageViewer/ImageBuffer.hs view
@@ -1,7 +1,7 @@ -- Author: Andy Stewart <lazycat.manatee@gmail.com> -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com> -- --- Copyright (C) 2010 Andy Stewart, all rights reserved.+-- 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@@ -18,15 +18,19 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TemplateHaskell #-} module Manatee.Extension.ImageViewer.ImageBuffer where import Control.Applicative import Control.Concurrent import Control.Concurrent.STM import DBus.Client hiding (Signal)+import Data.Binary import Data.ByteString.UTF8+import Data.DeriveTH import Data.List import Data.Typeable+import Manatee.Core.Config import Manatee.Core.DBus import Manatee.Core.Types import Manatee.Extension.ImageViewer.PageMode@@ -45,9 +49,29 @@ ,imageBufferFiles :: TVar [FilePath] ,imageBufferBroadcastChannel :: TChan String ,imageBufferSlideShowHanlderId :: TVar (Maybe HandlerId)+ ,imageBufferState :: TVar ImageState } deriving Typeable +data ImageState =+ ImageState {imageStateDirection :: ImageDirection+ ,imageStateZoom :: Maybe Double+ ,imageStateScrolledPosition :: (Double, Double)}++data ImageDirection = DirectionUp+ | DirectionDown+ | DirectionLeft+ | DirectionRight++data RotateAction = RotateCounterclockwise+ | RotateClockwise+ | RotateMirror++-- | Init state.+imageInitState :: ImageState+imageInitState =+ ImageState DirectionUp Nothing (0, 0)+ -- | New image buffer. imageBufferNew :: String -> [String] -> Client -> PageId -> CustomizeWrap -> IO ImageBuffer imageBufferNew path _ client pageId _ = do@@ -59,6 +83,7 @@ <*> newTVarIO [] <*> (newTChanIO :: IO (TChan String)) <*> newTVarIO Nothing+ <*> newTVarIO imageInitState -- Scan image files under current directory. forkIO $ imageBufferScanFiles buffer@@ -122,3 +147,19 @@ -- Scan... scan enum +-- | Write state.+imageBufferWriteState :: ImageBuffer -> FilePath -> IO ()+imageBufferWriteState buffer path = do+ state <- readTVarIO $ imageBufferState buffer+ writeConfigPath path state++-- | Read state.+imageBufferReadState :: ImageBuffer -> FilePath -> IO () +imageBufferReadState buffer path = do+ state <- readConfigPath path imageInitState+ writeTVarIO (imageBufferState buffer) state+ +$(derive makeBinary ''ImageDirection)+$(derive makeBinary ''RotateAction)+$(derive makeBinary ''ImageState)+
Manatee/Extension/ImageViewer/ImageView.hs view
@@ -1,7 +1,7 @@ -- Author: Andy Stewart <lazycat.manatee@gmail.com> -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com> -- --- Copyright (C) 2010 Andy Stewart, all rights reserved.+-- 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@@ -23,25 +23,25 @@ import Control.Applicative import Control.Concurrent.STM import Control.Monad+import Data.ByteString.UTF8 hiding (length) import Data.List import Data.Map (Map)-import Data.ByteString.UTF8 hiding (length) import Data.Text.Lazy (Text) import Data.Typeable import Graphics.UI.Gtk hiding (Statusbar, statusbarNew, get)-import Graphics.UI.Gtk.Gdk.SerializedEvent+import Manatee.Core.Config import Manatee.Core.PageFrame import Manatee.Core.PageView import Manatee.Core.Types import Manatee.Extension.ImageViewer.ImageBuffer import Manatee.Toolkit.GConf.GConf+import Manatee.Toolkit.General.List import Manatee.Toolkit.General.Maybe import Manatee.Toolkit.General.Misc-import Manatee.Toolkit.General.List import Manatee.Toolkit.General.STM-import Manatee.Toolkit.Gtk.Concurrent-import Manatee.Toolkit.Gtk.Gtk import Manatee.Toolkit.Gio.Gio+import Manatee.Toolkit.Gtk.Concurrent+import Manatee.Toolkit.Gtk.ScrolledWindow import Paths_manatee_imageviewer import System.FilePath @@ -53,6 +53,7 @@ ,imageViewFrame :: PageFrame ,imageViewView :: I.ImageView ,imageViewBuffer :: ImageBuffer+ ,imageViewDirection :: TVar ImageDirection ,imageViewBroadcastChannel:: ViewChannel String} deriving Typeable @@ -65,12 +66,17 @@ pageBufferPackageName _ = fmap takeFileName getDataDir instance PageView ImageView where- pageViewBuffer = PageBufferWrap . imageViewBuffer- pageViewPlugId = imageViewPlugId- pageViewBox = pageFrameBox . imageViewFrame- pageViewScrolledWindow = imageViewScrolledWindow- pageViewFocus = widgetGrabFocus . imageViewView- pageViewHandleKeyAction = imageViewHandleKeyAction+ pageViewBuffer = PageBufferWrap . imageViewBuffer+ pageViewPlugId = imageViewPlugId+ pageViewFrame = imageViewFrame+ pageViewLocalKeymap _ = imageViewLocalKeymap+ pageViewLocalCommandMap _ = imageViewLocalCommandMap+ pageViewFocus = widgetGrabFocus . imageViewView+ pageViewPropagateWidget = castToWidget . imageViewView+ pageViewSaveState view = imageViewSaveState view Nothing+ pageViewRestoreState view = imageViewRestoreState view Nothing+ pageViewWriteState view path = imageViewSaveState view (Just path)+ pageViewReadState view path = imageViewRestoreState view (Just path) -- | The intervals of slide show (ms). imageViewSlideShowInterval :: Int@@ -89,31 +95,36 @@ view <- I.imageViewNew pageFrameAddChild pFrame view + -- Init direction.+ direction <- newTVarIO DirectionUp+ -- Duplicate broadcast channel. channel <- createViewChannel (imageBufferBroadcastChannel buffer) view -- Build image view.- let imageView = ImageView pId pFrame view buffer channel+ let imageView = ImageView pId pFrame view buffer direction channel -- Listen broadcast channel. imageViewListenChannel imageView - -- Draw.- imageViewDraw imageView- -- Update zoom status. view `on` I.zoomChanged $ imageViewUpdateZoomStatus imageView return imageView -- | Draw image view.-imageViewDraw :: ImageView -> IO ()-imageViewDraw view = do- -- TODO: Need find a way free old pixbuf in GtkImageView after use new pixbuf.- -- Otherwise cause memory leak. +imageViewDraw :: ImageView -> ImageDirection -> IO ()+imageViewDraw view direction = do path <- readTVarIO $ imageBufferPath $ imageViewBuffer view- pixbuf <- pixbufNewFromFile (filepathGetDisplayName (fromString path))- I.imageViewSetPixbuf (imageViewView view) (Just pixbuf) True+ oldPixbuf <- pixbufNewFromFile (filepathGetDisplayName (fromString path))+ newPixbuf <- + case direction of+ DirectionUp -> return oldPixbuf+ DirectionRight -> pixbufRotateSimple oldPixbuf PixbufRotateClockwise+ DirectionLeft -> pixbufRotateSimple oldPixbuf PixbufRotateCounterclockwise+ DirectionDown -> pixbufRotateSimple oldPixbuf PixbufRotateUpsidedown+ writeTVarIO (imageViewDirection view) direction+ I.imageViewSetPixbuf (imageViewView view) (Just newPixbuf) True -- | Browse. imageViewBrowse :: ImageView -> FilePath -> IO ()@@ -128,14 +139,7 @@ imageViewListenChannel :: ImageView -> IO () imageViewListenChannel view = listenViewChannel (imageViewBroadcastChannel view) $ \_ ->- imageViewDraw view---- | Handle key action.-imageViewHandleKeyAction :: ImageView -> Text -> SerializedEvent -> IO () -imageViewHandleKeyAction view keystoke sEvent = - case M.lookup keystoke imageViewKeymap of- Just action -> action view- Nothing -> widgetPropagateEvent (imageViewView view) sEvent+ imageViewDraw view DirectionUp -- | Zoom out image. imageViewZoomOut :: ImageView -> IO ()@@ -178,13 +182,45 @@ files <- readTVarIO $ imageBufferFiles $ imageViewBuffer view getLast files ?>= \ file -> imageViewBrowse view file +-- | Update direction.+imageViewUpdateDirection :: ImageView -> RotateAction -> IO () +imageViewUpdateDirection ImageView {imageViewDirection = directionTVar}+ action = do+ -- Get old direction.+ direction <- readTVarIO directionTVar+ + -- Get new direction.+ let newDirection = + case action of+ RotateCounterclockwise ->+ case direction of+ DirectionUp -> DirectionLeft+ DirectionRight -> DirectionUp+ DirectionDown -> DirectionRight+ DirectionLeft -> DirectionDown+ RotateClockwise ->+ case direction of+ DirectionUp -> DirectionRight+ DirectionRight -> DirectionDown+ DirectionDown -> DirectionLeft+ DirectionLeft -> DirectionUp+ RotateMirror ->+ case direction of+ DirectionUp -> DirectionDown+ DirectionRight -> DirectionLeft+ DirectionDown -> DirectionUp+ DirectionLeft -> DirectionRight++ -- Update direction.+ writeTVarIO directionTVar newDirection+ -- | Rotate clockwise imageViewRotateClockwise :: ImageView -> IO () imageViewRotateClockwise view = do oldPixbuf <- I.imageViewGetPixbuf $ imageViewView view newPixbuf <- pixbufRotateSimple oldPixbuf PixbufRotateClockwise I.imageViewSetPixbuf (imageViewView view) (Just newPixbuf) True-+ imageViewUpdateDirection view RotateClockwise -- | Rotate counterclockwise. imageViewRotateCounterclockwise :: ImageView -> IO ()@@ -192,6 +228,7 @@ oldPixbuf <- I.imageViewGetPixbuf $ imageViewView view newPixbuf <- pixbufRotateSimple oldPixbuf PixbufRotateCounterclockwise I.imageViewSetPixbuf (imageViewView view) (Just newPixbuf) True+ imageViewUpdateDirection view RotateCounterclockwise -- | Rotate mirror. imageViewRotateMirror :: ImageView -> IO ()@@ -199,12 +236,13 @@ oldPixbuf <- I.imageViewGetPixbuf $ imageViewView view newPixbuf <- pixbufRotateSimple oldPixbuf PixbufRotateUpsidedown I.imageViewSetPixbuf (imageViewView view) (Just newPixbuf) True+ imageViewUpdateDirection view RotateMirror -- | Update zoom status. imageViewUpdateZoomStatus :: ImageView -> IO () imageViewUpdateZoomStatus view = do zoom <- liftM (\x -> floor $ formatFloatN x 2 * 100) $ I.imageViewGetZoom $ imageViewView view- pageFrameUpdateStatusbar (imageViewFrame view) "Zoom" (" Zoom (" ++ show zoom ++ "%)")+ pageViewUpdateStatusbar view "Zoom" (" Zoom (" ++ show zoom ++ "%)") -- | Find next image file under current directory. imageViewGetNextFile :: FilePath -> [FilePath] -> Maybe FilePath@@ -242,12 +280,12 @@ case sId of -- Stop slide show. Just id -> do- pageFrameUpdateStatusbar (imageViewFrame view) "SlideShow" " SlideShow (off)"+ pageViewUpdateStatusbar view "SlideShow" " SlideShow (off)" timeoutRemove id writeTVarIO slideShowId Nothing -- Start slide show. Nothing -> do- pageFrameUpdateStatusbar (imageViewFrame view) "SlideShow" " SlideShow (on)"+ pageViewUpdateStatusbar view "SlideShow" " SlideShow (on)" handlerId <- timeoutAdd (imageViewBrowseNext view >> return True) imageViewSlideShowInterval writeTVarIO slideShowId (Just handlerId) @@ -259,44 +297,109 @@ path <- readTVarIO bufferPath setDesktopBackground path 100 Zoom +-- | Keymap.+imageViewLocalKeymap :: Map Text Text+imageViewLocalKeymap = + M.fromList [("j", "Scroll step up")+ ,("k", "Scroll step down")+ ,("Down", "Scroll step up")+ ,("Up", "Scroll step down")+ ,("h", "Scroll step right")+ ,("l", "Scroll step left")+ ,("Right", "Scroll step right")+ ,("Left", "Scroll step left")+ ,(" ", "Scroll page up")+ ,("b", "Scroll page down")+ ,("PageDown", "Scroll page up")+ ,("PageUp", "Scroll page down")+ ,("J", "Scroll to bottom")+ ,("K", "Scroll to top")+ ,("End", "Scroll to bottom")+ ,("Home", "Scroll to top")+ ,(",", "Zoom out")+ ,(".", "Zoom in")+ ,("-", "Zoom out")+ ,("=", "Zoom in")+ ,("m", "Fit size")+ ,("n", "Browse next")+ ,("Return", "Browse previous")+ ,("p", "Browse previous")+ ,("N", "Browse last")+ ,("P", "Browse first")+ ,("<", "Rotate counterclockwise")+ ,(">", "Rotate clockwise")+ ,("/", "Rotate mirror")+ ,("s", "Slide show")+ ,("B", "Set as background")+ ]++-- | Keymap.+imageViewLocalCommandMap :: Map Text (ImageView -> IO ())+imageViewLocalCommandMap = + M.fromList [("Scroll step up", pageViewScrollStepUp)+ ,("Scroll step down", pageViewScrollStepDown)+ ,("Scroll step right", pageViewScrollStepRight)+ ,("Scroll step left", pageViewScrollStepLeft)+ ,("Scroll page up", pageViewScrollPageUp)+ ,("Scroll page down", pageViewScrollPageDown)+ ,("Scroll to bottom", pageViewScrollToBottom)+ ,("Scroll to top", pageViewScrollToTop)+ ,("Zoom out", imageViewZoomOut)+ ,("Zoom in", imageViewZoomIn)+ ,("Fit size", imageViewFit)+ ,("Browse next", imageViewBrowseNext)+ ,("Browse previous", imageViewBrowsePrev)+ ,("Browse last", imageViewBrowseLast)+ ,("Browse first", imageViewBrowseFirst)+ ,("Rotate counterclockwise", imageViewRotateCounterclockwise)+ ,("Rotate clockwise", imageViewRotateClockwise)+ ,("Rotate mirror", imageViewRotateMirror)+ ,("Slide show", imageViewSlideShow)+ ,("Set as background", imageViewSetAsBackground)+ ]+ -- | Scrolled window.-imageViewScrolledWindow :: ImageView -> ScrolledWindow +imageViewScrolledWindow :: ImageView -> ScrolledWindow imageViewScrolledWindow = pageFrameScrolledWindow . imageViewFrame --- | Keymap.-imageViewKeymap :: Map Text (ImageView -> IO ())-imageViewKeymap = - M.fromList [("j", pageViewScrollStepUp)- ,("k", pageViewScrollStepDown)- ,("Down", pageViewScrollStepUp)- ,("Up", pageViewScrollStepDown)- ,("h", pageViewScrollStepRight)- ,("l", pageViewScrollStepLeft)- ,("Right", pageViewScrollStepRight)- ,("Left", pageViewScrollStepLeft)- ,(" ", pageViewScrollPageUp)- ,("b", pageViewScrollPageDown)- ,("PageDown", pageViewScrollPageUp)- ,("PageUp", pageViewScrollPageDown)- ,("J", pageViewScrollToBottom)- ,("K", pageViewScrollToTop)- ,("End", pageViewScrollToBottom)- ,("Home", pageViewScrollToTop)- ,(",", imageViewZoomOut)- ,(".", imageViewZoomIn)- ,("-", imageViewZoomOut)- ,("=", imageViewZoomIn)- ,("m", imageViewFit)- ,("n", imageViewBrowseNext)- ,("Return", imageViewBrowseNext)- ,("p", imageViewBrowsePrev)- ,("N", imageViewBrowseLast)- ,("P", imageViewBrowseFirst)- ,("<", imageViewRotateCounterclockwise)- ,(">", imageViewRotateClockwise)- ,("/", imageViewRotateMirror)- ,("s", imageViewSlideShow)- ,("B", imageViewSetAsBackground)- ]+-- | Save state.+imageViewSaveState :: ImageView -> Maybe FilePath -> IO ()+imageViewSaveState view@(ImageView {imageViewBuffer = buffer+ ,imageViewView = imageView+ ,imageViewDirection = directionTVar}) + statePath = do+ -- Get direction.+ direction <- readTVarIO directionTVar + -- Get zoom level.+ zoom <- I.imageViewGetZoom imageView++ -- Get scroll position.+ scrolledWindowPosition <- scrolledWindowGetValue (imageViewScrolledWindow view)++ -- Save state.+ let state = ImageState direction (Just zoom) scrolledWindowPosition+ case statePath of+ Nothing -> writeTVarIO (imageBufferState buffer) state+ Just path -> writeConfigPath path state++-- | Restore state.+imageViewRestoreState :: ImageView -> Maybe FilePath -> IO ()+imageViewRestoreState view@(ImageView {imageViewBuffer = buffer+ ,imageViewView = imageView})+ statePath = do+ bufferState <- readTVarIO (imageBufferState buffer)+ (ImageState direction zoom scrolledWindowPosition) <- + case statePath of+ Just path -> readConfigPath path bufferState+ Nothing -> return bufferState++ -- Restore direction.+ imageViewDraw view direction++ -- Restore zoom level.+ zoom ?>= (I.imageViewSetZoom imageView)++ -- Restore scroll position.+ scrolledWindowSetValue (imageViewScrolledWindow view) scrolledWindowPosition
Manatee/Extension/ImageViewer/PageMode.hs view
@@ -1,7 +1,7 @@ -- Author: Andy Stewart <lazycat.manatee@gmail.com> -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com> -- --- Copyright (C) 2010 Andy Stewart, all rights reserved.+-- 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
Setup.hs view
@@ -1,7 +1,7 @@ -- Author: Andy Stewart <lazycat.manatee@gmail.com> -- Maintainer: Andy Stewart <lazycat.manatee@gmail.com> -- --- Copyright (C) 2010 Andy Stewart, all rights reserved.+-- 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@@ -19,6 +19,7 @@ import Distribution.Simple import Manatee.Core.Config import Manatee.Core.Types+import Manatee.Toolkit.Cabal.Utils import Manatee.Toolkit.General.List import Manatee.Toolkit.General.Map import Manatee.Extension.ImageViewer.PageMode@@ -28,7 +29,7 @@ main = defaultMainWithHooks simpleUserHooks { -- Update PageTypeRule after install successful.- postInst = \ _ _ _ _ -> do+ postInst = \ _ _ pack_des lbi -> do (PageTypeRule rule) <- readConfig pageTypeRulePath (PageTypeRule M.empty) writeConfig pageTypeRulePath (PageTypeRule (M.insert "PageImage" "manatee-imageviewer" rule)) -- Update FileOpenRule.@@ -45,4 +46,12 @@ (PageModeRule modeRule) <- readConfig pageModeRulePath (PageModeRule M.empty) writeConfig pageModeRulePath (PageModeRule (M.insert "PageImage" (Left $ pageModeName imageMode) modeRule))+ -- Update Application info.+ let snapshotPath = getDataFilePath pack_des lbi "data/welcome/snapshot.png"+ (WelcomeApplication apps) <- readConfig welcomeApplicationPath (WelcomeApplication M.empty)+ writeConfig welcomeApplicationPath (WelcomeApplication + (M.insert + ("Image Viewer", snapshotPath)+ ("PageImage", snapshotPath, [])+ apps)) }
+ data/welcome/snapshot.png view
binary file changed (absent → 1394575 bytes)
manatee-imageviewer.cabal view
@@ -1,13 +1,13 @@ name: manatee-imageviewer-version: 0.0.8+version: 0.1.0 Cabal-Version: >= 1.6 license: GPL-3 license-file: LICENSE-copyright: (c) 2009 ~ 2010 Andy Stewart+copyright: (c) 2010 ~ 2011 Andy Stewart synopsis: Image viewer extension for Manatee. description: manatee-imageviewer is image viewer extension for Manatee (Haskell/Gtk+ Integrated Live Environment) .- Video at (Select 720p HD) at : <http://www.youtube.com/watch?v=weS6zys3U8k> <http://www.youtube.com/watch?v=A3DgKDVkyeM> <http://v.youku.com/v_show/id_XMjI2MDMzODI4.html>+ Video (Select 720p HD) at : <http://www.youtube.com/watch?v=weS6zys3U8k> <http://www.youtube.com/watch?v=A3DgKDVkyeM> <http://v.youku.com/v_show/id_XMjI2MDMzODI4.html> . Screenshots at : <http://goo.gl/MkVw> .@@ -22,16 +22,19 @@ stability: provisional category: Manatee, Image Viewer, Image -tested-with: GHC==6.12.3+tested-with: GHC==7.0.2 build-type: Custom +data-dir: ""+data-files: data/welcome/snapshot.png+ Source-Repository head type: darcs location: http://patch-tag.com/r/AndyStewart/manatee-imageviewer Library- build-depends: base >= 4 && < 5, manatee-core >= 0.0.8, dbus-client >= 0.3 && < 0.4, stm >= 2.1.2.0,- containers >= 0.3.0.0, gtk-serialized-event >= 0.12.0, gtk >= 0.12.0, glib >= 0.12.0,+ build-depends: base >= 4 && < 5, manatee-core >= 0.1.0, dbus-client >= 0.3 && < 0.4, stm >= 2.1.2.0,+ containers >= 0.3.0.0, gtk >= 0.12.0, glib >= 0.12.0, derive, binary, gio >= 0.12.0, gtkimageview >= 0.12.0, text >= 0.7.1.0, regex-tdfa >= 1.1.2, filepath >= 1.1.0.3, utf8-string exposed-modules: