builder' :: FilePath ->
    PackageDescriptionEd ->
    FieldDescription PackageDescriptionEd ->
    (FilePath -> IDEAction) ->
    FilePath ->
    [ModuleName] ->
    [PackageId] ->
    [FieldDescription PackageDescriptionEd] ->
    PackageDescriptionEd ->
    PanePath ->
    Notebook ->
    Window ->
    IDEM (Maybe PackagePane,Connections)
builder' packageDir packageD packageDescr afterSaveAction initialPackagePath modules packageInfos fields
    origPackageD panePath nb window  = reifyIDE $ \ ideR -> do
    vb      <-  vBoxNew False 0
    bb      <-  hButtonBoxNew
    save    <- buttonNewFromStock "gtk-save"
    widgetSetSensitive save False
    closeB  <- buttonNewFromStock "gtk-close"
    addB    <- buttonNewFromStock (__ "Add Build Info")
    removeB <- buttonNewFromStock (__ "Remove Build Info")
    label   <-  labelNew (Nothing :: Maybe Text)
    boxPackStart bb addB PackNatural 0
    boxPackStart bb removeB PackNatural 0
    boxPackEnd bb closeB PackNatural 0
    boxPackEnd bb save PackNatural 0
    (widget, setInj, getExt, notifier)  <-  buildEditor packageDescr packageD
    let packagePane = PackagePane vb notifier
    boxPackStart vb widget PackGrow 7
    boxPackStart vb label PackNatural 0
    boxPackEnd vb bb PackNatural 7

    let fieldNames = map (\fd -> case getParameterPrim paraName (parameters fd) of
                                    Just s -> s
                                    Nothing -> (__ "Unnamed")) fields
    on addB buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> sysMessage Normal (__ "Content doesn't validate")
            Just pde -> reflectIDE (do
                    closePane packagePane
                    initPackage packageDir pde {bis = bis pde ++ [bis pde !! 0]}
                        (packageDD
                            (packageInfos)
                            packageDir
                            modules
                            (length (bis pde) + 1)
                            (concatMap (buildInfoD (Just packageDir) modules)
                                [0..length (bis pde)]))
                        panePath nb modules afterSaveAction origPackageD) ideR
    on removeB buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> sysMessage Normal (__ "Content doesn't validate")
            Just pde | length (bis pde) == 1  -> sysMessage Normal (__ "Just one Build Info")
                     | otherwise -> reflectIDE (do
                        closePane packagePane
                        initPackage packageDir pde{bis = take (length (bis pde) - 1) (bis pde)}
                            (packageDD
                                packageInfos
                                packageDir
                                modules
                                (length (bis pde) - 1)
                                (concatMap (buildInfoD (Just packageDir) modules)
                                    [0..length (bis pde) - 2]))
                            panePath nb modules afterSaveAction origPackageD) ideR
    on closeB buttonActivated $ do
        mbP <- extract packageD [getExt]
        let hasChanged = case mbP of
                                Nothing -> False
                                Just p -> p /= origPackageD
        if not hasChanged
            then reflectIDE (closePane packagePane >> return ()) ideR
            else do
                md <- messageDialogNew (Just window) []
                    MessageQuestion
                    ButtonsYesNo
                    (__ "Unsaved changes. Close anyway?")
                set md [ windowWindowPosition := WinPosCenterOnParent ]
                resp <- dialogRun md
                widgetDestroy md
                case resp of
                    ResponseYes ->   do
                        reflectIDE (closePane packagePane >> return ()) ideR
                    _  ->   return ()
    on save buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> return ()
            Just newPackage' -> let newPackage = fromEditor newPackage' in do
                let packagePath = packageDir </> (display . pkgName . package . pd) newPackage'
                                                ++ ".cabal"
                writeGenericPackageDescription packagePath (toGenericPackageDescription newPackage)
                reflectIDE (do
                    afterSaveAction packagePath
                    closePane packagePane
                    return ()) ideR
    registerEvent notifier MayHaveChanged (\ e -> do
        mbP <- extract packageD [getExt]
        let hasChanged = case mbP of
                                Nothing -> False
                                Just p -> p /= origPackageD
        when (isJust mbP) $ labelSetMarkup label ("" :: Text)
        when (isJust mbP) $ comparePDE (fromJust mbP) packageD
        markLabel nb (getTopWidget packagePane) hasChanged
        widgetSetSensitive save hasChanged
        return (e{gtkReturn=False}))
    registerEvent notifier ValidationError (\e -> do
        labelSetMarkup label $ "<span foreground=\"red\" size=\"x-large\">The following fields have invalid values: "
            <> eventText e <> "</span>"
        return e)
    return (Just packagePane,[])

