leksah-0.1: src/IDE/ReplacePane.hs
{-# OPTIONS_GHC -fglasgow-exts #-}
-----------------------------------------------------------------------------
--
-- Module : IDE.ReplacePane
-- Copyright : (c) Juergen Nicklisch-Franken (aka Jutaro)
-- License : GNU-GPL
--
-- Maintainer : Juergen Nicklisch-Franken <jnf at arcor.de>
-- Stability : experimental
-- Portability : portable
--
-- | The pane of ide for replacing text in a text buffer
--
-------------------------------------------------------------------------------
module IDE.ReplacePane (
ReplaceAction(..)
) where
import Graphics.UI.Gtk hiding (get)
import Data.Maybe
import Control.Monad.Reader
import Data.List
import Data.Char(toUpper)
import IDE.Core.State
import IDE.Framework.ViewFrame
import IDE.Framework.MakeEditor
import IDE.SourceEditor
import IDE.Framework.Parameters
import IDE.Framework.SimpleEditors
import IDE.Framework.EditorBasics
import IDE.FindPane
-------------------------------------------------------------------------------
--
-- * Interface
--
--
-- | The Replace Pane
--
class ReplaceAction alpha where
doReplace :: alpha
instance ReplaceAction IDEAction where
doReplace = doReplace'
instance IDEObject IDEReplace
instance CastablePane IDEReplace where
casting _ = ReplaceCasting
downCast _ (PaneC a) = case casting a of
ReplaceCasting -> Just a
_ -> Nothing
instance Recoverable ReplaceState where
toPaneState a = ReplaceSt a
instance Pane IDEReplace
where
primPaneName _ = "Replace"
getAddedIndex _ = 0
getTopWidget = castToWidget . replaceBox
paneId b = "*Replace"
makeActive p = throwIDE "don't activate replace bar"
close pane = do
(panePath,_) <- guiPropertiesFromName (paneName pane)
nb <- getNotebook panePath
mbI <- lift $notebookPageNum nb (getTopWidget pane)
case mbI of
Nothing -> lift $ do
sysMessage Normal "notebook page not found: unexpected"
return ()
Just i -> do
lift $notebookRemovePage nb i
removePaneAdmin pane
instance RecoverablePane IDEReplace ReplaceState where
saveState p = do
mbFind <- getPane ReplaceCasting
case mbFind of
Nothing -> return Nothing
Just p -> return Nothing
--lift $ do
--return (Just (StateC ReplaceState))
recoverState pp st = do
nb <- getNotebook pp
initReplace pp nb st
-------------------------------------------------------------------------------
--
-- * Implementation
--
emptyReplaceState = ReplaceState "" "" False False False
doReplace' :: IDEAction
doReplace' = do
replace <- getReplace
lift $ bringPaneToFront replace
lift $ widgetGrabFocus (replaceBox replace)
getReplace :: IDEM IDEReplace
getReplace = do
mbReplace <- getPane ReplaceCasting
case mbReplace of
Nothing -> do
prefs <- readIDE prefs
layout <- readIDE layout
let pp = getStandardPanePath (controlPanePath prefs) layout
nb <- getNotebook pp
initReplace pp nb emptyReplaceState
mbReplace <- getPane ReplaceCasting
case mbReplace of
Nothing -> throwIDE "Can't init replace pane"
Just m -> return m
Just m -> return m
initReplace :: PanePath -> Notebook -> ReplaceState -> IDEAction
initReplace panePath nb replace = do
ideR <- ask
panes <- readIDE panes
paneMap <- readIDE paneMap
prefs <- readIDE prefs
currentInfo <- readIDE currentInfo
(buf,cids) <- lift $ do
vb <- vBoxNew False 0
hb <- hBoxNew False 0
bb <- hButtonBoxNew
replAll <- buttonNewWithMnemonic "Replace _all"
replB <- buttonNewWithMnemonic "_Replace"
find <- buttonNewWithMnemonic "_Find"
boxPackStart bb find PackNatural 0
boxPackStart bb replB PackNatural 0
boxPackStart bb replAll PackNatural 0
resList <- mapM (\ fd -> (fieldEditor fd) replace) replaceDescription
let (widgetsP, setInjsP, getExtsP, notifiersP) = unzip4 resList
mapM_ (\ w -> boxPackStart hb w PackNatural 0) widgetsP
let fieldNames = map (\fd -> case getParameterPrim paraName (parameters fd) of
Just s -> s
Nothing -> "Unnamed") replaceDescription
find `onClicked` do
findOrSearch editFind getExtsP fieldNames replB replAll ideR
replB `onClicked` do
findOrSearch editReplace getExtsP fieldNames replB replAll ideR
replAll `onClicked` do
findOrSearch editReplaceAll getExtsP fieldNames replB replAll ideR
boxPackStart vb hb PackNatural 0
boxPackStart vb bb PackNatural 0
let replace = IDEReplace vb
notebookInsertOrdered nb vb (paneName replace)
widgetShowAll vb
return (replace,[])
addPaneAdmin buf (BufConnections [] [] []) panePath
lift $widgetGrabFocus (replaceBox buf)
where
findOrSearch :: (Bool -> Bool -> Bool -> String -> String -> SearchHint -> IDEM Bool)
-> [ReplaceState -> Extractor ReplaceState] -> [String] -> Button ->
Button -> IDERef -> IO()
findOrSearch f getExtsP fieldNames replB replAll ideR= do
mbReplaceState <- extractAndValidate replace getExtsP fieldNames
case mbReplaceState of
Nothing -> return ()
Just rs -> do
let hint = if searchBackwards rs then Backward else Forward
found <- runReaderT (f (matchEntire rs) (matchCase rs) False
(searchFor rs) (replaceWith rs) hint) ideR
widgetSetSensitivity replB found
widgetSetSensitivity replAll found
return ()
replaceDescription :: [FieldDescription ReplaceState]
replaceDescription = [
mkField
(paraName <<<- ParaName "Search for" $ emptyParams)
searchFor
(\ b a -> a{searchFor = b})
stringEditor
, mkField
(paraName <<<- ParaName "Replace with" $ emptyParams)
replaceWith
(\ b a -> a{replaceWith = b})
stringEditor
, mkField
(paraName <<<- ParaName "Match case" $ emptyParams)
matchCase
(\ b a -> a{matchCase = b})
boolEditor
, mkField
(paraName <<<- ParaName "Entire word" $ emptyParams)
matchEntire
(\ b a -> a{matchEntire = b})
boolEditor
, mkField
(paraName <<<- ParaName "Back" $ emptyParams)
searchBackwards
(\ b a -> a{searchBackwards = b})
boolEditor]
editReplace :: Bool -> Bool -> Bool -> String -> String -> SearchHint -> IDEM Bool
editReplace entireWord caseSensitive wrapAround search replace hint =
editReplace' entireWord caseSensitive wrapAround search replace hint True
editReplace' :: Bool -> Bool -> Bool -> String -> String -> SearchHint -> Bool -> IDEM Bool
editReplace' entireWord caseSensitive wrapAround search replace hint mayRepeat =
inBufContext' False $ \_ gtkbuf currentBuffer _ -> do
startMark <- lift $textBufferGetInsert gtkbuf
iter <- lift $textBufferGetIterAtMark gtkbuf startMark
iter2 <- lift $textIterCopy iter
lift $textIterForwardChars iter2 (length search)
str1 <- lift $textIterGetText iter iter2
if compare str1 search caseSensitive
then do
lift $textBufferDelete gtkbuf iter iter2
lift $textBufferInsert gtkbuf iter replace
editFind entireWord caseSensitive wrapAround search "" hint
else do
r <- editFind entireWord caseSensitive wrapAround search "" hint
if r
then editReplace' entireWord caseSensitive wrapAround search
replace hint False
else return False
where
compare s1 s2 True = s1 == s2
compare s1 s2 False = map toUpper s1 == map toUpper s2
editReplaceAll :: Bool -> Bool -> Bool -> String -> String -> SearchHint -> IDEM Bool
editReplaceAll entireWord caseSensitive wrapAround search replace hint = do
res <- editReplace' entireWord caseSensitive wrapAround search replace hint True
if res
then editReplaceAll entireWord caseSensitive wrapAround search replace hint
else return False