-- ---------------------------------------------------------------------
-- The description with some tricks
--
builder' :: FilePath ->
    PackageDescriptionEd ->
    FieldDescription PackageDescriptionEd ->
    (FilePath -> IDEAction) ->
    FilePath ->
    [ModuleName] ->
    [PackageId] ->
    [FieldDescription PackageDescriptionEd] ->
    PackageDescriptionEd ->
    PanePath ->
    Notebook ->
    Window ->
    IDEM (Maybe PackagePane,Connections)
builder' packageDir packageD packageDescr afterSaveAction initialPackagePath modules packageInfos fields
    origPackageD panePath nb window  = reifyIDE $ \ ideR -> do
    vb      <-  vBoxNew False 0
    bb      <-  hButtonBoxNew
    save    <- buttonNewFromStock "gtk-save"
    widgetSetSensitive save False
    closeB  <- buttonNewFromStock "gtk-close"
    addB    <- buttonNewFromStock (__ "Add Build Info")
    removeB <- buttonNewFromStock (__ "Remove Build Info")
    label   <-  labelNew (Nothing :: Maybe Text)
    boxPackStart bb addB PackNatural 0
    boxPackStart bb removeB PackNatural 0
    boxPackEnd bb closeB PackNatural 0
    boxPackEnd bb save PackNatural 0
    (widget, setInj, getExt, notifier)  <-  buildEditor packageDescr packageD
    let packagePane = PackagePane vb notifier
    boxPackStart vb widget PackGrow 7
    boxPackStart vb label PackNatural 0
    boxPackEnd vb bb PackNatural 7

    let fieldNames = map (\fd -> case getParameterPrim paraName (parameters fd) of
                                    Just s -> s
                                    Nothing -> (__ "Unnamed")) fields
    on addB buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> sysMessage Normal (__ "Content doesn't validate")
            Just pde -> reflectIDE (do
                    closePane packagePane
                    initPackage packageDir pde {bis = bis pde ++ [bis pde !! 0]}
                        (packageDD
                            (packageInfos)
                            packageDir
                            modules
                            (length (bis pde) + 1)
                            (concatMap (buildInfoD (Just packageDir) modules)
                                [0..length (bis pde)]))
                        panePath nb modules afterSaveAction origPackageD) ideR
    on removeB buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> sysMessage Normal (__ "Content doesn't validate")
            Just pde | length (bis pde) == 1  -> sysMessage Normal (__ "Just one Build Info")
                     | otherwise -> reflectIDE (do
                        closePane packagePane
                        initPackage packageDir pde{bis = take (length (bis pde) - 1) (bis pde)}
                            (packageDD
                                packageInfos
                                packageDir
                                modules
                                (length (bis pde) - 1)
                                (concatMap (buildInfoD (Just packageDir) modules)
                                    [0..length (bis pde) - 2]))
                            panePath nb modules afterSaveAction origPackageD) ideR
    on closeB buttonActivated $ do
        mbP <- extract packageD [getExt]
        let hasChanged = case mbP of
                                Nothing -> False
                                Just p -> p /= origPackageD
        if not hasChanged
            then reflectIDE (closePane packagePane >> return ()) ideR
            else do
                md <- messageDialogNew (Just window) []
                    MessageQuestion
                    ButtonsYesNo
                    (__ "Unsaved changes. Close anyway?")
                set md [ windowWindowPosition := WinPosCenterOnParent ]
                resp <- dialogRun md
                widgetDestroy md
                case resp of
                    ResponseYes ->   do
                        reflectIDE (closePane packagePane >> return ()) ideR
                    _  ->   return ()
    on save buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> return ()
            Just newPackage' -> let newPackage = fromEditor newPackage' in do
                let packagePath = packageDir </> (display . pkgName . package . pd) newPackage'
                                                ++ ".cabal"
                writeGenericPackageDescription packagePath (toGenericPackageDescription newPackage)
                reflectIDE (do
                    afterSaveAction packagePath
                    closePane packagePane
                    return ()) ideR
    registerEvent notifier MayHaveChanged (\ e -> do
        mbP <- extract packageD [getExt]
        let hasChanged = case mbP of
                                Nothing -> False
                                Just p -> p /= origPackageD
        when (isJust mbP) $ labelSetMarkup label ("" :: Text)
        when (isJust mbP) $ comparePDE (fromJust mbP) packageD
        markLabel nb (getTopWidget packagePane) hasChanged
        widgetSetSensitive save hasChanged
        return (e{gtkReturn=False}))
    registerEvent notifier ValidationError (\e -> do
        labelSetMarkup label $ "<span foreground=\"red\" size=\"x-large\">The following fields have invalid values: "
            <> eventText e <> "</span>"
        return e)
    return (Just packagePane,[])

-- ---------------------------------------------------------------------
-- The description with some tricks
--
builder' packageDir packageD packageDescr afterSaveAction initialPackagePath modules packageInfos fields
    origPackageD panePath nb window  = reifyIDE $ \ ideR -> do
    vb      <-  vBoxNew False 0
    bb      <-  hButtonBoxNew
    save    <- buttonNewFromStock "gtk-save"
    widgetSetSensitive save False
    closeB  <- buttonNewFromStock "gtk-close"
    addB    <- buttonNewFromStock (__ "Add Build Info")
    removeB <- buttonNewFromStock (__ "Remove Build Info")
    label   <-  labelNew (Nothing :: Maybe Text)
    boxPackStart bb addB PackNatural 0
    boxPackStart bb removeB PackNatural 0
    boxPackEnd bb closeB PackNatural 0
    boxPackEnd bb save PackNatural 0
    (widget, setInj, getExt, notifier)  <-  buildEditor packageDescr packageD
    let packagePane = PackagePane vb notifier
    boxPackStart vb widget PackGrow 7
    boxPackStart vb label PackNatural 0
    boxPackEnd vb bb PackNatural 7

    let fieldNames = map (\fd -> case getParameterPrim paraName (parameters fd) of
                                    Just s -> s
                                    Nothing -> (__ "Unnamed")) fields
    on addB buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> sysMessage Normal (__ "Content doesn't validate")
            Just pde -> reflectIDE (do
                    closePane packagePane
                    initPackage packageDir pde {bis = bis pde ++ [bis pde !! 0]}
                        (packageDD
                            (packageInfos)
                            packageDir
                            modules
                            (length (bis pde) + 1)
                            (concatMap (buildInfoD (Just packageDir) modules)
                                [0..length (bis pde)]))
                        panePath nb modules afterSaveAction origPackageD) ideR
    on removeB buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> sysMessage Normal (__ "Content doesn't validate")
            Just pde | length (bis pde) == 1  -> sysMessage Normal (__ "Just one Build Info")
                     | otherwise -> reflectIDE (do
                        closePane packagePane
                        initPackage packageDir pde{bis = take (length (bis pde) - 1) (bis pde)}
                            (packageDD
                                packageInfos
                                packageDir
                                modules
                                (length (bis pde) - 1)
                                (concatMap (buildInfoD (Just packageDir) modules)
                                    [0..length (bis pde) - 2]))
                            panePath nb modules afterSaveAction origPackageD) ideR
    on closeB buttonActivated $ do
        mbP <- extract packageD [getExt]
        let hasChanged = case mbP of
                                Nothing -> False
                                Just p -> p /= origPackageD
        if not hasChanged
            then reflectIDE (closePane packagePane >> return ()) ideR
            else do
                md <- messageDialogNew (Just window) []
                    MessageQuestion
                    ButtonsYesNo
                    (__ "Unsaved changes. Close anyway?")
                set md [ windowWindowPosition := WinPosCenterOnParent ]
                resp <- dialogRun md
                widgetDestroy md
                case resp of
                    ResponseYes ->   do
                        reflectIDE (closePane packagePane >> return ()) ideR
                    _  ->   return ()
    on save buttonActivated $ do
        mbNewPackage' <- extract packageD [getExt]
        case mbNewPackage' of
            Nothing -> return ()
            Just newPackage' -> let newPackage = fromEditor newPackage' in do
                let packagePath = packageDir </> (display . pkgName . package . pd) newPackage'
                                                ++ ".cabal"
                writeGenericPackageDescription packagePath (toGenericPackageDescription newPackage)
                reflectIDE (do
                    afterSaveAction packagePath
                    closePane packagePane
                    return ()) ideR
    registerEvent notifier MayHaveChanged (\ e -> do
        mbP <- extract packageD [getExt]
        let hasChanged = case mbP of
                                Nothing -> False
                                Just p -> p /= origPackageD
        when (isJust mbP) $ labelSetMarkup label ("" :: Text)
        when (isJust mbP) $ comparePDE (fromJust mbP) packageD
        markLabel nb (getTopWidget packagePane) hasChanged
        widgetSetSensitive save hasChanged
        return (e{gtkReturn=False}))
    registerEvent notifier ValidationError (\e -> do
        labelSetMarkup label $ "<span foreground=\"red\" size=\"x-large\">The following fields have invalid values: "
            <> eventText e <> "</span>"
        return e)
    return (Just packagePane,[])

-- ---------------------------------------------------------------------
-- The description with some tricks
--