Merge lp:~paolorotolo/pinta/fix-for-1093971 into lp:pinta
- fix-for-1093971
- Merge into trunk
Status: | Needs review | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~paolorotolo/pinta/fix-for-1093971 | ||||
Merge into: | lp:pinta | ||||
Diff against target: |
167457 lines (+164881/-0) (has conflicts) 428 files modified
Makefile.am (+117/-0) Makefile.in (+849/-0) Pinta.Core/.gitignore (+3/-0) Pinta.Core/Actions/AdjustmentsActions.cs (+57/-0) Pinta.Core/Actions/EditActions.cs (+433/-0) Pinta.Core/Actions/EffectsActions.cs (+93/-0) Pinta.Core/Actions/FileActions.cs (+131/-0) Pinta.Core/Actions/HelpActions.cs (+93/-0) Pinta.Core/Actions/ImageActions.cs (+301/-0) Pinta.Core/Actions/LayerActions.cs (+292/-0) Pinta.Core/Actions/ViewActions.cs (+276/-0) Pinta.Core/Actions/WindowActions.cs (+153/-0) Pinta.Core/Classes/Anchor.cs (+43/-0) Pinta.Core/Classes/AsyncEffectRenderer.cs (+361/-0) Pinta.Core/Classes/BaseExtension.cs (+41/-0) Pinta.Core/Classes/BasePaintBrush.cs (+42/-0) Pinta.Core/Classes/BaseTool.cs (+276/-0) Pinta.Core/Classes/Document.cs (+735/-0) Pinta.Core/Classes/DocumentWorkspace.cs (+273/-0) Pinta.Core/Classes/DocumentWorkspaceHistory.cs (+172/-0) Pinta.Core/Classes/GradientRenderer.cs (+229/-0) Pinta.Core/Classes/GradientRenderers.cs (+204/-0) Pinta.Core/Classes/IExtension.cs (+15/-0) Pinta.Core/Classes/IndexEventArgs.cs (+21/-0) Pinta.Core/Classes/IndexEventHandler.cs (+15/-0) Pinta.Core/Classes/Layer.cs (+280/-0) Pinta.Core/Classes/LayerProperties.cs (+53/-0) Pinta.Core/Classes/ObservableObject.cs (+53/-0) Pinta.Core/Classes/Palette.cs (+236/-0) Pinta.Core/Classes/ScaleFactor.cs (+377/-0) Pinta.Core/Effects/BaseEffect.cs (+199/-0) Pinta.Core/Effects/BinaryPixelOp.cs (+152/-0) Pinta.Core/Effects/BitVector2DSurfaceAdapter.cs (+207/-0) Pinta.Core/Effects/ColorBgra.cs (+702/-0) Pinta.Core/Effects/ColorDifferenceEffect.cs (+101/-0) Pinta.Core/Effects/ColorTransferMode.cs (+17/-0) Pinta.Core/Effects/Histogram.cs (+220/-0) Pinta.Core/Effects/HistogramRGB.cs (+136/-0) Pinta.Core/Effects/HsvColor.cs (+189/-0) Pinta.Core/Effects/IBitVector2D.cs (+57/-0) Pinta.Core/Effects/ISurfaceDraw.cs (+50/-0) Pinta.Core/Effects/IrregularSurface.cs (+206/-0) Pinta.Core/Effects/LocalHistogramEffect.cs (+535/-0) Pinta.Core/Effects/PixelOp.cs (+113/-0) Pinta.Core/Effects/PlacedSurface.cs (+175/-0) Pinta.Core/Effects/RgbColor.cs (+132/-0) Pinta.Core/Effects/Scanline.cs (+86/-0) Pinta.Core/Effects/SplineInterpolator.cs (+119/-0) Pinta.Core/Effects/UnaryPixelOp.cs (+107/-0) Pinta.Core/Effects/UnaryPixelOps.cs (+965/-0) Pinta.Core/Effects/UserBlendOp.cs (+34/-0) Pinta.Core/Effects/UserBlendOps.Generated.cs (+368/-0) Pinta.Core/Effects/UserBlendOps.cs (+74/-0) Pinta.Core/Effects/Utility.cs (+710/-0) Pinta.Core/Enumerations/EffectAdjustment.cs (+36/-0) Pinta.Core/Enumerations/GradientColorMode.cs (+36/-0) Pinta.Core/EventArgs/CanvasInvalidatedEventArgs.cs (+48/-0) Pinta.Core/EventArgs/DocumentCancelEventArgs.cs (+43/-0) Pinta.Core/EventArgs/DocumentEventArgs.cs (+40/-0) Pinta.Core/EventArgs/HistoryItemAddedEventArgs.cs (+40/-0) Pinta.Core/EventArgs/HistoryItemRemovedEventArgs.cs (+39/-0) Pinta.Core/EventArgs/LivePreviewEndedEventArgs.cs (+49/-0) Pinta.Core/EventArgs/LivePreviewRenderUpdatedEventArgs.cs (+43/-0) Pinta.Core/EventArgs/LivePreviewStartedEventArgs.cs (+37/-0) Pinta.Core/EventArgs/ModifyCompressionEventArgs.cs (+42/-0) Pinta.Core/EventArgs/TextChangedEventArgs.cs (+40/-0) Pinta.Core/EventArgs/ToolEventArgs.cs (+41/-0) Pinta.Core/Extensions/CairoExtensions.cs (+1410/-0) Pinta.Core/Extensions/GdkExtensions.cs (+106/-0) Pinta.Core/Extensions/GtkExtensions.cs (+193/-0) Pinta.Core/Extensions/OtherExtensions.cs (+109/-0) Pinta.Core/Extensions/ToolBarButton.cs (+45/-0) Pinta.Core/Extensions/ToolBarComboBox.cs (+69/-0) Pinta.Core/Extensions/ToolBarFontComboBox.cs (+65/-0) Pinta.Core/Extensions/ToolBarImage.cs (+43/-0) Pinta.Core/Extensions/ToolBarLabel.cs (+48/-0) Pinta.Core/Extensions/ToolBarSlider.cs (+51/-0) Pinta.Core/Extensions/ToolBarToggleButton.cs (+45/-0) Pinta.Core/HistoryItems/AddLayerHistoryItem.cs (+65/-0) Pinta.Core/HistoryItems/BaseHistoryItem.cs (+74/-0) Pinta.Core/HistoryItems/ClippedSurfaceHistoryItem.cs (+82/-0) Pinta.Core/HistoryItems/CompoundHistoryItem.cs (+75/-0) Pinta.Core/HistoryItems/DeleteLayerHistoryItem.cs (+66/-0) Pinta.Core/HistoryItems/FinishPixelsHistoryItem.cs (+98/-0) Pinta.Core/HistoryItems/InvertHistoryItem.cs (+165/-0) Pinta.Core/HistoryItems/MovePixelsHistoryItem.cs (+112/-0) Pinta.Core/HistoryItems/PasteHistoryItem.cs (+103/-0) Pinta.Core/HistoryItems/ResizeHistoryItem.cs (+110/-0) Pinta.Core/HistoryItems/SelectionHistoryItem.cs (+79/-0) Pinta.Core/HistoryItems/SimpleHistoryItem.cs (+89/-0) Pinta.Core/HistoryItems/SwapLayersHistoryItem.cs (+73/-0) Pinta.Core/HistoryItems/UpdateLayerPropertiesHistoryItem.cs (+70/-0) Pinta.Core/ImageFormats/FormatDescriptor.cs (+82/-0) Pinta.Core/ImageFormats/GdkPixbufFormat.cs (+86/-0) Pinta.Core/ImageFormats/IImageExporter.cs (+35/-0) Pinta.Core/ImageFormats/IImageImporter.cs (+35/-0) Pinta.Core/ImageFormats/JpegFormat.cs (+49/-0) Pinta.Core/ImageFormats/OraFormat.cs (+208/-0) Pinta.Core/ImageFormats/TgaExporter.cs (+118/-0) Pinta.Core/Makefile.am (+125/-0) Pinta.Core/Managers/ActionManager.cs (+161/-0) Pinta.Core/Managers/ChromeManager.cs (+148/-0) Pinta.Core/Managers/EffectsManager.cs (+141/-0) Pinta.Core/Managers/FontManager.cs (+87/-0) Pinta.Core/Managers/HistoryManager.cs (+103/-0) Pinta.Core/Managers/ImageConverterManager.cs (+159/-0) Pinta.Core/Managers/LayerManager.cs (+267/-0) Pinta.Core/Managers/LivePreviewManager.cs (+388/-0) Pinta.Core/Managers/PaintBrushManager.cs (+68/-0) Pinta.Core/Managers/PaletteManager.cs (+93/-0) Pinta.Core/Managers/ResourceManager.cs (+44/-0) Pinta.Core/Managers/SettingsManager.cs (+152/-0) Pinta.Core/Managers/SystemManager.cs (+138/-0) Pinta.Core/Managers/ToolManager.cs (+197/-0) Pinta.Core/Managers/WorkspaceManager.cs (+317/-0) Pinta.Core/Pinta.Core.csproj (+227/-0) Pinta.Core/PintaCore.cs (+71/-0) Pinta.Core/Properties/AssemblyInfo.cs (+26/-0) Pinta.Core/Widgets/MenuButton.cs (+188/-0) Pinta.Core/Widgets/ToolBarDropDownButton.cs (+100/-0) Pinta.Effects/.gitignore (+4/-0) Pinta.Effects/Adjustments/AutoLevelEffect.cs (+45/-0) Pinta.Effects/Adjustments/BlackAndWhiteEffect.cs (+37/-0) Pinta.Effects/Adjustments/BrightnessContrastEffect.cs (+178/-0) Pinta.Effects/Adjustments/CurvesEffect.cs (+137/-0) Pinta.Effects/Adjustments/HueSaturationEffect.cs (+81/-0) Pinta.Effects/Adjustments/InvertColorsEffect.cs (+37/-0) Pinta.Effects/Adjustments/LevelsEffect.cs (+78/-0) Pinta.Effects/Adjustments/PosterizeEffect.cs (+72/-0) Pinta.Effects/Adjustments/SepiaEffect.cs (+50/-0) Pinta.Effects/CoreEffectsExtension.cs (+62/-0) Pinta.Effects/Dialogs/Effects.CurvesDialog.cs (+408/-0) Pinta.Effects/Dialogs/Effects.LevelsDialog.cs (+526/-0) Pinta.Effects/Dialogs/Effects.PosterizeDialog.cs (+84/-0) Pinta.Effects/Effects/AddNoiseEffect.cs (+182/-0) Pinta.Effects/Effects/BulgeEffect.cs (+113/-0) Pinta.Effects/Effects/CloudsEffect.cs (+224/-0) Pinta.Effects/Effects/EdgeDetectEffect.cs (+90/-0) Pinta.Effects/Effects/EmbossEffect.cs (+146/-0) Pinta.Effects/Effects/FragmentEffect.cs (+121/-0) Pinta.Effects/Effects/FrostedGlassEffect.cs (+165/-0) Pinta.Effects/Effects/GaussianBlurEffect.cs (+269/-0) Pinta.Effects/Effects/GlowEffect.cs (+88/-0) Pinta.Effects/Effects/InkSketchEffect.cs (+172/-0) Pinta.Effects/Effects/JuliaFractalEffect.cs (+143/-0) Pinta.Effects/Effects/LocalHistogramEffect.cs (+545/-0) Pinta.Effects/Effects/MandelbrotFractalEffect.cs (+173/-0) Pinta.Effects/Effects/MedianEffect.cs (+80/-0) Pinta.Effects/Effects/MotionBlurEffect.cs (+122/-0) Pinta.Effects/Effects/OilPaintingEffect.cs (+183/-0) Pinta.Effects/Effects/OutlineEffect.cs (+152/-0) Pinta.Effects/Effects/PencilSketchEffect.cs (+106/-0) Pinta.Effects/Effects/PixelateEffect.cs (+122/-0) Pinta.Effects/Effects/PolarInversionEffect.cs (+72/-0) Pinta.Effects/Effects/RadialBlurEffect.cs (+170/-0) Pinta.Effects/Effects/RedEyeRemoveEffect.cs (+82/-0) Pinta.Effects/Effects/ReduceNoiseEffect.cs (+101/-0) Pinta.Effects/Effects/ReliefEffect.cs (+90/-0) Pinta.Effects/Effects/SharpenEffect.cs (+67/-0) Pinta.Effects/Effects/SoftenPortraitEffect.cs (+128/-0) Pinta.Effects/Effects/TileEffect.cs (+146/-0) Pinta.Effects/Effects/TwistEffect.cs (+137/-0) Pinta.Effects/Effects/UnfocusEffect.cs (+105/-0) Pinta.Effects/Effects/WarpEffect.cs (+191/-0) Pinta.Effects/Effects/ZoomBlurEffect.cs (+140/-0) Pinta.Effects/Makefile.am (+70/-0) Pinta.Effects/Pinta.Effects.csproj (+167/-0) Pinta.Effects/Properties/AssemblyInfo.cs (+42/-0) Pinta.Effects/Utilities/EffectHelper.cs (+66/-0) Pinta.Effects/gtk-gui/Pinta.Effects.CurvesDialog.cs (+234/-0) Pinta.Effects/gtk-gui/Pinta.Effects.LevelsDialog.cs (+566/-0) Pinta.Effects/gtk-gui/Pinta.Effects.PosterizeDialog.cs (+141/-0) Pinta.Effects/gtk-gui/generated.cs (+29/-0) Pinta.Effects/gtk-gui/gui.stetic (+1069/-0) Pinta.Gui.Widgets/.gitignore (+3/-0) Pinta.Gui.Widgets/DialogAttributes.cs (+101/-0) Pinta.Gui.Widgets/Dialogs/SimpleEffectDialog.cs (+426/-0) Pinta.Gui.Widgets/Makefile.am (+49/-0) Pinta.Gui.Widgets/Pinta.Gui.Widgets.csproj (+134/-0) Pinta.Gui.Widgets/Properties/AssemblyInfo.cs (+51/-0) Pinta.Gui.Widgets/Widgets/AnglePickerGraphic.cs (+179/-0) Pinta.Gui.Widgets/Widgets/AnglePickerWidget.cs (+90/-0) Pinta.Gui.Widgets/Widgets/Canvas/CanvasRenderer.cs (+306/-0) Pinta.Gui.Widgets/Widgets/Canvas/GridRenderer.cs (+86/-0) Pinta.Gui.Widgets/Widgets/Canvas/PintaCanvas.cs (+263/-0) Pinta.Gui.Widgets/Widgets/ColorGradientWidget.cs (+293/-0) Pinta.Gui.Widgets/Widgets/ColorPaletteWidget.cs (+197/-0) Pinta.Gui.Widgets/Widgets/ColorPanelWidget.cs (+65/-0) Pinta.Gui.Widgets/Widgets/ComboBoxWidget.cs (+72/-0) Pinta.Gui.Widgets/Widgets/HScaleSpinButtonWidget.cs (+164/-0) Pinta.Gui.Widgets/Widgets/HistogramWidget.cs (+176/-0) Pinta.Gui.Widgets/Widgets/History/HistoryTreeView.cs (+134/-0) Pinta.Gui.Widgets/Widgets/Layers/CellRendererSurface.cs (+132/-0) Pinta.Gui.Widgets/Widgets/Layers/LayersListWidget.cs (+224/-0) Pinta.Gui.Widgets/Widgets/OpenImages/OpenImagesListWidget.cs (+195/-0) Pinta.Gui.Widgets/Widgets/PointPickerGraphic.cs (+193/-0) Pinta.Gui.Widgets/Widgets/PointPickerWidget.cs (+147/-0) Pinta.Gui.Widgets/Widgets/ReseedButtonWidget.cs (+56/-0) Pinta.Gui.Widgets/Widgets/ToolBoxWidget.cs (+59/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.AnglePickerWidget.cs (+140/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.ColorGradientWidget.cs (+29/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.ColorPanelWidget.cs (+28/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.ComboBoxWidget.cs (+74/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.HScaleSpinButtonWidget.cs (+130/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.HistogramWidget.cs (+19/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.PointPickerWidget.cs (+206/-0) Pinta.Gui.Widgets/gtk-gui/Pinta.Gui.Widgets.ReseedButtonWidget.cs (+89/-0) Pinta.Gui.Widgets/gtk-gui/generated.cs (+115/-0) Pinta.Gui.Widgets/gtk-gui/gui.stetic (+654/-0) Pinta.Install.proj (+234/-0) Pinta.Resources/.gitignore (+2/-0) Pinta.Resources/Makefile.am (+166/-0) Pinta.Resources/Pinta.Resources.csproj (+547/-0) Pinta.Resources/Properties/AssemblyInfo.cs (+26/-0) Pinta.Resources/ResourceManager.cs (+44/-0) Pinta.Tools/.gitignore (+4/-0) Pinta.Tools/Brushes/CircleBrush.cs (+64/-0) Pinta.Tools/Brushes/GridBrush.cs (+64/-0) Pinta.Tools/Brushes/PaintBrush.cs (+86/-0) Pinta.Tools/Brushes/PlainBrush.cs (+65/-0) Pinta.Tools/Brushes/SplatterBrush.cs (+86/-0) Pinta.Tools/Brushes/SquaresBrush.cs (+60/-0) Pinta.Tools/CoreToolsExtension.cs (+50/-0) Pinta.Tools/Makefile.am (+55/-0) Pinta.Tools/Pinta.Tools.csproj (+149/-0) Pinta.Tools/Properties/AssemblyInfo.cs (+42/-0) Pinta.Tools/Tools/BaseBrushTool.cs (+165/-0) Pinta.Tools/Tools/CloneStampTool.cs (+160/-0) Pinta.Tools/Tools/ColorPickerTool.cs (+130/-0) Pinta.Tools/Tools/EllipseSelectTool.cs (+61/-0) Pinta.Tools/Tools/EllipseTool.cs (+82/-0) Pinta.Tools/Tools/EraserTool.cs (+107/-0) Pinta.Tools/Tools/FloodTool.cs (+362/-0) Pinta.Tools/Tools/FreeformShapeTool.cs (+228/-0) Pinta.Tools/Tools/GradientTool.cs (+221/-0) Pinta.Tools/Tools/LassoSelectTool.cs (+125/-0) Pinta.Tools/Tools/LineCurveTool.cs (+90/-0) Pinta.Tools/Tools/MagicWandTool.cs (+133/-0) Pinta.Tools/Tools/MoveSelectedTool.cs (+152/-0) Pinta.Tools/Tools/MoveSelectionTool.cs (+107/-0) Pinta.Tools/Tools/PaintBrushTool.cs (+165/-0) Pinta.Tools/Tools/PaintBucketTool.cs (+104/-0) Pinta.Tools/Tools/PanTool.cs (+84/-0) Pinta.Tools/Tools/PencilTool.cs (+174/-0) Pinta.Tools/Tools/RecolorTool.cs (+226/-0) Pinta.Tools/Tools/RectangleSelectTool.cs (+62/-0) Pinta.Tools/Tools/RectangleTool.cs (+76/-0) Pinta.Tools/Tools/RoundedRectangleTool.cs (+148/-0) Pinta.Tools/Tools/SelectTool.cs (+314/-0) Pinta.Tools/Tools/ShapeTool.cs (+276/-0) Pinta.Tools/Tools/TextTool/EditingMode.cs (+20/-0) Pinta.Tools/Tools/TextTool/Position.cs (+35/-0) Pinta.Tools/Tools/TextTool/TextAlignment.cs (+20/-0) Pinta.Tools/Tools/TextTool/TextEngine.cs (+442/-0) Pinta.Tools/Tools/TextTool/TextTool.cs (+719/-0) Pinta.Tools/Tools/ToolControl/ToolControl.cs (+71/-0) Pinta.Tools/Tools/ZoomTool.cs (+191/-0) Pinta.sln (+75/-0) Pinta/.gitignore (+4/-0) Pinta/Actions/Edit/PasteIntoNewImageAction.cs (+81/-0) Pinta/Actions/Edit/PasteIntoNewLayerAction.cs (+91/-0) Pinta/Actions/Edit/ResizePaletteAction.cs (+61/-0) Pinta/Actions/File/CloseDocumentAction.cs (+91/-0) Pinta/Actions/File/ExitAction.cs (+67/-0) Pinta/Actions/File/ModifyCompressionAction.cs (+62/-0) Pinta/Actions/File/NewDocumentAction.cs (+75/-0) Pinta/Actions/File/NewScreenshotAction.cs (+88/-0) Pinta/Actions/File/OpenDocumentAction.cs (+85/-0) Pinta/Actions/File/OpenRecentAction.cs (+55/-0) Pinta/Actions/File/SaveDocumentAction.cs (+51/-0) Pinta/Actions/File/SaveDocumentAsAction.cs (+51/-0) Pinta/Actions/File/SaveDocumentImplementationAction.cs (+246/-0) Pinta/Actions/Help/AboutDialogAction.cs (+60/-0) Pinta/Actions/Help/ExtensionManagerAction.cs (+58/-0) Pinta/Actions/IActionHandler.cs (+13/-0) Pinta/Actions/Image/ResizeCanvasAction.cs (+62/-0) Pinta/Actions/Image/ResizeImageAction.cs (+62/-0) Pinta/Actions/Layers/LayerPropertiesAction.cs (+112/-0) Pinta/Actions/Layers/RotateZoomLayerAction.cs (+90/-0) Pinta/Actions/View/ToolBarToggledAction.cs (+52/-0) Pinta/Actions/Window/CloseAllDocumentsAction.cs (+60/-0) Pinta/Actions/Window/SaveAllDocumentsAction.cs (+60/-0) Pinta/DialogHandlers.cs (+172/-0) Pinta/Dialogs/AboutDialog.cs (+312/-0) Pinta/Dialogs/AboutPintaTabPage.cs (+65/-0) Pinta/Dialogs/ErrorDialog.cs (+205/-0) Pinta/Dialogs/JpegCompressionDialog.cs (+64/-0) Pinta/Dialogs/LayerPropertiesDialog.cs (+126/-0) Pinta/Dialogs/NewImageDialog.cs (+58/-0) Pinta/Dialogs/ProgressDialog.cs (+79/-0) Pinta/Dialogs/ResizeCanvasDialog.cs (+279/-0) Pinta/Dialogs/ResizeImageDialog.cs (+128/-0) Pinta/Dialogs/SpinButtonEntryDialog.cs (+64/-0) Pinta/Dialogs/VersionInformationTabPage.cs (+94/-0) Pinta/DockLibrary/AutoHideBox.cs (+403/-0) Pinta/DockLibrary/DockBar.cs (+176/-0) Pinta/DockLibrary/DockBarItem.cs (+397/-0) Pinta/DockLibrary/DockContainer.cs (+451/-0) Pinta/DockLibrary/DockFrame.cs (+700/-0) Pinta/DockLibrary/DockFrameTopLevel.cs (+61/-0) Pinta/DockLibrary/DockGroup.cs (+1138/-0) Pinta/DockLibrary/DockGroupItem.cs (+418/-0) Pinta/DockLibrary/DockGroupType.cs (+41/-0) Pinta/DockLibrary/DockItem.cs (+518/-0) Pinta/DockLibrary/DockItemBehavior.cs (+48/-0) Pinta/DockLibrary/DockItemContainer.cs (+424/-0) Pinta/DockLibrary/DockItemStatus.cs (+42/-0) Pinta/DockLibrary/DockItemToolbar.cs (+181/-0) Pinta/DockLibrary/DockLayout.cs (+107/-0) Pinta/DockLibrary/DockObject.cs (+284/-0) Pinta/DockLibrary/DockPosition.cs (+45/-0) Pinta/DockLibrary/HslColor.cs (+158/-0) Pinta/DockLibrary/PlaceholderWindow.cs (+143/-0) Pinta/DockLibrary/ShadedContainer.cs (+351/-0) Pinta/DockLibrary/TabStrip.cs (+407/-0) Pinta/ExtensionPoints.cs (+45/-0) Pinta/Extensions/GtkExtensions.cs (+62/-0) Pinta/IgeMacMenu.cs (+94/-0) Pinta/Main.cs (+132/-0) Pinta/MainWindow.cs (+382/-0) Pinta/Makefile.am (+74/-0) Pinta/Options.cs (+1101/-0) Pinta/Pads/CanvasPad.cs (+175/-0) Pinta/Pads/ColorPalettePad.cs (+57/-0) Pinta/Pads/HistoryPad.cs (+57/-0) Pinta/Pads/IDockPad.cs (+11/-0) Pinta/Pads/LayersPad.cs (+63/-0) Pinta/Pads/OpenImagesPad.cs (+59/-0) Pinta/Pads/ToolBoxPad.cs (+55/-0) Pinta/Pinta.csproj (+213/-0) Pinta/Properties/AssemblyInfo.cs (+26/-0) Pinta/WindowShell.cs (+102/-0) Pinta/gtk-gui/Pinta.LayerPropertiesDialog.cs (+170/-0) Pinta/gtk-gui/Pinta.NewImageDialog.cs (+208/-0) Pinta/gtk-gui/Pinta.ProgressDialog.cs (+74/-0) Pinta/gtk-gui/Pinta.ResizeCanvasDialog.cs (+588/-0) Pinta/gtk-gui/Pinta.ResizeImageDialog.cs (+267/-0) Pinta/gtk-gui/generated.cs (+115/-0) Pinta/gtk-gui/gui.stetic (+1467/-0) Pinta/pinta.in (+3/-0) aclocal.m4 (+1788/-0) configure (+7423/-0) configure.ac (+68/-0) debian/changelog (+186/-0) debian/compat (+1/-0) debian/control (+32/-0) debian/copyright (+566/-0) debian/rules (+10/-0) debian/source/format (+1/-0) debian/watch (+4/-0) install-sh (+520/-0) license-mit.txt (+21/-0) license-pdn.txt (+20/-0) missing (+376/-0) pinta.in (+2/-0) pinta.pc.in (+9/-0) po/Makefile (+217/-0) po/Makefile.in (+217/-0) po/Makefile.in.in (+217/-0) po/POTFILES (+1/-0) po/POTFILES.in (+1/-0) po/af.po (+1635/-0) po/ar.po (+1671/-0) po/bg.po (+1662/-0) po/br.po (+1678/-0) po/bs.po (+1667/-0) po/ca.po (+1642/-0) po/cs.po (+1665/-0) po/da.po (+1676/-0) po/de.po (+1697/-0) po/el.po (+1668/-0) po/en_AU.po (+1667/-0) po/en_CA.po (+1667/-0) po/en_GB.po (+1675/-0) po/eo.po (+1671/-0) po/es.po (+1684/-0) po/et.po (+1635/-0) po/eu.po (+1681/-0) po/fi.po (+1671/-0) po/fil.po (+1636/-0) po/fo.po (+1650/-0) po/fr.po (+1693/-0) po/ga.po (+1639/-0) po/gl.po (+1686/-0) po/he.po (+1664/-0) po/hi.po (+1634/-0) po/hr.po (+1670/-0) po/hu.po (+1673/-0) po/hy.po (+1635/-0) po/id.po (+1674/-0) po/it.po (+1699/-0) po/ja.po (+1641/-0) po/ko.po (+1639/-0) po/la.po (+1635/-0) po/lt.po (+1655/-0) po/lv.po (+1671/-0) po/messages.in (+173/-0) po/messages.pot (+1628/-0) po/ms.po (+1673/-0) po/nb.po (+1677/-0) po/nl.po (+1676/-0) po/nn.po (+1659/-0) po/oc.po (+1635/-0) po/pl.po (+1703/-0) po/pt.po (+1685/-0) po/pt_BR.po (+1693/-0) po/ro.po (+1679/-0) po/ru.po (+1692/-0) po/sk.po (+1668/-0) po/sl.po (+1669/-0) po/sq.po (+1635/-0) po/sr.po (+1667/-0) po/sv.po (+1676/-0) po/th.po (+1637/-0) po/tr.po (+1675/-0) po/uk.po (+1674/-0) po/vi.po (+1638/-0) po/zh_CN.po (+1638/-0) po/zh_TW.po (+1638/-0) readme.md (+76/-0) todo.txt (+7/-0) xdg/Makefile (+467/-0) xdg/Makefile.am (+15/-0) xdg/Makefile.in (+467/-0) xdg/pinta.1 (+29/-0) xdg/pinta.desktop.in (+12/-0) xdg/pinta.xpm (+286/-0) xdg/scalable/pinta.svg (+546/-0) Conflict adding file Makefile.am. Moved existing file to Makefile.am.moved. Conflict adding file Pinta.Core. Moved existing file to Pinta.Core.moved. Conflict adding file Pinta.Effects. Moved existing file to Pinta.Effects.moved. Conflict adding file Pinta.Gui.Widgets. Moved existing file to Pinta.Gui.Widgets.moved. Conflict adding file Pinta.Install.proj. Moved existing file to Pinta.Install.proj.moved. Conflict adding file Pinta.Resources. Moved existing file to Pinta.Resources.moved. Conflict adding file Pinta.Tools. Moved existing file to Pinta.Tools.moved. Conflict adding file Pinta. Moved existing file to Pinta.moved. Conflict adding file Pinta.sln. Moved existing file to Pinta.sln.moved. Conflict adding file configure.ac. Moved existing file to configure.ac.moved. Conflict adding file license-mit.txt. Moved existing file to license-mit.txt.moved. Conflict adding file license-pdn.txt. Moved existing file to license-pdn.txt.moved. Conflict adding file pinta.in. Moved existing file to pinta.in.moved. Conflict adding file pinta.pc.in. Moved existing file to pinta.pc.in.moved. Conflict adding file po. Moved existing file to po.moved. Conflict adding file readme.md. Moved existing file to readme.md.moved. Conflict adding file xdg. Moved existing file to xdg.moved. |
||||
To merge this branch: | bzr merge lp:~paolorotolo/pinta/fix-for-1093971 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Pinta Maintainers | Pending | ||
Review via email: mp+144515@code.launchpad.net |
Commit message
Description of the change
Add gnome-icon-
Unmerged revisions
- 14. By Paolo Rotolo
-
* Add gnome-icon-
theme-full to depends (LP: #1093971) - 13. By Iain Lane
-
* [2c6b414] Imported Upstream version 1.2
- Individual layers can now be rotated arbitrarily
- Added specific mouse cursors for tools (pencil, paintbucket, etc)
- Autocrop of image
- Gradient tool now takes advantage of multiple cores to speed up
rendering time
- Added image preview to the images pad
- Added white text background option
- Show image previews in the Open File dialog
* [7e1f9e8] Update BDs to require Mono 2.8 per upstream - 12. By Jo Shields
-
* [236a231] Update debian/rules for DH8-compatible "--with cli"
* [51033d9] Fix typo in clean override rule
* [87189a7] Add a get-out so "make cleanall" doesn't fail the build on a
pristine tree - 11. By Iain Lane
-
* [a2af0ce] Imported Upstream version 1.1
* [6b57160] Wrap too-long changelog line — silence, Lintian!
* [1e6d30f] Update copyright to newer DEP5ness
* [3879389] Update watch file for new upstream download location
* Remove upstreamed patches
+ [16a2b1b] remove-targetversion patch
+ [0114794] unversion-lib-references
* Add new build dependencies required by this release
+ [1cc97d9] mono-addins
+ [b698368] intltool
* [b698368] Remove references to other programs in long description
* [bd76c1d] BD on intltool for required by upstream - 10. By Iain Lane
-
[92d659c] Depend on gnome-icon-theme since Pinta will crash without the icons
(LP: #846396) - 9. By Jo Shields
-
No change rebuild against Mono's CLR 4.0 class library
- 8. By Iain Lane
-
* Upload to unstable
* [1b878e8] Update to use my d.o email address
* [22d952c] Alter BDs and patches so we can build against both 2.0 and 4.0 - 7. By Rico Tzschichholz
-
New upstream release version 0.7
- 6. By Maia Everett
-
* Add myself to uploaders.
* Add cairo_1.9_flush_ markdirty. patch:
- Fix rendering with Cairo 1.9 (Closes: #588886)
* Add tools_exceptions_and_history_ corruption. patch:
- Fix exceptions and data loss when clicking two mouse buttons
while drawing
* Add double_save_exception. patch:
- Fix exception when trying to save after doing "save as"
* Add tool_toolbar_fixed_size. patch:
- Force tool toolbar to fixed size
* Bump Standards-Version to 3.9.1, no changes needed. - 5. By Jo Shields
-
[ Jo Shields ]
* New upstream release
* +DFSG release of Pinta 0.4. Deleted files:
+ ./Pinta.Gui.Widgets/ bin/Debug/ Pinta.Gui. Widgets. dll
* debian/rules:
+ Switch to entirely minimal DH7 rules file, since the Automake
wrapper for xbuild handles things we were having to do by hand
* debian/pinta.sh,
debian/pinta.desktop,
debian/pinta.xpm,
debian/pinta.install:
+ Upstream now takes care of providing an icon and a .desktop file,
and DH7 takes care of putting everything where it should be, so
all these files have been deleted
* debian/copyright:
+ Updated (thanks to Maia Kozheva <email address hidden>)[ Iain Lane ]
* [a8be0d2] Remove BD on libglade2.0-cil-dev; no longer necessary
* [41bfc27] debian/watch: Mangle version for +dfsg
* [9c1ad07] Standards-Version → 3.9.0, no changes required
* [0232079] Work around buggy upstream make clean target, fixing
double build
Preview Diff
1 | === added file 'Makefile.am' |
2 | --- Makefile.am 1970-01-01 00:00:00 +0000 |
3 | +++ Makefile.am 2013-01-23 15:01:21 +0000 |
4 | @@ -0,0 +1,117 @@ |
5 | +SUBDIRS = xdg |
6 | + |
7 | +BINDIR = $(srcdir)/bin |
8 | + |
9 | +PINTA_ASSEMBLY_PC = $(srcdir)/$(PACKAGE_NAME).pc |
10 | + |
11 | +BINFILES = \ |
12 | + $(BINDIR)/Pinta.exe \ |
13 | + $(BINDIR)/Pinta.Core.dll \ |
14 | + $(BINDIR)/Pinta.Gui.Widgets.dll \ |
15 | + $(BINDIR)/Pinta.Resources.dll \ |
16 | + $(BINDIR)/Pinta.Effects.dll \ |
17 | + $(BINDIR)/Pinta.Tools.dll |
18 | + |
19 | +RELEASE_FILE = $(PACKAGE)-$(VERSION) |
20 | + |
21 | +#magic automake variables |
22 | + |
23 | +pkgconfigdir = $(libdir)/pkgconfig |
24 | +pkgconfig_DATA = $(PINTA_ASSEMBLY_PC) |
25 | + |
26 | +#end |
27 | + |
28 | +# target: all - Default target: build |
29 | +all: build |
30 | + |
31 | +# target: run - Launch the uninstalled copy |
32 | +run: |
33 | + $(MONO) bin/Pinta.exe |
34 | + |
35 | +# target: help - Display callable targets. |
36 | +help: |
37 | + egrep "^# target:" Makefile | sed 's/^# target:/make/' |
38 | + |
39 | +# target: build - Build Pinta. |
40 | +build: Pinta.sln |
41 | + cd $(srcdir) && $(XBUILD) Pinta.sln |
42 | + cd $(srcdir) && $(XBUILD) Pinta.Install.proj /target:CompileTranslations |
43 | + |
44 | +# target: list - List source files. |
45 | +list: |
46 | + if ! git status > /dev/null 2> /dev/null ;\ |
47 | + then \ |
48 | + find . -type f -name *.cs | sed 's|./||' ;\ |
49 | + else \ |
50 | + git ls-files | grep '\.cs' ;\ |
51 | + fi |
52 | + |
53 | +#target: updatepot - update the messages.pot file |
54 | +updatepot: build |
55 | + find . -type f -name *.cs | sed 's|./||' > files.list |
56 | + grep -v System.ComponentModel.Composition files.list > files2.list |
57 | + xgettext --from-code=UTF-8 -f files2.list -o po/messages.pot |
58 | + cat po/messages.in >> po/messages.pot |
59 | + rm files.list |
60 | + rm files2.list |
61 | + |
62 | +# target: clean - Default clean command: cleanobj and cleanbin |
63 | +clean: cleanobj cleanbin |
64 | + |
65 | +# target: distclean - Removes configure files. |
66 | +distclean: clean |
67 | + rm -f Makefile pinta config.status config.cache config.log configure.lineno config.status.lineno pinta.pc |
68 | + |
69 | +# target: cleanall - Removes build files. |
70 | +cleanall: distclean |
71 | + rm -rf autom4te.cache |
72 | + rm -f configure aclocal.m4 missing install-sh Makefile.in |
73 | + |
74 | +# target: cleanbin - Removes built files. |
75 | +cleanbin: |
76 | + rm -rvf $(BINDIR)/* |
77 | + |
78 | +# target: cleanobj - Removes temporary build files. |
79 | +cleanobj: |
80 | + find $(srcdir)/ -type d -name obj | xargs rm -rvf |
81 | + |
82 | +# target: install - Installs Pinta. |
83 | +install: pinta $(BINFILES) |
84 | + cd $(srcdir) && $(XBUILD) /target:Install /property:InstallPrefix=$(DESTDIR)$(prefix) \ |
85 | + /property:BinDir=$(DESTDIR)$(bindir) /property:LibDir=$(DESTDIR)$(libdir) \ |
86 | + /property:DataRootDir=$(DESTDIR)$(datarootdir) /property:ManDir=$(DESTDIR)$(mandir) \ |
87 | + /property:LocaleDir=$(DESTDIR)$(localedir) Pinta.Install.proj |
88 | + $(INSTALL_SCRIPT) pinta $(DESTDIR)$(bindir)/$(PACKAGE) |
89 | + |
90 | +# target: uninstall - Uninstalls Pinta. |
91 | +uninstall: |
92 | + $(XBUILD) /target:Uninstall /property:InstallPrefix=$(DESTDIR)$(prefix) Pinta.Install.proj |
93 | + |
94 | +# target: release - Default release type: releasetar |
95 | +release: releasetar |
96 | + |
97 | +# target: releasetar - Make a release tarball. |
98 | +releasetar: $(BINFILES) |
99 | + cd $(BINDIR) && tar -czf ../$(RELEASE_FILE).tgz --exclude=*mdb * |
100 | + |
101 | +# target: releasezip - Make a release zip file. |
102 | +releasezip: $(BINFILES) |
103 | + cd $(BINDIR) && zip -r ../$(RELEASE_FILE).zip * -x "*.mdb" |
104 | + |
105 | +EXTRA_DIST = Pinta Pinta.Core Pinta.Effects Pinta.Gui.Widgets Pinta.Resources Pinta.Tools po xdg license-mit.txt \ |
106 | + license-pdn.txt todo.txt Pinta.sln Pinta.Install.proj pinta.pc.in readme.md intltool-extract.in \ |
107 | + intltool-merge.in intltool-update.in |
108 | + |
109 | +CLEANFILES = \ |
110 | + intltool-extract \ |
111 | + intltool-update \ |
112 | + intltool-merge |
113 | + |
114 | +DISTCLEANFILES = intltool-extract \ |
115 | + intltool-merge \ |
116 | + intltool-update \ |
117 | + po/.intltool-merge-cache |
118 | + |
119 | + |
120 | + |
121 | +.PHONY: install uninstall cleanall cleanbin cleanobj release releasetar releasezip |
122 | |
123 | === renamed file 'Makefile.am' => 'Makefile.am.moved' |
124 | === added file 'Makefile.in' |
125 | --- Makefile.in 1970-01-01 00:00:00 +0000 |
126 | +++ Makefile.in 2013-01-23 15:01:21 +0000 |
127 | @@ -0,0 +1,849 @@ |
128 | +# Makefile.in generated by automake 1.11.1 from Makefile.am. |
129 | +# @configure_input@ |
130 | + |
131 | +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
132 | +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, |
133 | +# Inc. |
134 | +# This Makefile.in is free software; the Free Software Foundation |
135 | +# gives unlimited permission to copy and/or distribute it, |
136 | +# with or without modifications, as long as this notice is preserved. |
137 | + |
138 | +# This program is distributed in the hope that it will be useful, |
139 | +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without |
140 | +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
141 | +# PARTICULAR PURPOSE. |
142 | + |
143 | +@SET_MAKE@ |
144 | + |
145 | +VPATH = @srcdir@ |
146 | +pkgdatadir = $(datadir)/@PACKAGE@ |
147 | +pkgincludedir = $(includedir)/@PACKAGE@ |
148 | +pkglibdir = $(libdir)/@PACKAGE@ |
149 | +pkglibexecdir = $(libexecdir)/@PACKAGE@ |
150 | +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd |
151 | +install_sh_DATA = $(install_sh) -c -m 644 |
152 | +install_sh_PROGRAM = $(install_sh) -c |
153 | +install_sh_SCRIPT = $(install_sh) -c |
154 | +INSTALL_HEADER = $(INSTALL_DATA) |
155 | +transform = $(program_transform_name) |
156 | +NORMAL_INSTALL = : |
157 | +PRE_INSTALL = : |
158 | +POST_INSTALL = : |
159 | +NORMAL_UNINSTALL = : |
160 | +PRE_UNINSTALL = : |
161 | +POST_UNINSTALL = : |
162 | +subdir = . |
163 | +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ |
164 | + $(srcdir)/Makefile.in $(srcdir)/pinta.in $(srcdir)/pinta.pc.in \ |
165 | + $(top_srcdir)/configure install-sh missing |
166 | +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 |
167 | +am__aclocal_m4_deps = $(top_srcdir)/configure.ac |
168 | +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ |
169 | + $(ACLOCAL_M4) |
170 | +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ |
171 | + configure.lineno config.status.lineno |
172 | +mkinstalldirs = $(install_sh) -d |
173 | +CONFIG_CLEAN_FILES = pinta.pc pinta |
174 | +CONFIG_CLEAN_VPATH_FILES = |
175 | +SOURCES = |
176 | +DIST_SOURCES = |
177 | +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ |
178 | + html-recursive info-recursive install-data-recursive \ |
179 | + install-dvi-recursive install-exec-recursive \ |
180 | + install-html-recursive install-info-recursive \ |
181 | + install-pdf-recursive install-ps-recursive install-recursive \ |
182 | + installcheck-recursive installdirs-recursive pdf-recursive \ |
183 | + ps-recursive uninstall-recursive |
184 | +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
185 | +am__vpath_adj = case $$p in \ |
186 | + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
187 | + *) f=$$p;; \ |
188 | + esac; |
189 | +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
190 | +am__install_max = 40 |
191 | +am__nobase_strip_setup = \ |
192 | + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
193 | +am__nobase_strip = \ |
194 | + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
195 | +am__nobase_list = $(am__nobase_strip_setup); \ |
196 | + for p in $$list; do echo "$$p $$p"; done | \ |
197 | + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
198 | + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
199 | + if (++n[$$2] == $(am__install_max)) \ |
200 | + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
201 | + END { for (dir in files) print dir, files[dir] }' |
202 | +am__base_list = \ |
203 | + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
204 | + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
205 | +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" |
206 | +DATA = $(pkgconfig_DATA) |
207 | +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ |
208 | + distclean-recursive maintainer-clean-recursive |
209 | +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ |
210 | + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ |
211 | + distdir dist dist-all distcheck |
212 | +ETAGS = etags |
213 | +CTAGS = ctags |
214 | +DIST_SUBDIRS = $(SUBDIRS) |
215 | +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
216 | +distdir = $(PACKAGE)-$(VERSION) |
217 | +top_distdir = $(distdir) |
218 | +am__remove_distdir = \ |
219 | + { test ! -d "$(distdir)" \ |
220 | + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ |
221 | + && rm -fr "$(distdir)"; }; } |
222 | +am__relativize = \ |
223 | + dir0=`pwd`; \ |
224 | + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ |
225 | + sed_rest='s,^[^/]*/*,,'; \ |
226 | + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ |
227 | + sed_butlast='s,/*[^/]*$$,,'; \ |
228 | + while test -n "$$dir1"; do \ |
229 | + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ |
230 | + if test "$$first" != "."; then \ |
231 | + if test "$$first" = ".."; then \ |
232 | + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ |
233 | + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ |
234 | + else \ |
235 | + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ |
236 | + if test "$$first2" = "$$first"; then \ |
237 | + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ |
238 | + else \ |
239 | + dir2="../$$dir2"; \ |
240 | + fi; \ |
241 | + dir0="$$dir0"/"$$first"; \ |
242 | + fi; \ |
243 | + fi; \ |
244 | + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ |
245 | + done; \ |
246 | + reldir="$$dir2" |
247 | +DIST_ARCHIVES = $(distdir).tar.gz |
248 | +GZIP_ENV = --best |
249 | +distuninstallcheck_listfiles = find . -type f -print |
250 | +distcleancheck_listfiles = find . -type f -print |
251 | +ACLOCAL = @ACLOCAL@ |
252 | +ALL_LINGUAS = @ALL_LINGUAS@ |
253 | +AMTAR = @AMTAR@ |
254 | +AUTOCONF = @AUTOCONF@ |
255 | +AUTOHEADER = @AUTOHEADER@ |
256 | +AUTOMAKE = @AUTOMAKE@ |
257 | +AWK = @AWK@ |
258 | +CATALOGS = @CATALOGS@ |
259 | +CATOBJEXT = @CATOBJEXT@ |
260 | +CC = @CC@ |
261 | +CCDEPMODE = @CCDEPMODE@ |
262 | +CFLAGS = @CFLAGS@ |
263 | +CPP = @CPP@ |
264 | +CPPFLAGS = @CPPFLAGS@ |
265 | +CYGPATH_W = @CYGPATH_W@ |
266 | +DATADIRNAME = @DATADIRNAME@ |
267 | +DEFS = @DEFS@ |
268 | +DEPDIR = @DEPDIR@ |
269 | +ECHO_C = @ECHO_C@ |
270 | +ECHO_N = @ECHO_N@ |
271 | +ECHO_T = @ECHO_T@ |
272 | +EGREP = @EGREP@ |
273 | +EXEEXT = @EXEEXT@ |
274 | +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ |
275 | +GLIB_SHARP_20_CFLAGS = @GLIB_SHARP_20_CFLAGS@ |
276 | +GLIB_SHARP_20_LIBS = @GLIB_SHARP_20_LIBS@ |
277 | +GMOFILES = @GMOFILES@ |
278 | +GMSGFMT = @GMSGFMT@ |
279 | +GREP = @GREP@ |
280 | +GTK_SHARP_20_CFLAGS = @GTK_SHARP_20_CFLAGS@ |
281 | +GTK_SHARP_20_LIBS = @GTK_SHARP_20_LIBS@ |
282 | +INSTALL = @INSTALL@ |
283 | +INSTALL_DATA = @INSTALL_DATA@ |
284 | +INSTALL_PROGRAM = @INSTALL_PROGRAM@ |
285 | +INSTALL_SCRIPT = @INSTALL_SCRIPT@ |
286 | +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ |
287 | +INSTOBJEXT = @INSTOBJEXT@ |
288 | +INTLLIBS = @INTLLIBS@ |
289 | +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ |
290 | +INTLTOOL_MERGE = @INTLTOOL_MERGE@ |
291 | +INTLTOOL_PERL = @INTLTOOL_PERL@ |
292 | +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ |
293 | +LDFLAGS = @LDFLAGS@ |
294 | +LIBOBJS = @LIBOBJS@ |
295 | +LIBS = @LIBS@ |
296 | +LTLIBOBJS = @LTLIBOBJS@ |
297 | +MAKEINFO = @MAKEINFO@ |
298 | +MKDIR_P = @MKDIR_P@ |
299 | +MKINSTALLDIRS = @MKINSTALLDIRS@ |
300 | +MONO = @MONO@ |
301 | +MONO_CAIRO_CFLAGS = @MONO_CAIRO_CFLAGS@ |
302 | +MONO_CAIRO_LIBS = @MONO_CAIRO_LIBS@ |
303 | +MONO_CFLAGS = @MONO_CFLAGS@ |
304 | +MONO_LIBS = @MONO_LIBS@ |
305 | +MSGFMT = @MSGFMT@ |
306 | +MSGFMT_OPTS = @MSGFMT_OPTS@ |
307 | +MSGMERGE = @MSGMERGE@ |
308 | +OBJEXT = @OBJEXT@ |
309 | +PACKAGE = @PACKAGE@ |
310 | +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ |
311 | +PACKAGE_NAME = @PACKAGE_NAME@ |
312 | +PACKAGE_STRING = @PACKAGE_STRING@ |
313 | +PACKAGE_TARNAME = @PACKAGE_TARNAME@ |
314 | +PACKAGE_URL = @PACKAGE_URL@ |
315 | +PACKAGE_VERSION = @PACKAGE_VERSION@ |
316 | +PATH_SEPARATOR = @PATH_SEPARATOR@ |
317 | +PKG_CONFIG = @PKG_CONFIG@ |
318 | +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ |
319 | +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ |
320 | +POFILES = @POFILES@ |
321 | +POSUB = @POSUB@ |
322 | +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ |
323 | +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ |
324 | +SET_MAKE = @SET_MAKE@ |
325 | +SHELL = @SHELL@ |
326 | +STRIP = @STRIP@ |
327 | +USE_NLS = @USE_NLS@ |
328 | +VERSION = @VERSION@ |
329 | +XBUILD = @XBUILD@ |
330 | +XGETTEXT = @XGETTEXT@ |
331 | +abs_builddir = @abs_builddir@ |
332 | +abs_srcdir = @abs_srcdir@ |
333 | +abs_top_builddir = @abs_top_builddir@ |
334 | +abs_top_srcdir = @abs_top_srcdir@ |
335 | +ac_ct_CC = @ac_ct_CC@ |
336 | +am__include = @am__include@ |
337 | +am__leading_dot = @am__leading_dot@ |
338 | +am__quote = @am__quote@ |
339 | +am__tar = @am__tar@ |
340 | +am__untar = @am__untar@ |
341 | +bindir = @bindir@ |
342 | +build_alias = @build_alias@ |
343 | +builddir = @builddir@ |
344 | +datadir = @datadir@ |
345 | +datarootdir = @datarootdir@ |
346 | +docdir = @docdir@ |
347 | +dvidir = @dvidir@ |
348 | +exec_prefix = @exec_prefix@ |
349 | +host_alias = @host_alias@ |
350 | +htmldir = @htmldir@ |
351 | +includedir = @includedir@ |
352 | +infodir = @infodir@ |
353 | +install_sh = @install_sh@ |
354 | +libdir = @libdir@ |
355 | +libexecdir = @libexecdir@ |
356 | +localedir = @localedir@ |
357 | +localstatedir = @localstatedir@ |
358 | +mandir = @mandir@ |
359 | +mkdir_p = @mkdir_p@ |
360 | +oldincludedir = @oldincludedir@ |
361 | +pdfdir = @pdfdir@ |
362 | +pintalocaledir = @pintalocaledir@ |
363 | +prefix = @prefix@ |
364 | +program_transform_name = @program_transform_name@ |
365 | +psdir = @psdir@ |
366 | +sbindir = @sbindir@ |
367 | +sharedstatedir = @sharedstatedir@ |
368 | +srcdir = @srcdir@ |
369 | +sysconfdir = @sysconfdir@ |
370 | +target_alias = @target_alias@ |
371 | +top_build_prefix = @top_build_prefix@ |
372 | +top_builddir = @top_builddir@ |
373 | +top_srcdir = @top_srcdir@ |
374 | +SUBDIRS = xdg |
375 | +BINDIR = $(srcdir)/bin |
376 | +PINTA_ASSEMBLY_PC = $(srcdir)/$(PACKAGE_NAME).pc |
377 | +BINFILES = \ |
378 | + $(BINDIR)/Pinta.exe \ |
379 | + $(BINDIR)/Pinta.Core.dll \ |
380 | + $(BINDIR)/Pinta.Gui.Widgets.dll \ |
381 | + $(BINDIR)/Pinta.Resources.dll \ |
382 | + $(BINDIR)/Pinta.Effects.dll \ |
383 | + $(BINDIR)/Pinta.Tools.dll |
384 | + |
385 | +RELEASE_FILE = $(PACKAGE)-$(VERSION) |
386 | + |
387 | +#magic automake variables |
388 | +pkgconfigdir = $(libdir)/pkgconfig |
389 | +pkgconfig_DATA = $(PINTA_ASSEMBLY_PC) |
390 | +EXTRA_DIST = Pinta Pinta.Core Pinta.Effects Pinta.Gui.Widgets Pinta.Resources Pinta.Tools po xdg license-mit.txt \ |
391 | + license-pdn.txt todo.txt Pinta.sln Pinta.Install.proj pinta.pc.in readme.md intltool-extract.in \ |
392 | + intltool-merge.in intltool-update.in |
393 | + |
394 | +CLEANFILES = \ |
395 | + intltool-extract \ |
396 | + intltool-update \ |
397 | + intltool-merge |
398 | + |
399 | +DISTCLEANFILES = intltool-extract \ |
400 | + intltool-merge \ |
401 | + intltool-update \ |
402 | + po/.intltool-merge-cache |
403 | + |
404 | +all: all-recursive |
405 | + |
406 | +.SUFFIXES: |
407 | +am--refresh: |
408 | + @: |
409 | +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) |
410 | + @for dep in $?; do \ |
411 | + case '$(am__configure_deps)' in \ |
412 | + *$$dep*) \ |
413 | + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ |
414 | + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ |
415 | + && exit 0; \ |
416 | + exit 1;; \ |
417 | + esac; \ |
418 | + done; \ |
419 | + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ |
420 | + $(am__cd) $(top_srcdir) && \ |
421 | + $(AUTOMAKE) --foreign Makefile |
422 | +.PRECIOUS: Makefile |
423 | +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
424 | + @case '$?' in \ |
425 | + *config.status*) \ |
426 | + echo ' $(SHELL) ./config.status'; \ |
427 | + $(SHELL) ./config.status;; \ |
428 | + *) \ |
429 | + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ |
430 | + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ |
431 | + esac; |
432 | + |
433 | +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) |
434 | + $(SHELL) ./config.status --recheck |
435 | + |
436 | +$(top_srcdir)/configure: $(am__configure_deps) |
437 | + $(am__cd) $(srcdir) && $(AUTOCONF) |
438 | +$(ACLOCAL_M4): $(am__aclocal_m4_deps) |
439 | + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) |
440 | +$(am__aclocal_m4_deps): |
441 | +pinta.pc: $(top_builddir)/config.status $(srcdir)/pinta.pc.in |
442 | + cd $(top_builddir) && $(SHELL) ./config.status $@ |
443 | +pinta: $(top_builddir)/config.status $(srcdir)/pinta.in |
444 | + cd $(top_builddir) && $(SHELL) ./config.status $@ |
445 | +install-pkgconfigDATA: $(pkgconfig_DATA) |
446 | + @$(NORMAL_INSTALL) |
447 | + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" |
448 | + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ |
449 | + for p in $$list; do \ |
450 | + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ |
451 | + echo "$$d$$p"; \ |
452 | + done | $(am__base_list) | \ |
453 | + while read files; do \ |
454 | + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ |
455 | + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ |
456 | + done |
457 | + |
458 | +uninstall-pkgconfigDATA: |
459 | + @$(NORMAL_UNINSTALL) |
460 | + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ |
461 | + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ |
462 | + test -n "$$files" || exit 0; \ |
463 | + echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ |
464 | + cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files |
465 | + |
466 | +# This directory's subdirectories are mostly independent; you can cd |
467 | +# into them and run `make' without going through this Makefile. |
468 | +# To change the values of `make' variables: instead of editing Makefiles, |
469 | +# (1) if the variable is set in `config.status', edit `config.status' |
470 | +# (which will cause the Makefiles to be regenerated when you run `make'); |
471 | +# (2) otherwise, pass the desired values on the `make' command line. |
472 | +$(RECURSIVE_TARGETS): |
473 | + @fail= failcom='exit 1'; \ |
474 | + for f in x $$MAKEFLAGS; do \ |
475 | + case $$f in \ |
476 | + *=* | --[!k]*);; \ |
477 | + *k*) failcom='fail=yes';; \ |
478 | + esac; \ |
479 | + done; \ |
480 | + dot_seen=no; \ |
481 | + target=`echo $@ | sed s/-recursive//`; \ |
482 | + list='$(SUBDIRS)'; for subdir in $$list; do \ |
483 | + echo "Making $$target in $$subdir"; \ |
484 | + if test "$$subdir" = "."; then \ |
485 | + dot_seen=yes; \ |
486 | + local_target="$$target-am"; \ |
487 | + else \ |
488 | + local_target="$$target"; \ |
489 | + fi; \ |
490 | + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ |
491 | + || eval $$failcom; \ |
492 | + done; \ |
493 | + if test "$$dot_seen" = "no"; then \ |
494 | + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ |
495 | + fi; test -z "$$fail" |
496 | + |
497 | +$(RECURSIVE_CLEAN_TARGETS): |
498 | + @fail= failcom='exit 1'; \ |
499 | + for f in x $$MAKEFLAGS; do \ |
500 | + case $$f in \ |
501 | + *=* | --[!k]*);; \ |
502 | + *k*) failcom='fail=yes';; \ |
503 | + esac; \ |
504 | + done; \ |
505 | + dot_seen=no; \ |
506 | + case "$@" in \ |
507 | + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ |
508 | + *) list='$(SUBDIRS)' ;; \ |
509 | + esac; \ |
510 | + rev=''; for subdir in $$list; do \ |
511 | + if test "$$subdir" = "."; then :; else \ |
512 | + rev="$$subdir $$rev"; \ |
513 | + fi; \ |
514 | + done; \ |
515 | + rev="$$rev ."; \ |
516 | + target=`echo $@ | sed s/-recursive//`; \ |
517 | + for subdir in $$rev; do \ |
518 | + echo "Making $$target in $$subdir"; \ |
519 | + if test "$$subdir" = "."; then \ |
520 | + local_target="$$target-am"; \ |
521 | + else \ |
522 | + local_target="$$target"; \ |
523 | + fi; \ |
524 | + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ |
525 | + || eval $$failcom; \ |
526 | + done && test -z "$$fail" |
527 | +tags-recursive: |
528 | + list='$(SUBDIRS)'; for subdir in $$list; do \ |
529 | + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ |
530 | + done |
531 | +ctags-recursive: |
532 | + list='$(SUBDIRS)'; for subdir in $$list; do \ |
533 | + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ |
534 | + done |
535 | + |
536 | +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) |
537 | + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
538 | + unique=`for i in $$list; do \ |
539 | + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
540 | + done | \ |
541 | + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ |
542 | + END { if (nonempty) { for (i in files) print i; }; }'`; \ |
543 | + mkid -fID $$unique |
544 | +tags: TAGS |
545 | + |
546 | +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
547 | + $(TAGS_FILES) $(LISP) |
548 | + set x; \ |
549 | + here=`pwd`; \ |
550 | + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ |
551 | + include_option=--etags-include; \ |
552 | + empty_fix=.; \ |
553 | + else \ |
554 | + include_option=--include; \ |
555 | + empty_fix=; \ |
556 | + fi; \ |
557 | + list='$(SUBDIRS)'; for subdir in $$list; do \ |
558 | + if test "$$subdir" = .; then :; else \ |
559 | + test ! -f $$subdir/TAGS || \ |
560 | + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ |
561 | + fi; \ |
562 | + done; \ |
563 | + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
564 | + unique=`for i in $$list; do \ |
565 | + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
566 | + done | \ |
567 | + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ |
568 | + END { if (nonempty) { for (i in files) print i; }; }'`; \ |
569 | + shift; \ |
570 | + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ |
571 | + test -n "$$unique" || unique=$$empty_fix; \ |
572 | + if test $$# -gt 0; then \ |
573 | + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
574 | + "$$@" $$unique; \ |
575 | + else \ |
576 | + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
577 | + $$unique; \ |
578 | + fi; \ |
579 | + fi |
580 | +ctags: CTAGS |
581 | +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
582 | + $(TAGS_FILES) $(LISP) |
583 | + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
584 | + unique=`for i in $$list; do \ |
585 | + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
586 | + done | \ |
587 | + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ |
588 | + END { if (nonempty) { for (i in files) print i; }; }'`; \ |
589 | + test -z "$(CTAGS_ARGS)$$unique" \ |
590 | + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ |
591 | + $$unique |
592 | + |
593 | +GTAGS: |
594 | + here=`$(am__cd) $(top_builddir) && pwd` \ |
595 | + && $(am__cd) $(top_srcdir) \ |
596 | + && gtags -i $(GTAGS_ARGS) "$$here" |
597 | + |
598 | +distclean-tags: |
599 | + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
600 | + |
601 | +distdir: $(DISTFILES) |
602 | + $(am__remove_distdir) |
603 | + test -d "$(distdir)" || mkdir "$(distdir)" |
604 | + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ |
605 | + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ |
606 | + list='$(DISTFILES)'; \ |
607 | + dist_files=`for file in $$list; do echo $$file; done | \ |
608 | + sed -e "s|^$$srcdirstrip/||;t" \ |
609 | + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ |
610 | + case $$dist_files in \ |
611 | + */*) $(MKDIR_P) `echo "$$dist_files" | \ |
612 | + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ |
613 | + sort -u` ;; \ |
614 | + esac; \ |
615 | + for file in $$dist_files; do \ |
616 | + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ |
617 | + if test -d $$d/$$file; then \ |
618 | + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ |
619 | + if test -d "$(distdir)/$$file"; then \ |
620 | + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ |
621 | + fi; \ |
622 | + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ |
623 | + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ |
624 | + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ |
625 | + fi; \ |
626 | + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ |
627 | + else \ |
628 | + test -f "$(distdir)/$$file" \ |
629 | + || cp -p $$d/$$file "$(distdir)/$$file" \ |
630 | + || exit 1; \ |
631 | + fi; \ |
632 | + done |
633 | + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ |
634 | + if test "$$subdir" = .; then :; else \ |
635 | + test -d "$(distdir)/$$subdir" \ |
636 | + || $(MKDIR_P) "$(distdir)/$$subdir" \ |
637 | + || exit 1; \ |
638 | + fi; \ |
639 | + done |
640 | + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ |
641 | + if test "$$subdir" = .; then :; else \ |
642 | + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ |
643 | + $(am__relativize); \ |
644 | + new_distdir=$$reldir; \ |
645 | + dir1=$$subdir; dir2="$(top_distdir)"; \ |
646 | + $(am__relativize); \ |
647 | + new_top_distdir=$$reldir; \ |
648 | + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ |
649 | + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ |
650 | + ($(am__cd) $$subdir && \ |
651 | + $(MAKE) $(AM_MAKEFLAGS) \ |
652 | + top_distdir="$$new_top_distdir" \ |
653 | + distdir="$$new_distdir" \ |
654 | + am__remove_distdir=: \ |
655 | + am__skip_length_check=: \ |
656 | + am__skip_mode_fix=: \ |
657 | + distdir) \ |
658 | + || exit 1; \ |
659 | + fi; \ |
660 | + done |
661 | + -test -n "$(am__skip_mode_fix)" \ |
662 | + || find "$(distdir)" -type d ! -perm -755 \ |
663 | + -exec chmod u+rwx,go+rx {} \; -o \ |
664 | + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ |
665 | + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ |
666 | + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ |
667 | + || chmod -R a+r "$(distdir)" |
668 | +dist-gzip: distdir |
669 | + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz |
670 | + $(am__remove_distdir) |
671 | + |
672 | +dist-bzip2: distdir |
673 | + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 |
674 | + $(am__remove_distdir) |
675 | + |
676 | +dist-lzma: distdir |
677 | + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma |
678 | + $(am__remove_distdir) |
679 | + |
680 | +dist-xz: distdir |
681 | + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz |
682 | + $(am__remove_distdir) |
683 | + |
684 | +dist-tarZ: distdir |
685 | + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z |
686 | + $(am__remove_distdir) |
687 | + |
688 | +dist-shar: distdir |
689 | + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz |
690 | + $(am__remove_distdir) |
691 | + |
692 | +dist-zip: distdir |
693 | + -rm -f $(distdir).zip |
694 | + zip -rq $(distdir).zip $(distdir) |
695 | + $(am__remove_distdir) |
696 | + |
697 | +dist dist-all: distdir |
698 | + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz |
699 | + $(am__remove_distdir) |
700 | + |
701 | +# This target untars the dist file and tries a VPATH configuration. Then |
702 | +# it guarantees that the distribution is self-contained by making another |
703 | +# tarfile. |
704 | +distcheck: dist |
705 | + case '$(DIST_ARCHIVES)' in \ |
706 | + *.tar.gz*) \ |
707 | + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ |
708 | + *.tar.bz2*) \ |
709 | + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ |
710 | + *.tar.lzma*) \ |
711 | + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ |
712 | + *.tar.xz*) \ |
713 | + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ |
714 | + *.tar.Z*) \ |
715 | + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ |
716 | + *.shar.gz*) \ |
717 | + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ |
718 | + *.zip*) \ |
719 | + unzip $(distdir).zip ;;\ |
720 | + esac |
721 | + chmod -R a-w $(distdir); chmod a+w $(distdir) |
722 | + mkdir $(distdir)/_build |
723 | + mkdir $(distdir)/_inst |
724 | + chmod a-w $(distdir) |
725 | + test -d $(distdir)/_build || exit 0; \ |
726 | + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ |
727 | + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ |
728 | + && am__cwd=`pwd` \ |
729 | + && $(am__cd) $(distdir)/_build \ |
730 | + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ |
731 | + $(DISTCHECK_CONFIGURE_FLAGS) \ |
732 | + && $(MAKE) $(AM_MAKEFLAGS) \ |
733 | + && $(MAKE) $(AM_MAKEFLAGS) dvi \ |
734 | + && $(MAKE) $(AM_MAKEFLAGS) check \ |
735 | + && $(MAKE) $(AM_MAKEFLAGS) install \ |
736 | + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ |
737 | + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ |
738 | + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ |
739 | + distuninstallcheck \ |
740 | + && chmod -R a-w "$$dc_install_base" \ |
741 | + && ({ \ |
742 | + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ |
743 | + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ |
744 | + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ |
745 | + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ |
746 | + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ |
747 | + } || { rm -rf "$$dc_destdir"; exit 1; }) \ |
748 | + && rm -rf "$$dc_destdir" \ |
749 | + && $(MAKE) $(AM_MAKEFLAGS) dist \ |
750 | + && rm -rf $(DIST_ARCHIVES) \ |
751 | + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ |
752 | + && cd "$$am__cwd" \ |
753 | + || exit 1 |
754 | + $(am__remove_distdir) |
755 | + @(echo "$(distdir) archives ready for distribution: "; \ |
756 | + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ |
757 | + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' |
758 | +distuninstallcheck: |
759 | + @$(am__cd) '$(distuninstallcheck_dir)' \ |
760 | + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ |
761 | + || { echo "ERROR: files left after uninstall:" ; \ |
762 | + if test -n "$(DESTDIR)"; then \ |
763 | + echo " (check DESTDIR support)"; \ |
764 | + fi ; \ |
765 | + $(distuninstallcheck_listfiles) ; \ |
766 | + exit 1; } >&2 |
767 | +distcleancheck: distclean |
768 | + @if test '$(srcdir)' = . ; then \ |
769 | + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ |
770 | + exit 1 ; \ |
771 | + fi |
772 | + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ |
773 | + || { echo "ERROR: files left in build directory after distclean:" ; \ |
774 | + $(distcleancheck_listfiles) ; \ |
775 | + exit 1; } >&2 |
776 | +check-am: all-am |
777 | +check: check-recursive |
778 | +all-am: Makefile $(DATA) |
779 | +installdirs: installdirs-recursive |
780 | +installdirs-am: |
781 | + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ |
782 | + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
783 | + done |
784 | +install-exec: install-exec-recursive |
785 | +install-data: install-data-recursive |
786 | + |
787 | +install-am: all-am |
788 | + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
789 | + |
790 | +installcheck: installcheck-recursive |
791 | +install-strip: |
792 | + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ |
793 | + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ |
794 | + `test -z '$(STRIP)' || \ |
795 | + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install |
796 | +mostlyclean-generic: |
797 | + |
798 | +clean-generic: |
799 | + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) |
800 | + |
801 | +distclean-generic: |
802 | + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) |
803 | + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) |
804 | + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) |
805 | + |
806 | +maintainer-clean-generic: |
807 | + @echo "This command is intended for maintainers to use" |
808 | + @echo "it deletes files that may require special tools to rebuild." |
809 | +clean-am: clean-generic mostlyclean-am |
810 | + |
811 | +distclean-am: clean-am distclean-generic distclean-tags |
812 | + |
813 | +dvi: dvi-recursive |
814 | + |
815 | +dvi-am: |
816 | + |
817 | +html: html-recursive |
818 | + |
819 | +html-am: |
820 | + |
821 | +info: info-recursive |
822 | + |
823 | +info-am: |
824 | + |
825 | +install-data-am: install-pkgconfigDATA |
826 | + |
827 | +install-dvi: install-dvi-recursive |
828 | + |
829 | +install-dvi-am: |
830 | + |
831 | +install-exec-am: |
832 | + |
833 | +install-html: install-html-recursive |
834 | + |
835 | +install-html-am: |
836 | + |
837 | +install-info: install-info-recursive |
838 | + |
839 | +install-info-am: |
840 | + |
841 | +install-man: |
842 | + |
843 | +install-pdf: install-pdf-recursive |
844 | + |
845 | +install-pdf-am: |
846 | + |
847 | +install-ps: install-ps-recursive |
848 | + |
849 | +install-ps-am: |
850 | + |
851 | +installcheck-am: |
852 | + |
853 | +maintainer-clean: maintainer-clean-recursive |
854 | + -rm -f $(am__CONFIG_DISTCLEAN_FILES) |
855 | + -rm -rf $(top_srcdir)/autom4te.cache |
856 | + -rm -f Makefile |
857 | +maintainer-clean-am: distclean-am maintainer-clean-generic |
858 | + |
859 | +mostlyclean: mostlyclean-recursive |
860 | + |
861 | +mostlyclean-am: mostlyclean-generic |
862 | + |
863 | +pdf: pdf-recursive |
864 | + |
865 | +pdf-am: |
866 | + |
867 | +ps: ps-recursive |
868 | + |
869 | +ps-am: |
870 | + |
871 | +uninstall-am: uninstall-pkgconfigDATA |
872 | + |
873 | +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ |
874 | + install-am install-strip tags-recursive |
875 | + |
876 | +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ |
877 | + all all-am am--refresh check check-am clean clean-generic \ |
878 | + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ |
879 | + dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ |
880 | + distclean distclean-generic distclean-tags distcleancheck \ |
881 | + distdir distuninstallcheck dvi dvi-am html html-am info \ |
882 | + info-am install install-am install-data install-data-am \ |
883 | + install-dvi install-dvi-am install-exec install-exec-am \ |
884 | + install-html install-html-am install-info install-info-am \ |
885 | + install-man install-pdf install-pdf-am install-pkgconfigDATA \ |
886 | + install-ps install-ps-am install-strip installcheck \ |
887 | + installcheck-am installdirs installdirs-am maintainer-clean \ |
888 | + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ |
889 | + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ |
890 | + uninstall-pkgconfigDATA |
891 | + |
892 | + |
893 | +#end |
894 | + |
895 | +# target: all - Default target: build |
896 | +all: build |
897 | + |
898 | +# target: run - Launch the uninstalled copy |
899 | +run: |
900 | + $(MONO) bin/Pinta.exe |
901 | + |
902 | +# target: help - Display callable targets. |
903 | +help: |
904 | + egrep "^# target:" Makefile | sed 's/^# target:/make/' |
905 | + |
906 | +# target: build - Build Pinta. |
907 | +build: Pinta.sln |
908 | + cd $(srcdir) && $(XBUILD) Pinta.sln |
909 | + cd $(srcdir) && $(XBUILD) Pinta.Install.proj /target:CompileTranslations |
910 | + |
911 | +# target: list - List source files. |
912 | +list: |
913 | + if ! git status > /dev/null 2> /dev/null ;\ |
914 | + then \ |
915 | + find . -type f -name *.cs | sed 's|./||' ;\ |
916 | + else \ |
917 | + git ls-files | grep '\.cs' ;\ |
918 | + fi |
919 | + |
920 | +#target: updatepot - update the messages.pot file |
921 | +updatepot: build |
922 | + find . -type f -name *.cs | sed 's|./||' > files.list |
923 | + grep -v System.ComponentModel.Composition files.list > files2.list |
924 | + xgettext --from-code=UTF-8 -f files2.list -o po/messages.pot |
925 | + cat po/messages.in >> po/messages.pot |
926 | + rm files.list |
927 | + rm files2.list |
928 | + |
929 | +# target: clean - Default clean command: cleanobj and cleanbin |
930 | +clean: cleanobj cleanbin |
931 | + |
932 | +# target: distclean - Removes configure files. |
933 | +distclean: clean |
934 | + rm -f Makefile pinta config.status config.cache config.log configure.lineno config.status.lineno pinta.pc |
935 | + |
936 | +# target: cleanall - Removes build files. |
937 | +cleanall: distclean |
938 | + rm -rf autom4te.cache |
939 | + rm -f configure aclocal.m4 missing install-sh Makefile.in |
940 | + |
941 | +# target: cleanbin - Removes built files. |
942 | +cleanbin: |
943 | + rm -rvf $(BINDIR)/* |
944 | + |
945 | +# target: cleanobj - Removes temporary build files. |
946 | +cleanobj: |
947 | + find $(srcdir)/ -type d -name obj | xargs rm -rvf |
948 | + |
949 | +# target: install - Installs Pinta. |
950 | +install: pinta $(BINFILES) |
951 | + cd $(srcdir) && $(XBUILD) /target:Install /property:InstallPrefix=$(DESTDIR)$(prefix) \ |
952 | + /property:BinDir=$(DESTDIR)$(bindir) /property:LibDir=$(DESTDIR)$(libdir) \ |
953 | + /property:DataRootDir=$(DESTDIR)$(datarootdir) /property:ManDir=$(DESTDIR)$(mandir) \ |
954 | + /property:LocaleDir=$(DESTDIR)$(localedir) Pinta.Install.proj |
955 | + $(INSTALL_SCRIPT) pinta $(DESTDIR)$(bindir)/$(PACKAGE) |
956 | + |
957 | +# target: uninstall - Uninstalls Pinta. |
958 | +uninstall: |
959 | + $(XBUILD) /target:Uninstall /property:InstallPrefix=$(DESTDIR)$(prefix) Pinta.Install.proj |
960 | + |
961 | +# target: release - Default release type: releasetar |
962 | +release: releasetar |
963 | + |
964 | +# target: releasetar - Make a release tarball. |
965 | +releasetar: $(BINFILES) |
966 | + cd $(BINDIR) && tar -czf ../$(RELEASE_FILE).tgz --exclude=*mdb * |
967 | + |
968 | +# target: releasezip - Make a release zip file. |
969 | +releasezip: $(BINFILES) |
970 | + cd $(BINDIR) && zip -r ../$(RELEASE_FILE).zip * -x "*.mdb" |
971 | + |
972 | +.PHONY: install uninstall cleanall cleanbin cleanobj release releasetar releasezip |
973 | + |
974 | +# Tell versions [3.59,3.63) of GNU make to not export all variables. |
975 | +# Otherwise a system limit (for SysV at least) may be exceeded. |
976 | +.NOEXPORT: |
977 | |
978 | === added directory 'Pinta' |
979 | === added directory 'Pinta.Core' |
980 | === renamed directory 'Pinta.Core' => 'Pinta.Core.moved' |
981 | === added file 'Pinta.Core/.gitignore' |
982 | --- Pinta.Core/.gitignore 1970-01-01 00:00:00 +0000 |
983 | +++ Pinta.Core/.gitignore 2013-01-23 15:01:21 +0000 |
984 | @@ -0,0 +1,3 @@ |
985 | +/bin/ |
986 | +/obj/ |
987 | +*.user |
988 | \ No newline at end of file |
989 | |
990 | === added directory 'Pinta.Core/Actions' |
991 | === added file 'Pinta.Core/Actions/AdjustmentsActions.cs' |
992 | --- Pinta.Core/Actions/AdjustmentsActions.cs 1970-01-01 00:00:00 +0000 |
993 | +++ Pinta.Core/Actions/AdjustmentsActions.cs 2013-01-23 15:01:21 +0000 |
994 | @@ -0,0 +1,57 @@ |
995 | +// |
996 | +// AdjustmentsActions.cs |
997 | +// |
998 | +// Author: |
999 | +// Jonathan Pobst <monkey@jpobst.com> |
1000 | +// |
1001 | +// Copyright (c) 2010 Jonathan Pobst |
1002 | +// |
1003 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
1004 | +// of this software and associated documentation files (the "Software"), to deal |
1005 | +// in the Software without restriction, including without limitation the rights |
1006 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1007 | +// copies of the Software, and to permit persons to whom the Software is |
1008 | +// furnished to do so, subject to the following conditions: |
1009 | +// |
1010 | +// The above copyright notice and this permission notice shall be included in |
1011 | +// all copies or substantial portions of the Software. |
1012 | +// |
1013 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1014 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1015 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1016 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1017 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1018 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1019 | +// THE SOFTWARE. |
1020 | + |
1021 | +using System; |
1022 | +using System.Collections.Generic; |
1023 | +using System.Threading; |
1024 | +using Cairo; |
1025 | + |
1026 | +namespace Pinta.Core |
1027 | +{ |
1028 | + public class AdjustmentsActions |
1029 | + { |
1030 | + public List<Gtk.Action> Actions { get; private set; } |
1031 | + |
1032 | + public AdjustmentsActions () |
1033 | + { |
1034 | + Actions = new List<Gtk.Action> (); |
1035 | + } |
1036 | + |
1037 | + #region Initialization |
1038 | + public void CreateMainMenu (Gtk.Menu menu) |
1039 | + { |
1040 | + } |
1041 | + #endregion |
1042 | + |
1043 | + #region Public Methods |
1044 | + public void ToggleActionsSensitive (bool sensitive) |
1045 | + { |
1046 | + foreach (Gtk.Action a in Actions) |
1047 | + a.Sensitive = sensitive; |
1048 | + } |
1049 | + #endregion |
1050 | + } |
1051 | +} |
1052 | |
1053 | === added file 'Pinta.Core/Actions/EditActions.cs' |
1054 | --- Pinta.Core/Actions/EditActions.cs 1970-01-01 00:00:00 +0000 |
1055 | +++ Pinta.Core/Actions/EditActions.cs 2013-01-23 15:01:21 +0000 |
1056 | @@ -0,0 +1,433 @@ |
1057 | +// |
1058 | +// EditActions.cs |
1059 | +// |
1060 | +// Author: |
1061 | +// Jonathan Pobst <monkey@jpobst.com> |
1062 | +// |
1063 | +// Copyright (c) 2010 Jonathan Pobst |
1064 | +// |
1065 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
1066 | +// of this software and associated documentation files (the "Software"), to deal |
1067 | +// in the Software without restriction, including without limitation the rights |
1068 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1069 | +// copies of the Software, and to permit persons to whom the Software is |
1070 | +// furnished to do so, subject to the following conditions: |
1071 | +// |
1072 | +// The above copyright notice and this permission notice shall be included in |
1073 | +// all copies or substantial portions of the Software. |
1074 | +// |
1075 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1076 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1077 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1078 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1079 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1080 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1081 | +// THE SOFTWARE. |
1082 | + |
1083 | +using System; |
1084 | +using Gtk; |
1085 | +using Cairo; |
1086 | +using Mono.Unix; |
1087 | + |
1088 | +namespace Pinta.Core |
1089 | +{ |
1090 | + public class EditActions |
1091 | + { |
1092 | + public Gtk.Action Undo { get; private set; } |
1093 | + public Gtk.Action Redo { get; private set; } |
1094 | + public Gtk.Action Cut { get; private set; } |
1095 | + public Gtk.Action Copy { get; private set; } |
1096 | + public Gtk.Action Paste { get; private set; } |
1097 | + public Gtk.Action PasteIntoNewLayer { get; private set; } |
1098 | + public Gtk.Action PasteIntoNewImage { get; private set; } |
1099 | + public Gtk.Action EraseSelection { get; private set; } |
1100 | + public Gtk.Action FillSelection { get; private set; } |
1101 | + public Gtk.Action InvertSelection { get; private set; } |
1102 | + public Gtk.Action SelectAll { get; private set; } |
1103 | + public Gtk.Action Deselect { get; private set; } |
1104 | + public Gtk.Action LoadPalette { get; private set; } |
1105 | + public Gtk.Action SavePalette { get; private set; } |
1106 | + public Gtk.Action ResetPalette { get; private set; } |
1107 | + public Gtk.Action ResizePalette { get; private set; } |
1108 | + |
1109 | + private string lastPaletteDir = null; |
1110 | + |
1111 | + public EditActions () |
1112 | + { |
1113 | + Gtk.IconFactory fact = new Gtk.IconFactory (); |
1114 | + fact.Add ("Menu.Edit.Deselect.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Edit.Deselect.png"))); |
1115 | + fact.Add ("Menu.Edit.EraseSelection.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Edit.EraseSelection.png"))); |
1116 | + fact.Add ("Menu.Edit.FillSelection.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Edit.FillSelection.png"))); |
1117 | + fact.Add ("Menu.Edit.InvertSelection.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Edit.InvertSelection.png"))); |
1118 | + fact.Add ("Menu.Edit.SelectAll.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Edit.SelectAll.png"))); |
1119 | + fact.AddDefault (); |
1120 | + |
1121 | + Undo = new Gtk.Action ("Undo", Catalog.GetString ("Undo"), null, Stock.Undo); |
1122 | + Redo = new Gtk.Action ("Redo", Catalog.GetString ("Redo"), null, Stock.Redo); |
1123 | + Cut = new Gtk.Action ("Cut", Catalog.GetString ("Cut"), null, Stock.Cut); |
1124 | + Copy = new Gtk.Action ("Copy", Catalog.GetString ("Copy"), null, Stock.Copy); |
1125 | + Paste = new Gtk.Action ("Paste", Catalog.GetString ("Paste"), null, Stock.Paste); |
1126 | + PasteIntoNewLayer = new Gtk.Action ("PasteIntoNewLayer", Catalog.GetString ("Paste Into New Layer"), null, Stock.Paste); |
1127 | + PasteIntoNewImage = new Gtk.Action ("PasteIntoNewImage", Catalog.GetString ("Paste Into New Image"), null, Stock.Paste); |
1128 | + EraseSelection = new Gtk.Action ("EraseSelection", Catalog.GetString ("Delete Selection"), null, "Menu.Edit.EraseSelection.png"); |
1129 | + FillSelection = new Gtk.Action ("FillSelection", Catalog.GetString ("Fill Selection"), null, "Menu.Edit.FillSelection.png"); |
1130 | + InvertSelection = new Gtk.Action ("InvertSelection", Catalog.GetString ("Invert Selection"), null, "Menu.Edit.InvertSelection.png"); |
1131 | + SelectAll = new Gtk.Action ("SelectAll", Catalog.GetString ("Select All"), null, Stock.SelectAll); |
1132 | + Deselect = new Gtk.Action ("Deselect", Catalog.GetString ("Deselect All"), null, "Menu.Edit.Deselect.png"); |
1133 | + |
1134 | + LoadPalette = new Gtk.Action ("LoadPalette", Catalog.GetString ("Open..."), null, Stock.Open); |
1135 | + SavePalette = new Gtk.Action ("SavePalette", Catalog.GetString ("Save As..."), null, Stock.Save); |
1136 | + ResetPalette = new Gtk.Action ("ResetPalette", Catalog.GetString ("Reset to Default"), null, Stock.RevertToSaved); |
1137 | + ResizePalette = new Gtk.Action ("ResizePalette", Catalog.GetString ("Set Number of Colors"), null, "Menu.Image.Resize.png"); |
1138 | + |
1139 | + Undo.IsImportant = true; |
1140 | + Undo.Sensitive = false; |
1141 | + Redo.Sensitive = false; |
1142 | + InvertSelection.Sensitive = false; |
1143 | + Deselect.Sensitive = false; |
1144 | + EraseSelection.Sensitive = false; |
1145 | + FillSelection.Sensitive = false; |
1146 | + } |
1147 | + |
1148 | + #region Initialization |
1149 | + public void CreateMainMenu (Gtk.Menu menu) |
1150 | + { |
1151 | + menu.Append (Undo.CreateAcceleratedMenuItem (Gdk.Key.Z, Gdk.ModifierType.ControlMask)); |
1152 | + |
1153 | + ImageMenuItem redo = Redo.CreateAcceleratedMenuItem (Gdk.Key.Z, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask); |
1154 | + redo.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.Y, Gdk.ModifierType.ControlMask, AccelFlags.Visible)); |
1155 | + menu.Append (redo); |
1156 | + |
1157 | + menu.AppendSeparator (); |
1158 | + menu.Append (Cut.CreateAcceleratedMenuItem (Gdk.Key.X, Gdk.ModifierType.ControlMask)); |
1159 | + menu.Append (Copy.CreateAcceleratedMenuItem (Gdk.Key.C, Gdk.ModifierType.ControlMask)); |
1160 | + menu.Append (Paste.CreateAcceleratedMenuItem (Gdk.Key.V, Gdk.ModifierType.ControlMask)); |
1161 | + menu.Append (PasteIntoNewLayer.CreateAcceleratedMenuItem (Gdk.Key.V, Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)); |
1162 | + menu.Append (PasteIntoNewImage.CreateAcceleratedMenuItem (Gdk.Key.V, Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.ControlMask)); |
1163 | + |
1164 | + menu.AppendSeparator (); |
1165 | + menu.Append (SelectAll.CreateAcceleratedMenuItem (Gdk.Key.A, Gdk.ModifierType.ControlMask)); |
1166 | + |
1167 | + ImageMenuItem deslect = Deselect.CreateAcceleratedMenuItem (Gdk.Key.A, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask); |
1168 | + deslect.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.D, Gdk.ModifierType.ControlMask, AccelFlags.Visible)); |
1169 | + menu.Append (deslect); |
1170 | + |
1171 | + menu.AppendSeparator (); |
1172 | + menu.Append (EraseSelection.CreateAcceleratedMenuItem (Gdk.Key.Delete, Gdk.ModifierType.None)); |
1173 | + menu.Append (FillSelection.CreateAcceleratedMenuItem (Gdk.Key.BackSpace, Gdk.ModifierType.None)); |
1174 | + //menu.Append (InvertSelection.CreateAcceleratedMenuItem (Gdk.Key.I, Gdk.ModifierType.ControlMask)); |
1175 | + |
1176 | + menu.AppendSeparator (); |
1177 | + Gtk.Action menu_action = new Gtk.Action ("Palette", Mono.Unix.Catalog.GetString ("Palette"), null, null); |
1178 | + Menu palette_menu = (Menu) menu.AppendItem (menu_action.CreateSubMenuItem ()).Submenu; |
1179 | + palette_menu.Append (LoadPalette.CreateMenuItem ()); |
1180 | + palette_menu.Append (SavePalette.CreateMenuItem ()); |
1181 | + palette_menu.Append (ResetPalette.CreateMenuItem ()); |
1182 | + palette_menu.Append (ResizePalette.CreateMenuItem ()); |
1183 | + } |
1184 | + |
1185 | + public void CreateHistoryWindowToolBar (Gtk.Toolbar toolbar) |
1186 | + { |
1187 | + toolbar.AppendItem (Undo.CreateToolBarItem ()); |
1188 | + toolbar.AppendItem (Redo.CreateToolBarItem ()); |
1189 | + } |
1190 | + |
1191 | + public void RegisterHandlers () |
1192 | + { |
1193 | + Deselect.Activated += HandlePintaCoreActionsEditDeselectActivated; |
1194 | + EraseSelection.Activated += HandlePintaCoreActionsEditEraseSelectionActivated; |
1195 | + SelectAll.Activated += HandlePintaCoreActionsEditSelectAllActivated; |
1196 | + FillSelection.Activated += HandlePintaCoreActionsEditFillSelectionActivated; |
1197 | + Paste.Activated += HandlerPintaCoreActionsEditPasteActivated; |
1198 | + Copy.Activated += HandlerPintaCoreActionsEditCopyActivated; |
1199 | + Undo.Activated += HandlerPintaCoreActionsEditUndoActivated; |
1200 | + Redo.Activated += HandlerPintaCoreActionsEditRedoActivated; |
1201 | + Cut.Activated += HandlerPintaCoreActionsEditCutActivated; |
1202 | + LoadPalette.Activated += HandlerPintaCoreActionsEditLoadPaletteActivated; |
1203 | + SavePalette.Activated += HandlerPintaCoreActionsEditSavePaletteActivated; |
1204 | + ResetPalette.Activated += HandlerPintaCoreActionsEditResetPaletteActivated; |
1205 | + |
1206 | + PintaCore.Workspace.ActiveDocumentChanged += WorkspaceActiveDocumentChanged; |
1207 | + } |
1208 | + #endregion |
1209 | + |
1210 | + #region Action Handlers |
1211 | + private void HandlePintaCoreActionsEditFillSelectionActivated (object sender, EventArgs e) |
1212 | + { |
1213 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1214 | + |
1215 | + PintaCore.Tools.Commit (); |
1216 | + |
1217 | + Cairo.ImageSurface old = doc.CurrentLayer.Surface.Clone (); |
1218 | + |
1219 | + using (var g = new Cairo.Context (doc.CurrentLayer.Surface)) { |
1220 | + g.AppendPath (doc.SelectionPath); |
1221 | + g.FillRule = FillRule.EvenOdd; |
1222 | + |
1223 | + g.Color = PintaCore.Palette.PrimaryColor; |
1224 | + g.Fill (); |
1225 | + } |
1226 | + |
1227 | + doc.Workspace.Invalidate (); |
1228 | + doc.History.PushNewItem (new SimpleHistoryItem ("Menu.Edit.FillSelection.png", Catalog.GetString ("Fill Selection"), old, doc.CurrentLayerIndex)); |
1229 | + } |
1230 | + |
1231 | + private void HandlePintaCoreActionsEditSelectAllActivated (object sender, EventArgs e) |
1232 | + { |
1233 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1234 | + |
1235 | + PintaCore.Tools.Commit (); |
1236 | + |
1237 | + SelectionHistoryItem hist = new SelectionHistoryItem (Stock.SelectAll, Catalog.GetString ("Select All")); |
1238 | + hist.TakeSnapshot (); |
1239 | + |
1240 | + doc.ResetSelectionPath (); |
1241 | + doc.ShowSelection = true; |
1242 | + |
1243 | + doc.History.PushNewItem (hist); |
1244 | + doc.Workspace.Invalidate (); |
1245 | + } |
1246 | + |
1247 | + private void HandlePintaCoreActionsEditEraseSelectionActivated (object sender, EventArgs e) |
1248 | + { |
1249 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1250 | + |
1251 | + PintaCore.Tools.Commit (); |
1252 | + |
1253 | + Cairo.ImageSurface old = doc.CurrentLayer.Surface.Clone (); |
1254 | + |
1255 | + using (var g = new Cairo.Context (doc.CurrentLayer.Surface)) { |
1256 | + g.AppendPath (doc.SelectionPath); |
1257 | + g.FillRule = FillRule.EvenOdd; |
1258 | + |
1259 | + g.Operator = Cairo.Operator.Clear; |
1260 | + g.Fill (); |
1261 | + } |
1262 | + |
1263 | + doc.Workspace.Invalidate (); |
1264 | + |
1265 | + if (sender is string && (sender as string) == "Cut") |
1266 | + doc.History.PushNewItem (new SimpleHistoryItem (Stock.Cut, Catalog.GetString ("Cut"), old, doc.CurrentLayerIndex)); |
1267 | + else |
1268 | + doc.History.PushNewItem (new SimpleHistoryItem ("Menu.Edit.EraseSelection.png", Catalog.GetString ("Erase Selection"), old, doc.CurrentLayerIndex)); |
1269 | + } |
1270 | + |
1271 | + private void HandlePintaCoreActionsEditDeselectActivated (object sender, EventArgs e) |
1272 | + { |
1273 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1274 | + |
1275 | + PintaCore.Tools.Commit (); |
1276 | + |
1277 | + SelectionHistoryItem hist = new SelectionHistoryItem ("Menu.Edit.Deselect.png", Catalog.GetString ("Deselect")); |
1278 | + hist.TakeSnapshot (); |
1279 | + |
1280 | + doc.ResetSelectionPath (); |
1281 | + |
1282 | + doc.History.PushNewItem (hist); |
1283 | + doc.Workspace.Invalidate (); |
1284 | + } |
1285 | + |
1286 | + private void HandlerPintaCoreActionsEditPasteActivated (object sender, EventArgs e) |
1287 | + { |
1288 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1289 | + |
1290 | + PintaCore.Tools.Commit (); |
1291 | + |
1292 | + Gtk.Clipboard cb = Gtk.Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false)); |
1293 | + |
1294 | + Path p; |
1295 | + |
1296 | + // Don't dispose this, as we're going to give it to the history |
1297 | + Gdk.Pixbuf image = cb.WaitForImage (); |
1298 | + |
1299 | + if (image == null) |
1300 | + return; |
1301 | + |
1302 | + Gdk.Size canvas_size = PintaCore.Workspace.ImageSize; |
1303 | + |
1304 | + // If the image being pasted is larger than the canvas size, allow the user to optionally resize the canvas |
1305 | + if (image.Width > canvas_size.Width || image.Height > canvas_size.Height) |
1306 | + { |
1307 | + string message = Catalog.GetString ("The image being pasted is larger than the canvas size. What would you like to do?"); |
1308 | + |
1309 | + var enlarge_dialog = new MessageDialog (PintaCore.Chrome.MainWindow, DialogFlags.Modal, MessageType.Question, ButtonsType.None, message); |
1310 | + enlarge_dialog.AddButton (Catalog.GetString ("Expand canvas"), ResponseType.Accept); |
1311 | + enlarge_dialog.AddButton (Catalog.GetString ("Don't change canvas size"), ResponseType.Reject); |
1312 | + enlarge_dialog.AddButton (Stock.Cancel, ResponseType.Cancel); |
1313 | + enlarge_dialog.DefaultResponse = ResponseType.Accept; |
1314 | + |
1315 | + ResponseType response = (ResponseType)enlarge_dialog.Run (); |
1316 | + enlarge_dialog.Destroy (); |
1317 | + |
1318 | + if (response == ResponseType.Accept) |
1319 | + { |
1320 | + PintaCore.Workspace.ResizeCanvas (image.Width, image.Height, Pinta.Core.Anchor.Center); |
1321 | + PintaCore.Actions.View.UpdateCanvasScale (); |
1322 | + } |
1323 | + else if (response == ResponseType.Cancel || response == ResponseType.DeleteEvent) |
1324 | + { |
1325 | + return; |
1326 | + } |
1327 | + } |
1328 | + |
1329 | + // Copy the paste to the temp layer |
1330 | + doc.CreateSelectionLayer (); |
1331 | + doc.ShowSelectionLayer = true; |
1332 | + |
1333 | + using (Cairo.Context g = new Cairo.Context (doc.SelectionLayer.Surface)) { |
1334 | + g.DrawPixbuf (image, new Cairo.Point (0, 0)); |
1335 | + p = g.CreateRectanglePath (new Rectangle (0, 0, image.Width, image.Height)); |
1336 | + } |
1337 | + |
1338 | + PintaCore.Tools.SetCurrentTool (Catalog.GetString ("Move Selected Pixels")); |
1339 | + |
1340 | + Path old_path = doc.SelectionPath; |
1341 | + bool old_show_selection = doc.ShowSelection; |
1342 | + |
1343 | + doc.SelectionPath = p; |
1344 | + doc.ShowSelection = true; |
1345 | + |
1346 | + doc.Workspace.Invalidate (); |
1347 | + |
1348 | + doc.History.PushNewItem (new PasteHistoryItem (image, old_path, old_show_selection)); |
1349 | + } |
1350 | + |
1351 | + private void HandlerPintaCoreActionsEditCopyActivated (object sender, EventArgs e) |
1352 | + { |
1353 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1354 | + |
1355 | + PintaCore.Tools.Commit (); |
1356 | + |
1357 | + ImageSurface src = doc.GetClippedLayer (doc.CurrentLayerIndex); |
1358 | + |
1359 | + Gdk.Rectangle rect = doc.GetSelectedBounds (true); |
1360 | + |
1361 | + ImageSurface dest = new ImageSurface (Format.Argb32, rect.Width, rect.Height); |
1362 | + |
1363 | + using (Context g = new Context (dest)) { |
1364 | + g.SetSourceSurface (src, -rect.X, -rect.Y); |
1365 | + g.Paint (); |
1366 | + } |
1367 | + |
1368 | + Gtk.Clipboard cb = Gtk.Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false)); |
1369 | + cb.Image = dest.ToPixbuf (); |
1370 | + |
1371 | + (src as IDisposable).Dispose (); |
1372 | + (dest as IDisposable).Dispose (); |
1373 | + } |
1374 | + |
1375 | + private void HandlerPintaCoreActionsEditCutActivated (object sender, EventArgs e) |
1376 | + { |
1377 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1378 | + |
1379 | + PintaCore.Tools.Commit (); |
1380 | + |
1381 | + // Copy selection |
1382 | + HandlerPintaCoreActionsEditCopyActivated (sender, e); |
1383 | + |
1384 | + // Erase selection |
1385 | + HandlePintaCoreActionsEditEraseSelectionActivated ("Cut", e); |
1386 | + } |
1387 | + |
1388 | + private void HandlerPintaCoreActionsEditUndoActivated (object sender, EventArgs e) |
1389 | + { |
1390 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1391 | + doc.History.Undo (); |
1392 | + } |
1393 | + |
1394 | + private void HandlerPintaCoreActionsEditRedoActivated (object sender, EventArgs e) |
1395 | + { |
1396 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1397 | + doc.History.Redo (); |
1398 | + } |
1399 | + |
1400 | + private void HandlerPintaCoreActionsEditLoadPaletteActivated (object sender, EventArgs e) |
1401 | + { |
1402 | + var fcd = new Gtk.FileChooserDialog (Catalog.GetString ("Open Palette File"), PintaCore.Chrome.MainWindow, |
1403 | + FileChooserAction.Open, Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, |
1404 | + Gtk.Stock.Open, Gtk.ResponseType.Ok); |
1405 | + |
1406 | + FileFilter ff = new FileFilter (); |
1407 | + ff.AddPattern ("*.txt"); |
1408 | + ff.AddPattern ("*.gpl"); |
1409 | + ff.Name = Catalog.GetString ("Palette files (*.txt, *.gpl)"); |
1410 | + fcd.AddFilter (ff); |
1411 | + |
1412 | + FileFilter ff2 = new FileFilter (); |
1413 | + ff2.Name = Catalog.GetString ("All files"); |
1414 | + ff2.AddPattern ("*.*"); |
1415 | + fcd.AddFilter (ff2); |
1416 | + |
1417 | + fcd.AlternativeButtonOrder = new int[] { (int) ResponseType.Ok, (int) ResponseType.Cancel }; |
1418 | + |
1419 | + if (lastPaletteDir != null) |
1420 | + fcd.SetCurrentFolder (lastPaletteDir); |
1421 | + |
1422 | + int response = fcd.Run (); |
1423 | + |
1424 | + if (response == (int) Gtk.ResponseType.Ok) { |
1425 | + try { |
1426 | + lastPaletteDir = fcd.CurrentFolder; |
1427 | + PintaCore.Palette.CurrentPalette.Load (fcd.Filename); |
1428 | + } catch { |
1429 | + MessageDialog md = new MessageDialog (PintaCore.Chrome.MainWindow, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, Catalog.GetString ("Could not open palette file: {0}.\nPlease verify that you are trying to open a valid GIMP or Paint.NET palette."), fcd.Filename); |
1430 | + md.Title = Catalog.GetString ("Error"); |
1431 | + |
1432 | + md.Run (); |
1433 | + md.Destroy (); |
1434 | + } |
1435 | + } |
1436 | + |
1437 | + fcd.Destroy (); |
1438 | + } |
1439 | + |
1440 | + private void HandlerPintaCoreActionsEditSavePaletteActivated (object sender, EventArgs e) |
1441 | + { |
1442 | + var fcd = new Gtk.FileChooserDialog (Catalog.GetString ("Save Palette File"), PintaCore.Chrome.MainWindow, |
1443 | + FileChooserAction.Save, Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, |
1444 | + Gtk.Stock.Save, Gtk.ResponseType.Ok); |
1445 | + |
1446 | + FileFilter ffPDN = new FileFilter (); |
1447 | + ffPDN.AddPattern ("*.txt"); |
1448 | + ffPDN.Name = Catalog.GetString ("Paint.NET palette (*.txt)"); |
1449 | + fcd.AddFilter (ffPDN); |
1450 | + |
1451 | + FileFilter ffGIMP = new FileFilter (); |
1452 | + ffGIMP.AddPattern ("*.gpl"); |
1453 | + ffGIMP.Name = Catalog.GetString ("GIMP palette (*.gpl)"); |
1454 | + fcd.AddFilter (ffGIMP); |
1455 | + |
1456 | + fcd.AlternativeButtonOrder = new int[] { (int) ResponseType.Ok, (int) ResponseType.Cancel }; |
1457 | + |
1458 | + if (lastPaletteDir != null) |
1459 | + fcd.SetCurrentFolder (lastPaletteDir); |
1460 | + |
1461 | + int response = fcd.Run (); |
1462 | + |
1463 | + if (response == (int) Gtk.ResponseType.Ok) { |
1464 | + Palette.FileFormat format = (fcd.Filter == ffPDN) ? Palette.FileFormat.PDN : Palette.FileFormat.GIMP; |
1465 | + PintaCore.Palette.CurrentPalette.Save (fcd.Filename, format); |
1466 | + } |
1467 | + |
1468 | + fcd.Destroy (); |
1469 | + } |
1470 | + |
1471 | + private void HandlerPintaCoreActionsEditResetPaletteActivated (object sender, EventArgs e) |
1472 | + { |
1473 | + PintaCore.Palette.CurrentPalette.LoadDefault (); |
1474 | + } |
1475 | + |
1476 | + private void WorkspaceActiveDocumentChanged (object sender, EventArgs e) |
1477 | + { |
1478 | + if (!PintaCore.Workspace.HasOpenDocuments) { |
1479 | + Undo.Sensitive = false; |
1480 | + Redo.Sensitive = false; |
1481 | + return; |
1482 | + } |
1483 | + |
1484 | + Redo.Sensitive = PintaCore.Workspace.ActiveWorkspace.History.CanRedo; |
1485 | + Undo.Sensitive = PintaCore.Workspace.ActiveWorkspace.History.CanUndo; |
1486 | + } |
1487 | + #endregion |
1488 | + } |
1489 | +} |
1490 | |
1491 | === added file 'Pinta.Core/Actions/EffectsActions.cs' |
1492 | --- Pinta.Core/Actions/EffectsActions.cs 1970-01-01 00:00:00 +0000 |
1493 | +++ Pinta.Core/Actions/EffectsActions.cs 2013-01-23 15:01:21 +0000 |
1494 | @@ -0,0 +1,93 @@ |
1495 | +// |
1496 | +// EffectsActions.cs |
1497 | +// |
1498 | +// Author: |
1499 | +// Jonathan Pobst <monkey@jpobst.com> |
1500 | +// |
1501 | +// Copyright (c) 2010 Jonathan Pobst |
1502 | +// |
1503 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
1504 | +// of this software and associated documentation files (the "Software"), to deal |
1505 | +// in the Software without restriction, including without limitation the rights |
1506 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1507 | +// copies of the Software, and to permit persons to whom the Software is |
1508 | +// furnished to do so, subject to the following conditions: |
1509 | +// |
1510 | +// The above copyright notice and this permission notice shall be included in |
1511 | +// all copies or substantial portions of the Software. |
1512 | +// |
1513 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1514 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1515 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1516 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1517 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1518 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1519 | +// THE SOFTWARE. |
1520 | + |
1521 | +using System; |
1522 | +using Gtk; |
1523 | +using System.Collections.Generic; |
1524 | + |
1525 | +namespace Pinta.Core |
1526 | +{ |
1527 | + public class EffectsActions |
1528 | + { |
1529 | + private Menu effects_menu; |
1530 | + private Dictionary<Gtk.Action, MenuItem> menu_items; |
1531 | + |
1532 | + public Dictionary<string, Gtk.Menu> Menus { get; private set; } |
1533 | + public List<Gtk.Action> Actions { get; private set; } |
1534 | + |
1535 | + public EffectsActions () |
1536 | + { |
1537 | + Actions = new List<Gtk.Action> (); |
1538 | + Menus = new Dictionary<string,Menu> (); |
1539 | + menu_items = new Dictionary<Gtk.Action, MenuItem> (); |
1540 | + } |
1541 | + |
1542 | + #region Initialization |
1543 | + public void CreateMainMenu (Gtk.Menu menu) |
1544 | + { |
1545 | + effects_menu = menu; |
1546 | + } |
1547 | + |
1548 | + public void AddEffect (string category, Gtk.Action action) |
1549 | + { |
1550 | + if (!Menus.ContainsKey (category)) { |
1551 | + Gtk.Action menu_action = new Gtk.Action (category, Mono.Unix.Catalog.GetString (category), null, null); |
1552 | + Menu category_menu = (Menu)effects_menu.AppendMenuItemSorted ((MenuItem)(menu_action.CreateSubMenuItem ())).Submenu; |
1553 | + |
1554 | + Menus.Add (category, category_menu); |
1555 | + } |
1556 | + |
1557 | + Actions.Add (action); |
1558 | + var menu_item = (MenuItem)action.CreateMenuItem (); |
1559 | + |
1560 | + Menu m = Menus[category]; |
1561 | + m.AppendMenuItemSorted (menu_item); |
1562 | + |
1563 | + menu_items.Add (action, menu_item); |
1564 | + } |
1565 | + |
1566 | + // TODO: Remove menu category if empty |
1567 | + internal void RemoveEffect (string category, Gtk.Action action) |
1568 | + { |
1569 | + if (!Menus.ContainsKey (category)) |
1570 | + return; |
1571 | + if (!menu_items.ContainsKey (action)) |
1572 | + return; |
1573 | + |
1574 | + var menu = Menus[category]; |
1575 | + menu.Remove (menu_items[action]); |
1576 | + } |
1577 | + #endregion |
1578 | + |
1579 | + #region Public Methods |
1580 | + public void ToggleActionsSensitive (bool sensitive) |
1581 | + { |
1582 | + foreach (Gtk.Action a in Actions) |
1583 | + a.Sensitive = sensitive; |
1584 | + } |
1585 | + #endregion |
1586 | + } |
1587 | +} |
1588 | |
1589 | === added file 'Pinta.Core/Actions/FileActions.cs' |
1590 | --- Pinta.Core/Actions/FileActions.cs 1970-01-01 00:00:00 +0000 |
1591 | +++ Pinta.Core/Actions/FileActions.cs 2013-01-23 15:01:21 +0000 |
1592 | @@ -0,0 +1,131 @@ |
1593 | +// |
1594 | +// FileActions.cs |
1595 | +// |
1596 | +// Author: |
1597 | +// Jonathan Pobst <monkey@jpobst.com> |
1598 | +// |
1599 | +// Copyright (c) 2010 Jonathan Pobst |
1600 | +// |
1601 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
1602 | +// of this software and associated documentation files (the "Software"), to deal |
1603 | +// in the Software without restriction, including without limitation the rights |
1604 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1605 | +// copies of the Software, and to permit persons to whom the Software is |
1606 | +// furnished to do so, subject to the following conditions: |
1607 | +// |
1608 | +// The above copyright notice and this permission notice shall be included in |
1609 | +// all copies or substantial portions of the Software. |
1610 | +// |
1611 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1612 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1613 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1614 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1615 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1616 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1617 | +// THE SOFTWARE. |
1618 | + |
1619 | +using System; |
1620 | +using System.Collections.Generic; |
1621 | +using System.IO; |
1622 | +using Gdk; |
1623 | +using Gtk; |
1624 | +using Mono.Unix; |
1625 | + |
1626 | +namespace Pinta.Core |
1627 | +{ |
1628 | + public class FileActions |
1629 | + { |
1630 | + public Gtk.Action New { get; private set; } |
1631 | + public Gtk.Action NewScreenshot { get; private set; } |
1632 | + public Gtk.Action Open { get; private set; } |
1633 | + public Gtk.RecentAction OpenRecent { get; private set; } |
1634 | + public Gtk.Action Close { get; private set; } |
1635 | + public Gtk.Action Save { get; private set; } |
1636 | + public Gtk.Action SaveAs { get; private set; } |
1637 | + public Gtk.Action Print { get; private set; } |
1638 | + public Gtk.Action Exit { get; private set; } |
1639 | + |
1640 | + public event EventHandler BeforeQuit; |
1641 | + public event EventHandler<ModifyCompressionEventArgs> ModifyCompression; |
1642 | + public event EventHandler<DocumentCancelEventArgs> SaveDocument; |
1643 | + |
1644 | + public FileActions () |
1645 | + { |
1646 | + New = new Gtk.Action ("New", Catalog.GetString ("New..."), null, Stock.New); |
1647 | + NewScreenshot = new Gtk.Action ("NewScreenshot", Catalog.GetString ("New Screenshot..."), null, Stock.Fullscreen); |
1648 | + Open = new Gtk.Action ("Open", Catalog.GetString ("Open..."), null, Stock.Open); |
1649 | + OpenRecent = new RecentAction ("OpenRecent", Catalog.GetString ("Open Recent"), null, Stock.Open, RecentManager.Default); |
1650 | + |
1651 | + RecentFilter recentFilter = new RecentFilter (); |
1652 | + recentFilter.AddApplication ("Pinta"); |
1653 | + |
1654 | + (OpenRecent as RecentAction).AddFilter (recentFilter); |
1655 | + |
1656 | + Close = new Gtk.Action ("Close", Catalog.GetString ("Close"), null, Stock.Close); |
1657 | + Save = new Gtk.Action ("Save", Catalog.GetString ("Save"), null, Stock.Save); |
1658 | + SaveAs = new Gtk.Action ("SaveAs", Catalog.GetString ("Save As..."), null, Stock.SaveAs); |
1659 | + Print = new Gtk.Action ("Print", Catalog.GetString ("Print"), null, Stock.Print); |
1660 | + Exit = new Gtk.Action ("Exit", Catalog.GetString ("Quit"), null, Stock.Quit); |
1661 | + |
1662 | + New.ShortLabel = Catalog.GetString ("New"); |
1663 | + Open.ShortLabel = Catalog.GetString ("Open"); |
1664 | + Open.IsImportant = true; |
1665 | + Save.IsImportant = true; |
1666 | + |
1667 | + Close.Sensitive = false; |
1668 | + Print.Sensitive = false; |
1669 | + } |
1670 | + |
1671 | + #region Initialization |
1672 | + public void CreateMainMenu (Gtk.Menu menu) |
1673 | + { |
1674 | + menu.Append (New.CreateAcceleratedMenuItem (Gdk.Key.N, Gdk.ModifierType.ControlMask)); |
1675 | + menu.Append (NewScreenshot.CreateMenuItem ()); |
1676 | + menu.Append (Open.CreateAcceleratedMenuItem (Gdk.Key.O, Gdk.ModifierType.ControlMask)); |
1677 | + menu.Append (OpenRecent.CreateMenuItem ()); |
1678 | + menu.AppendSeparator (); |
1679 | + menu.Append (Save.CreateAcceleratedMenuItem (Gdk.Key.S, Gdk.ModifierType.ControlMask)); |
1680 | + menu.Append (SaveAs.CreateAcceleratedMenuItem (Gdk.Key.S, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
1681 | + menu.AppendSeparator (); |
1682 | + //menu.Append (Print.CreateAcceleratedMenuItem (Gdk.Key.P, Gdk.ModifierType.ControlMask)); |
1683 | + //menu.AppendSeparator (); |
1684 | + menu.Append (Close.CreateAcceleratedMenuItem (Gdk.Key.W, Gdk.ModifierType.ControlMask)); |
1685 | + menu.Append (Exit.CreateAcceleratedMenuItem (Gdk.Key.Q, Gdk.ModifierType.ControlMask)); |
1686 | + } |
1687 | + |
1688 | + public void RegisterHandlers () |
1689 | + { |
1690 | + } |
1691 | + #endregion |
1692 | + |
1693 | + #region Event Invokers |
1694 | + public void RaiseBeforeQuit () |
1695 | + { |
1696 | + if (BeforeQuit != null) |
1697 | + BeforeQuit (this, EventArgs.Empty); |
1698 | + } |
1699 | + |
1700 | + internal bool RaiseSaveDocument (Document document, bool saveAs) |
1701 | + { |
1702 | + DocumentCancelEventArgs e = new DocumentCancelEventArgs (document, saveAs); |
1703 | + |
1704 | + if (SaveDocument == null) |
1705 | + throw new InvalidOperationException ("GUI is not handling PintaCore.Workspace.SaveDocument"); |
1706 | + else |
1707 | + SaveDocument (this, e); |
1708 | + |
1709 | + return !e.Cancel; |
1710 | + } |
1711 | + |
1712 | + internal int RaiseModifyCompression (int defaultCompression) |
1713 | + { |
1714 | + ModifyCompressionEventArgs e = new ModifyCompressionEventArgs (defaultCompression); |
1715 | + |
1716 | + if (ModifyCompression != null) |
1717 | + ModifyCompression (this, e); |
1718 | + |
1719 | + return e.Cancel ? -1 : e.Quality; |
1720 | + } |
1721 | + #endregion |
1722 | + } |
1723 | +} |
1724 | |
1725 | === added file 'Pinta.Core/Actions/HelpActions.cs' |
1726 | --- Pinta.Core/Actions/HelpActions.cs 1970-01-01 00:00:00 +0000 |
1727 | +++ Pinta.Core/Actions/HelpActions.cs 2013-01-23 15:01:21 +0000 |
1728 | @@ -0,0 +1,93 @@ |
1729 | +// |
1730 | +// HelpActions.cs |
1731 | +// |
1732 | +// Author: |
1733 | +// Jonathan Pobst <monkey@jpobst.com> |
1734 | +// |
1735 | +// Copyright (c) 2010 Jonathan Pobst |
1736 | +// |
1737 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
1738 | +// of this software and associated documentation files (the "Software"), to deal |
1739 | +// in the Software without restriction, including without limitation the rights |
1740 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1741 | +// copies of the Software, and to permit persons to whom the Software is |
1742 | +// furnished to do so, subject to the following conditions: |
1743 | +// |
1744 | +// The above copyright notice and this permission notice shall be included in |
1745 | +// all copies or substantial portions of the Software. |
1746 | +// |
1747 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1748 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1749 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1750 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1751 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1752 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1753 | +// THE SOFTWARE. |
1754 | + |
1755 | +using System; |
1756 | +using System.Diagnostics; |
1757 | +using System.Reflection; |
1758 | +using Gtk; |
1759 | +using Mono.Unix; |
1760 | + |
1761 | +namespace Pinta.Core |
1762 | +{ |
1763 | + public class HelpActions |
1764 | + { |
1765 | + public Gtk.Action ExtensionManager { get; private set; } |
1766 | + public Gtk.Action Website { get; private set; } |
1767 | + public Gtk.Action Bugs { get; private set; } |
1768 | + public Gtk.Action Translate { get; private set; } |
1769 | + public Gtk.Action About { get; private set; } |
1770 | + |
1771 | + public HelpActions () |
1772 | + { |
1773 | + Gtk.IconFactory fact = new Gtk.IconFactory (); |
1774 | + fact.Add ("Menu.Help.Bug.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Help.Bug.png"))); |
1775 | + fact.Add ("Menu.Help.Website.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Help.Website.png"))); |
1776 | + fact.Add ("Menu.Help.Translate.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Help.Translate.png"))); |
1777 | + fact.Add ("Menu.Help.Extensions.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Help.Extensions.png"))); |
1778 | + fact.AddDefault (); |
1779 | + |
1780 | + ExtensionManager = new Gtk.Action ("ExtensionManager", Catalog.GetString ("Extension Manager"), null, "Menu.Help.Extensions.png"); |
1781 | + Website = new Gtk.Action ("Website", Catalog.GetString ("Pinta Website"), null, "Menu.Help.Website.png"); |
1782 | + Bugs = new Gtk.Action ("Bugs", Catalog.GetString ("File a Bug"), null, "Menu.Help.Bug.png"); |
1783 | + Translate = new Gtk.Action ("Translate", Catalog.GetString ("Translate This Application"), null, "Menu.Help.Translate.png"); |
1784 | + About = new Gtk.Action ("About", Catalog.GetString ("About"), null, Stock.About); |
1785 | + } |
1786 | + |
1787 | + #region Initialization |
1788 | + public void CreateMainMenu (Gtk.Menu menu) |
1789 | + { |
1790 | + menu.Append (ExtensionManager.CreateMenuItem ()); |
1791 | + menu.Append (Website.CreateMenuItem ()); |
1792 | + menu.Append (Bugs.CreateMenuItem ()); |
1793 | + menu.Append (Translate.CreateMenuItem ()); |
1794 | + menu.AppendSeparator (); |
1795 | + menu.Append (About.CreateMenuItem ()); |
1796 | + } |
1797 | + |
1798 | + public void RegisterHandlers () |
1799 | + { |
1800 | + Website.Activated += new EventHandler (Website_Activated); |
1801 | + Bugs.Activated += new EventHandler (Bugs_Activated); |
1802 | + Translate.Activated += Translate_Activated; |
1803 | + } |
1804 | + |
1805 | + private void Bugs_Activated (object sender, EventArgs e) |
1806 | + { |
1807 | + Process.Start ("https://bugs.launchpad.net/pinta"); |
1808 | + } |
1809 | + |
1810 | + private void Translate_Activated (object sender, EventArgs e) |
1811 | + { |
1812 | + Process.Start ("https://translations.launchpad.net/pinta"); |
1813 | + } |
1814 | + |
1815 | + private void Website_Activated (object sender, EventArgs e) |
1816 | + { |
1817 | + Process.Start ("http://www.pinta-project.com"); |
1818 | + } |
1819 | + #endregion |
1820 | + } |
1821 | +} |
1822 | |
1823 | === added file 'Pinta.Core/Actions/ImageActions.cs' |
1824 | --- Pinta.Core/Actions/ImageActions.cs 1970-01-01 00:00:00 +0000 |
1825 | +++ Pinta.Core/Actions/ImageActions.cs 2013-01-23 15:01:21 +0000 |
1826 | @@ -0,0 +1,301 @@ |
1827 | +// |
1828 | +// ImageActions.cs |
1829 | +// |
1830 | +// Author: |
1831 | +// Jonathan Pobst <monkey@jpobst.com> |
1832 | +// |
1833 | +// Copyright (c) 2010 Jonathan Pobst |
1834 | +// |
1835 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
1836 | +// of this software and associated documentation files (the "Software"), to deal |
1837 | +// in the Software without restriction, including without limitation the rights |
1838 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1839 | +// copies of the Software, and to permit persons to whom the Software is |
1840 | +// furnished to do so, subject to the following conditions: |
1841 | +// |
1842 | +// The above copyright notice and this permission notice shall be included in |
1843 | +// all copies or substantial portions of the Software. |
1844 | +// |
1845 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1846 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1847 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1848 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1849 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1850 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1851 | +// THE SOFTWARE. |
1852 | + |
1853 | +using System; |
1854 | +using Mono.Unix; |
1855 | + |
1856 | +namespace Pinta.Core |
1857 | +{ |
1858 | + public class ImageActions |
1859 | + { |
1860 | + public Gtk.Action CropToSelection { get; private set; } |
1861 | + public Gtk.Action AutoCrop { get; private set; } |
1862 | + public Gtk.Action Resize { get; private set; } |
1863 | + public Gtk.Action CanvasSize { get; private set; } |
1864 | + public Gtk.Action FlipHorizontal { get; private set; } |
1865 | + public Gtk.Action FlipVertical { get; private set; } |
1866 | + public Gtk.Action RotateCW { get; private set; } |
1867 | + public Gtk.Action RotateCCW { get; private set; } |
1868 | + public Gtk.Action Rotate180 { get; private set; } |
1869 | + public Gtk.Action Flatten { get; private set; } |
1870 | + |
1871 | + public ImageActions () |
1872 | + { |
1873 | + Gtk.IconFactory fact = new Gtk.IconFactory (); |
1874 | + fact.Add ("Menu.Image.CanvasSize.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.CanvasSize.png"))); |
1875 | + fact.Add ("Menu.Image.Crop.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.Crop.png"))); |
1876 | + fact.Add ("Menu.Image.Flatten.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.Flatten.png"))); |
1877 | + fact.Add ("Menu.Image.FlipHorizontal.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.FlipHorizontal.png"))); |
1878 | + fact.Add ("Menu.Image.FlipVertical.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.FlipVertical.png"))); |
1879 | + fact.Add ("Menu.Image.Resize.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.Resize.png"))); |
1880 | + fact.Add ("Menu.Image.Rotate180CW.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.Rotate180CW.png"))); |
1881 | + fact.Add ("Menu.Image.Rotate90CCW.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.Rotate90CCW.png"))); |
1882 | + fact.Add ("Menu.Image.Rotate90CW.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Image.Rotate90CW.png"))); |
1883 | + fact.AddDefault (); |
1884 | + |
1885 | + CropToSelection = new Gtk.Action ("CropToSelection", Catalog.GetString ("Crop to Selection"), null, "Menu.Image.Crop.png"); |
1886 | + AutoCrop = new Gtk.Action ("AutoCrop", Catalog.GetString ("Auto Crop"), null, "Menu.Image.Crop.png"); |
1887 | + Resize = new Gtk.Action ("Resize", Catalog.GetString ("Resize Image..."), null, "Menu.Image.Resize.png"); |
1888 | + CanvasSize = new Gtk.Action ("CanvasSize", Catalog.GetString ("Resize Canvas..."), null, "Menu.Image.CanvasSize.png"); |
1889 | + FlipHorizontal = new Gtk.Action ("FlipHorizontal", Catalog.GetString ("Flip Horizontal"), null, "Menu.Image.FlipHorizontal.png"); |
1890 | + FlipVertical = new Gtk.Action ("FlipVertical", Catalog.GetString ("Flip Vertical"), null, "Menu.Image.FlipVertical.png"); |
1891 | + RotateCW = new Gtk.Action ("RotateCW", Catalog.GetString ("Rotate 90° Clockwise"), null, "Menu.Image.Rotate90CW.png"); |
1892 | + RotateCCW = new Gtk.Action ("RotateCCW", Catalog.GetString ("Rotate 90° Counter-Clockwise"), null, "Menu.Image.Rotate90CCW.png"); |
1893 | + Rotate180 = new Gtk.Action ("Rotate180", Catalog.GetString ("Rotate 180°"), null, "Menu.Image.Rotate180CW.png"); |
1894 | + Flatten = new Gtk.Action ("Flatten", Catalog.GetString ("Flatten"), null, "Menu.Image.Flatten.png"); |
1895 | + |
1896 | + CropToSelection.Sensitive = false; |
1897 | + } |
1898 | + |
1899 | + #region Initialization |
1900 | + public void CreateMainMenu (Gtk.Menu menu) |
1901 | + { |
1902 | + menu.Append (CropToSelection.CreateAcceleratedMenuItem (Gdk.Key.X, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
1903 | + menu.Append (AutoCrop.CreateAcceleratedMenuItem (Gdk.Key.X, Gdk.ModifierType.Mod1Mask | Gdk.ModifierType.ControlMask)); |
1904 | + menu.Append (Resize.CreateAcceleratedMenuItem (Gdk.Key.R, Gdk.ModifierType.ControlMask)); |
1905 | + menu.Append (CanvasSize.CreateAcceleratedMenuItem (Gdk.Key.R, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
1906 | + menu.AppendSeparator (); |
1907 | + menu.Append (FlipHorizontal.CreateMenuItem ()); |
1908 | + menu.Append (FlipVertical.CreateMenuItem ()); |
1909 | + menu.AppendSeparator (); |
1910 | + menu.Append (RotateCW.CreateAcceleratedMenuItem (Gdk.Key.H, Gdk.ModifierType.ControlMask)); |
1911 | + menu.Append (RotateCCW.CreateAcceleratedMenuItem (Gdk.Key.G, Gdk.ModifierType.ControlMask)); |
1912 | + menu.Append (Rotate180.CreateAcceleratedMenuItem (Gdk.Key.J, Gdk.ModifierType.ControlMask)); |
1913 | + menu.AppendSeparator (); |
1914 | + menu.Append (Flatten.CreateAcceleratedMenuItem (Gdk.Key.F, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
1915 | + } |
1916 | + |
1917 | + public void RegisterHandlers () |
1918 | + { |
1919 | + FlipHorizontal.Activated += HandlePintaCoreActionsImageFlipHorizontalActivated; |
1920 | + FlipVertical.Activated += HandlePintaCoreActionsImageFlipVerticalActivated; |
1921 | + Rotate180.Activated += HandlePintaCoreActionsImageRotate180Activated; |
1922 | + Flatten.Activated += HandlePintaCoreActionsImageFlattenActivated; |
1923 | + RotateCW.Activated += HandlePintaCoreActionsImageRotateCWActivated; |
1924 | + RotateCCW.Activated += HandlePintaCoreActionsImageRotateCCWActivated; |
1925 | + CropToSelection.Activated += HandlePintaCoreActionsImageCropToSelectionActivated; |
1926 | + AutoCrop.Activated += HandlePintaCoreActionsImageAutoCropActivated; |
1927 | + } |
1928 | + #endregion |
1929 | + |
1930 | + #region Action Handlers |
1931 | + private void HandlePintaCoreActionsImageRotateCCWActivated (object sender, EventArgs e) |
1932 | + { |
1933 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1934 | + |
1935 | + PintaCore.Tools.Commit (); |
1936 | + doc.RotateImageCCW (); |
1937 | + |
1938 | + doc.ResetSelectionPath (); |
1939 | + |
1940 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.Rotate90CCW)); |
1941 | + } |
1942 | + |
1943 | + private void HandlePintaCoreActionsImageRotateCWActivated (object sender, EventArgs e) |
1944 | + { |
1945 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1946 | + |
1947 | + PintaCore.Tools.Commit (); |
1948 | + doc.RotateImageCW (); |
1949 | + |
1950 | + doc.ResetSelectionPath (); |
1951 | + |
1952 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.Rotate90CW)); |
1953 | + } |
1954 | + |
1955 | + private void HandlePintaCoreActionsImageFlattenActivated (object sender, EventArgs e) |
1956 | + { |
1957 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1958 | + |
1959 | + PintaCore.Tools.Commit (); |
1960 | + |
1961 | + CompoundHistoryItem hist = new CompoundHistoryItem ("Menu.Image.Flatten.png", Catalog.GetString ("Flatten")); |
1962 | + SimpleHistoryItem h1 = new SimpleHistoryItem (string.Empty, string.Empty, doc.Layers[0].Surface.Clone (), 0); |
1963 | + |
1964 | + hist.Push (h1); |
1965 | + |
1966 | + for (int i = 1; i < doc.Layers.Count; i++) |
1967 | + hist.Push (new DeleteLayerHistoryItem (string.Empty, string.Empty, doc.Layers[i], i)); |
1968 | + |
1969 | + doc.FlattenImage (); |
1970 | + |
1971 | + doc.History.PushNewItem (hist); |
1972 | + } |
1973 | + |
1974 | + private void HandlePintaCoreActionsImageRotate180Activated (object sender, EventArgs e) |
1975 | + { |
1976 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1977 | + |
1978 | + PintaCore.Tools.Commit (); |
1979 | + doc.RotateImage180 (); |
1980 | + |
1981 | + doc.ResetSelectionPath (); |
1982 | + |
1983 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.Rotate180)); |
1984 | + } |
1985 | + |
1986 | + private void HandlePintaCoreActionsImageFlipVerticalActivated (object sender, EventArgs e) |
1987 | + { |
1988 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1989 | + |
1990 | + PintaCore.Tools.Commit (); |
1991 | + doc.FlipImageVertical (); |
1992 | + |
1993 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.FlipVertical)); |
1994 | + } |
1995 | + |
1996 | + private void HandlePintaCoreActionsImageFlipHorizontalActivated (object sender, EventArgs e) |
1997 | + { |
1998 | + Document doc = PintaCore.Workspace.ActiveDocument; |
1999 | + |
2000 | + PintaCore.Tools.Commit (); |
2001 | + doc.FlipImageHorizontal (); |
2002 | + |
2003 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.FlipHorizontal)); |
2004 | + } |
2005 | + |
2006 | + private void HandlePintaCoreActionsImageCropToSelectionActivated (object sender, EventArgs e) |
2007 | + { |
2008 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2009 | + |
2010 | + PintaCore.Tools.Commit (); |
2011 | + |
2012 | + Gdk.Rectangle rect = doc.GetSelectedBounds (true); |
2013 | + |
2014 | + CropImageToRectangle (doc, rect); |
2015 | + } |
2016 | + |
2017 | + private void HandlePintaCoreActionsImageAutoCropActivated (object sender, EventArgs e) |
2018 | + { |
2019 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2020 | + |
2021 | + PintaCore.Tools.Commit (); |
2022 | + |
2023 | + Cairo.ImageSurface image = doc.CurrentLayer.Surface; |
2024 | + Gdk.Rectangle rect = image.GetBounds (); |
2025 | + |
2026 | + Cairo.Color borderColor = image.GetPixel (0, 0); |
2027 | + bool cropSide = true; |
2028 | + int depth = -1; |
2029 | + |
2030 | + //From the top down |
2031 | + while (cropSide) { |
2032 | + depth++; |
2033 | + for (int i = 0; i < image.Width; i++) { |
2034 | + if (!borderColor.Equals(image.GetPixel (i, depth))) { |
2035 | + cropSide = false; |
2036 | + break; |
2037 | + } |
2038 | + } |
2039 | + //Check if the image is blank/mono-coloured, only need to do it on this scan |
2040 | + if (depth == image.Height) |
2041 | + return; |
2042 | + } |
2043 | + |
2044 | + rect = new Gdk.Rectangle (rect.X, rect.Y + depth, rect.Width, rect.Height - depth); |
2045 | + |
2046 | + depth = image.Height; |
2047 | + cropSide = true; |
2048 | + //From the bottom up |
2049 | + while (cropSide) { |
2050 | + depth--; |
2051 | + for (int i = 0; i < image.Width; i++) { |
2052 | + if (!borderColor.Equals(image.GetPixel (i, depth))) { |
2053 | + cropSide = false; |
2054 | + break; |
2055 | + } |
2056 | + } |
2057 | + |
2058 | + } |
2059 | + |
2060 | + rect = new Gdk.Rectangle (rect.X, rect.Y, rect.Width, depth - rect.Y); |
2061 | + |
2062 | + depth = 0; |
2063 | + cropSide = true; |
2064 | + //From left to right |
2065 | + while (cropSide) { |
2066 | + depth++; |
2067 | + for (int i = 0; i < image.Height; i++) { |
2068 | + if (!borderColor.Equals(image.GetPixel (depth, i))) { |
2069 | + cropSide = false; |
2070 | + break; |
2071 | + } |
2072 | + } |
2073 | + |
2074 | + } |
2075 | + |
2076 | + rect = new Gdk.Rectangle (rect.X + depth, rect.Y, rect.Width - depth, rect.Height); |
2077 | + |
2078 | + depth = image.Width; |
2079 | + cropSide = true; |
2080 | + //From right to left |
2081 | + while (cropSide) { |
2082 | + depth--; |
2083 | + for (int i = 0; i < image.Height; i++) { |
2084 | + if (!borderColor.Equals(image.GetPixel (depth, i))) { |
2085 | + cropSide = false; |
2086 | + break; |
2087 | + } |
2088 | + } |
2089 | + |
2090 | + } |
2091 | + |
2092 | + rect = new Gdk.Rectangle (rect.X, rect.Y, depth - rect.X, rect.Height); |
2093 | + |
2094 | + CropImageToRectangle (doc, rect); |
2095 | + } |
2096 | + #endregion |
2097 | + |
2098 | + static void CropImageToRectangle (Document doc, Gdk.Rectangle rect) |
2099 | + { |
2100 | + ResizeHistoryItem hist = new ResizeHistoryItem (doc.ImageSize); |
2101 | + |
2102 | + hist.Icon = "Menu.Image.Crop.png"; |
2103 | + hist.Text = Catalog.GetString ("Crop to Selection"); |
2104 | + hist.TakeSnapshotOfImage (); |
2105 | + hist.RestorePath = doc.SelectionPath.Clone (); |
2106 | + |
2107 | + PintaCore.Chrome.Canvas.GdkWindow.FreezeUpdates (); |
2108 | + |
2109 | + double original_scale = doc.Workspace.Scale; |
2110 | + doc.ImageSize = rect.Size; |
2111 | + doc.Workspace.CanvasSize = rect.Size; |
2112 | + doc.Workspace.Scale = original_scale; |
2113 | + |
2114 | + PintaCore.Actions.View.UpdateCanvasScale (); |
2115 | + |
2116 | + PintaCore.Chrome.Canvas.GdkWindow.ThawUpdates (); |
2117 | + |
2118 | + foreach (var layer in doc.Layers) |
2119 | + layer.Crop (rect, doc.SelectionPath); |
2120 | + |
2121 | + doc.History.PushNewItem (hist); |
2122 | + doc.ResetSelectionPath (); |
2123 | + |
2124 | + doc.Workspace.Invalidate (); |
2125 | + } |
2126 | + } |
2127 | +} |
2128 | |
2129 | === added file 'Pinta.Core/Actions/LayerActions.cs' |
2130 | --- Pinta.Core/Actions/LayerActions.cs 1970-01-01 00:00:00 +0000 |
2131 | +++ Pinta.Core/Actions/LayerActions.cs 2013-01-23 15:01:21 +0000 |
2132 | @@ -0,0 +1,292 @@ |
2133 | +// |
2134 | +// LayerActions.cs |
2135 | +// |
2136 | +// Author: |
2137 | +// Jonathan Pobst <monkey@jpobst.com> |
2138 | +// |
2139 | +// Copyright (c) 2010 Jonathan Pobst |
2140 | +// |
2141 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
2142 | +// of this software and associated documentation files (the "Software"), to deal |
2143 | +// in the Software without restriction, including without limitation the rights |
2144 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
2145 | +// copies of the Software, and to permit persons to whom the Software is |
2146 | +// furnished to do so, subject to the following conditions: |
2147 | +// |
2148 | +// The above copyright notice and this permission notice shall be included in |
2149 | +// all copies or substantial portions of the Software. |
2150 | +// |
2151 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
2152 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
2153 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
2154 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
2155 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
2156 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
2157 | +// THE SOFTWARE. |
2158 | + |
2159 | +using System; |
2160 | +using Gdk; |
2161 | +using Gtk; |
2162 | +using Mono.Unix; |
2163 | +using System.IO; |
2164 | + |
2165 | +namespace Pinta.Core |
2166 | +{ |
2167 | + public class LayerActions |
2168 | + { |
2169 | + public Gtk.Action AddNewLayer { get; private set; } |
2170 | + public Gtk.Action DeleteLayer { get; private set; } |
2171 | + public Gtk.Action DuplicateLayer { get; private set; } |
2172 | + public Gtk.Action MergeLayerDown { get; private set; } |
2173 | + public Gtk.Action ImportFromFile { get; private set; } |
2174 | + public Gtk.Action FlipHorizontal { get; private set; } |
2175 | + public Gtk.Action FlipVertical { get; private set; } |
2176 | + public Gtk.Action RotateZoom { get; private set; } |
2177 | + public Gtk.Action MoveLayerUp { get; private set; } |
2178 | + public Gtk.Action MoveLayerDown { get; private set; } |
2179 | + public Gtk.Action Properties { get; private set; } |
2180 | + |
2181 | + public LayerActions () |
2182 | + { |
2183 | + Gtk.IconFactory fact = new Gtk.IconFactory (); |
2184 | + fact.Add ("Menu.Layers.AddNewLayer.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.AddNewLayer.png"))); |
2185 | + fact.Add ("Menu.Layers.DeleteLayer.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.DeleteLayer.png"))); |
2186 | + fact.Add ("Menu.Layers.DuplicateLayer.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.DuplicateLayer.png"))); |
2187 | + fact.Add ("Menu.Layers.MergeLayerDown.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.MergeLayerDown.png"))); |
2188 | + fact.Add ("Menu.Layers.MoveLayerDown.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.MoveLayerDown.png"))); |
2189 | + fact.Add ("Menu.Layers.MoveLayerUp.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.MoveLayerUp.png"))); |
2190 | + fact.Add ("Menu.Layers.FlipHorizontal.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.FlipHorizontal.png"))); |
2191 | + fact.Add ("Menu.Layers.FlipVertical.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.FlipVertical.png"))); |
2192 | + fact.Add ("Menu.Layers.ImportFromFile.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.ImportFromFile.png"))); |
2193 | + fact.Add ("Menu.Layers.LayerProperties.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.LayerProperties.png"))); |
2194 | + fact.Add ("Menu.Layers.RotateZoom.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.Layers.RotateZoom.png"))); |
2195 | + fact.AddDefault (); |
2196 | + |
2197 | + AddNewLayer = new Gtk.Action ("AddNewLayer", Catalog.GetString ("Add New Layer"), null, "Menu.Layers.AddNewLayer.png"); |
2198 | + DeleteLayer = new Gtk.Action ("DeleteLayer", Catalog.GetString ("Delete Layer"), null, "Menu.Layers.DeleteLayer.png"); |
2199 | + DuplicateLayer = new Gtk.Action ("DuplicateLayer", Catalog.GetString ("Duplicate Layer"), null, "Menu.Layers.DuplicateLayer.png"); |
2200 | + MergeLayerDown = new Gtk.Action ("MergeLayerDown", Catalog.GetString ("Merge Layer Down"), null, "Menu.Layers.MergeLayerDown.png"); |
2201 | + ImportFromFile = new Gtk.Action ("ImportFromFile", Catalog.GetString ("Import from File..."), null, "Menu.Layers.ImportFromFile.png"); |
2202 | + FlipHorizontal = new Gtk.Action ("FlipHorizontal", Catalog.GetString ("Flip Horizontal"), null, "Menu.Layers.FlipHorizontal.png"); |
2203 | + FlipVertical = new Gtk.Action ("FlipVertical", Catalog.GetString ("Flip Vertical"), null, "Menu.Layers.FlipVertical.png"); |
2204 | + RotateZoom = new Gtk.Action ("RotateZoom", Catalog.GetString ("Rotate / Zoom Layer..."), null, "Menu.Layers.RotateZoom.png"); |
2205 | + MoveLayerUp = new Gtk.Action ("MoveLayerUp", Catalog.GetString ("Move Layer Up"), null, "Menu.Layers.MoveLayerUp.png"); |
2206 | + MoveLayerDown = new Gtk.Action ("MoveLayerDown", Catalog.GetString ("Move Layer Down"), null, "Menu.Layers.MoveLayerDown.png"); |
2207 | + Properties = new Gtk.Action ("Properties", Catalog.GetString ("Layer Properties..."), null, "Menu.Layers.LayerProperties.png"); |
2208 | + |
2209 | + RotateZoom.Sensitive = false; |
2210 | + } |
2211 | + |
2212 | + #region Initialization |
2213 | + public void CreateMainMenu (Gtk.Menu menu) |
2214 | + { |
2215 | + menu.Append (AddNewLayer.CreateAcceleratedMenuItem (Gdk.Key.N, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
2216 | + menu.Append (DeleteLayer.CreateAcceleratedMenuItem (Gdk.Key.Delete, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
2217 | + menu.Append (DuplicateLayer.CreateAcceleratedMenuItem (Gdk.Key.D, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
2218 | + menu.Append (MergeLayerDown.CreateAcceleratedMenuItem (Gdk.Key.M, Gdk.ModifierType.ControlMask)); |
2219 | + menu.Append (ImportFromFile.CreateMenuItem ()); |
2220 | + menu.AppendSeparator (); |
2221 | + menu.Append (FlipHorizontal.CreateMenuItem ()); |
2222 | + menu.Append (FlipVertical.CreateMenuItem ()); |
2223 | + menu.Append (RotateZoom.CreateMenuItem ()); |
2224 | + menu.AppendSeparator (); |
2225 | + menu.Append (Properties.CreateAcceleratedMenuItem (Gdk.Key.F4, Gdk.ModifierType.None)); |
2226 | + } |
2227 | + |
2228 | + public void CreateLayerWindowToolBar (Gtk.Toolbar toolbar) |
2229 | + { |
2230 | + toolbar.AppendItem (AddNewLayer.CreateToolBarItem ()); |
2231 | + toolbar.AppendItem (DeleteLayer.CreateToolBarItem ()); |
2232 | + toolbar.AppendItem (DuplicateLayer.CreateToolBarItem ()); |
2233 | + toolbar.AppendItem (MergeLayerDown.CreateToolBarItem ()); |
2234 | + toolbar.AppendItem (MoveLayerUp.CreateToolBarItem ()); |
2235 | + toolbar.AppendItem (MoveLayerDown.CreateToolBarItem ()); |
2236 | + toolbar.AppendItem (Properties.CreateToolBarItem ()); |
2237 | + } |
2238 | + |
2239 | + public void RegisterHandlers () |
2240 | + { |
2241 | + AddNewLayer.Activated += HandlePintaCoreActionsLayersAddNewLayerActivated; |
2242 | + DeleteLayer.Activated += HandlePintaCoreActionsLayersDeleteLayerActivated; |
2243 | + DuplicateLayer.Activated += HandlePintaCoreActionsLayersDuplicateLayerActivated; |
2244 | + MergeLayerDown.Activated += HandlePintaCoreActionsLayersMergeLayerDownActivated; |
2245 | + MoveLayerDown.Activated += HandlePintaCoreActionsLayersMoveLayerDownActivated; |
2246 | + MoveLayerUp.Activated += HandlePintaCoreActionsLayersMoveLayerUpActivated; |
2247 | + FlipHorizontal.Activated += HandlePintaCoreActionsLayersFlipHorizontalActivated; |
2248 | + FlipVertical.Activated += HandlePintaCoreActionsLayersFlipVerticalActivated; |
2249 | + ImportFromFile.Activated += HandlePintaCoreActionsLayersImportFromFileActivated; |
2250 | + |
2251 | + PintaCore.Layers.LayerAdded += EnableOrDisableLayerActions; |
2252 | + PintaCore.Layers.LayerRemoved += EnableOrDisableLayerActions; |
2253 | + PintaCore.Layers.SelectedLayerChanged += EnableOrDisableLayerActions; |
2254 | + |
2255 | + EnableOrDisableLayerActions (null, EventArgs.Empty); |
2256 | + } |
2257 | + #endregion |
2258 | + |
2259 | + #region Action Handlers |
2260 | + private void EnableOrDisableLayerActions (object sender, EventArgs e) |
2261 | + { |
2262 | + if (PintaCore.Workspace.HasOpenDocuments && PintaCore.Workspace.ActiveDocument.Layers.Count > 1) { |
2263 | + PintaCore.Actions.Layers.DeleteLayer.Sensitive = true; |
2264 | + PintaCore.Actions.Image.Flatten.Sensitive = true; |
2265 | + } else { |
2266 | + PintaCore.Actions.Layers.DeleteLayer.Sensitive = false; |
2267 | + PintaCore.Actions.Image.Flatten.Sensitive = false; |
2268 | + } |
2269 | + |
2270 | + if (PintaCore.Workspace.HasOpenDocuments && PintaCore.Workspace.ActiveDocument.CurrentLayerIndex > 0) { |
2271 | + PintaCore.Actions.Layers.MergeLayerDown.Sensitive = true; |
2272 | + PintaCore.Actions.Layers.MoveLayerDown.Sensitive = true; |
2273 | + } else { |
2274 | + PintaCore.Actions.Layers.MergeLayerDown.Sensitive = false; |
2275 | + PintaCore.Actions.Layers.MoveLayerDown.Sensitive = false; |
2276 | + } |
2277 | + |
2278 | + if (PintaCore.Workspace.HasOpenDocuments && PintaCore.Workspace.ActiveDocument.CurrentLayerIndex < PintaCore.Workspace.ActiveDocument.Layers.Count - 1) |
2279 | + PintaCore.Actions.Layers.MoveLayerUp.Sensitive = true; |
2280 | + else |
2281 | + PintaCore.Actions.Layers.MoveLayerUp.Sensitive = false; |
2282 | + } |
2283 | + |
2284 | + private void HandlePintaCoreActionsLayersImportFromFileActivated (object sender, EventArgs e) |
2285 | + { |
2286 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2287 | + PintaCore.Tools.Commit (); |
2288 | + |
2289 | + Gtk.FileChooserDialog fcd = new Gtk.FileChooserDialog (Catalog.GetString ("Open Image File"), null, FileChooserAction.Open, Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, Gtk.Stock.Open, Gtk.ResponseType.Ok); |
2290 | + |
2291 | + fcd.SetCurrentFolder (PintaCore.System.LastDialogDirectory); |
2292 | + fcd.AlternativeButtonOrder = new int[] { (int) ResponseType.Ok, (int) ResponseType.Cancel }; |
2293 | + |
2294 | + fcd.AddImagePreview (); |
2295 | + |
2296 | + int response = fcd.Run (); |
2297 | + |
2298 | + if (response == (int)Gtk.ResponseType.Ok) { |
2299 | + |
2300 | + string file = fcd.Filename; |
2301 | + PintaCore.System.LastDialogDirectory = fcd.CurrentFolder; |
2302 | + |
2303 | + // Open the image and add it to the layers |
2304 | + Layer layer = doc.AddNewLayer (System.IO.Path.GetFileName (file)); |
2305 | + |
2306 | + using (var fs = new FileStream (file, FileMode.Open)) |
2307 | + using (Pixbuf bg = new Pixbuf (fs)) |
2308 | + using (Cairo.Context g = new Cairo.Context (layer.Surface)) { |
2309 | + CairoHelper.SetSourcePixbuf (g, bg, 0, 0); |
2310 | + g.Paint (); |
2311 | + } |
2312 | + |
2313 | + doc.SetCurrentLayer (layer); |
2314 | + |
2315 | + AddLayerHistoryItem hist = new AddLayerHistoryItem ("Menu.Layers.ImportFromFile.png", Catalog.GetString ("Import From File"), doc.Layers.IndexOf (layer)); |
2316 | + doc.History.PushNewItem (hist); |
2317 | + |
2318 | + doc.Workspace.Invalidate (); |
2319 | + } |
2320 | + |
2321 | + fcd.Destroy (); |
2322 | + } |
2323 | + |
2324 | + private void HandlePintaCoreActionsLayersFlipVerticalActivated (object sender, EventArgs e) |
2325 | + { |
2326 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2327 | + PintaCore.Tools.Commit (); |
2328 | + |
2329 | + doc.CurrentLayer.FlipVertical (); |
2330 | + doc.Workspace.Invalidate (); |
2331 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.FlipLayerVertical, doc.CurrentLayerIndex)); |
2332 | + } |
2333 | + |
2334 | + private void HandlePintaCoreActionsLayersFlipHorizontalActivated (object sender, EventArgs e) |
2335 | + { |
2336 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2337 | + PintaCore.Tools.Commit (); |
2338 | + |
2339 | + doc.CurrentLayer.FlipHorizontal (); |
2340 | + doc.Workspace.Invalidate (); |
2341 | + doc.History.PushNewItem (new InvertHistoryItem (InvertType.FlipLayerHorizontal, doc.CurrentLayerIndex)); |
2342 | + } |
2343 | + |
2344 | + private void HandlePintaCoreActionsLayersMoveLayerUpActivated (object sender, EventArgs e) |
2345 | + { |
2346 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2347 | + PintaCore.Tools.Commit (); |
2348 | + |
2349 | + SwapLayersHistoryItem hist = new SwapLayersHistoryItem ("Menu.Layers.MoveLayerUp.png", Catalog.GetString ("Move Layer Up"), doc.CurrentLayerIndex, doc.CurrentLayerIndex + 1); |
2350 | + |
2351 | + doc.MoveCurrentLayerUp (); |
2352 | + doc.History.PushNewItem (hist); |
2353 | + } |
2354 | + |
2355 | + private void HandlePintaCoreActionsLayersMoveLayerDownActivated (object sender, EventArgs e) |
2356 | + { |
2357 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2358 | + PintaCore.Tools.Commit (); |
2359 | + |
2360 | + SwapLayersHistoryItem hist = new SwapLayersHistoryItem ("Menu.Layers.MoveLayerDown.png", Catalog.GetString ("Move Layer Down"), doc.CurrentLayerIndex, doc.CurrentLayerIndex - 1); |
2361 | + |
2362 | + doc.MoveCurrentLayerDown (); |
2363 | + doc.History.PushNewItem (hist); |
2364 | + } |
2365 | + |
2366 | + private void HandlePintaCoreActionsLayersMergeLayerDownActivated (object sender, EventArgs e) |
2367 | + { |
2368 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2369 | + PintaCore.Tools.Commit (); |
2370 | + |
2371 | + CompoundHistoryItem hist = new CompoundHistoryItem ("Menu.Layers.MergeLayerDown.png", Catalog.GetString ("Merge Layer Down")); |
2372 | + DeleteLayerHistoryItem h1 = new DeleteLayerHistoryItem (string.Empty, string.Empty, doc.CurrentLayer, doc.CurrentLayerIndex); |
2373 | + SimpleHistoryItem h2 = new SimpleHistoryItem (string.Empty, string.Empty, doc.Layers[doc.CurrentLayerIndex - 1].Surface.Clone (), doc.CurrentLayerIndex - 1); |
2374 | + |
2375 | + hist.Push (h1); |
2376 | + hist.Push (h2); |
2377 | + |
2378 | + doc.MergeCurrentLayerDown (); |
2379 | + |
2380 | + doc.History.PushNewItem (hist); |
2381 | + } |
2382 | + |
2383 | + private void HandlePintaCoreActionsLayersDuplicateLayerActivated (object sender, EventArgs e) |
2384 | + { |
2385 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2386 | + PintaCore.Tools.Commit (); |
2387 | + |
2388 | + Layer l = doc.DuplicateCurrentLayer (); |
2389 | + |
2390 | + // Make new layer the current layer |
2391 | + doc.SetCurrentLayer (l); |
2392 | + |
2393 | + AddLayerHistoryItem hist = new AddLayerHistoryItem ("Menu.Layers.DuplicateLayer.png", Catalog.GetString ("Duplicate Layer"), doc.Layers.IndexOf (l)); |
2394 | + doc.History.PushNewItem (hist); |
2395 | + } |
2396 | + |
2397 | + private void HandlePintaCoreActionsLayersDeleteLayerActivated (object sender, EventArgs e) |
2398 | + { |
2399 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2400 | + PintaCore.Tools.Commit (); |
2401 | + |
2402 | + DeleteLayerHistoryItem hist = new DeleteLayerHistoryItem ("Menu.Layers.DeleteLayer.png", Catalog.GetString ("Delete Layer"), doc.CurrentLayer, doc.CurrentLayerIndex); |
2403 | + |
2404 | + doc.DeleteLayer (doc.CurrentLayerIndex, false); |
2405 | + |
2406 | + doc.History.PushNewItem (hist); |
2407 | + } |
2408 | + |
2409 | + private void HandlePintaCoreActionsLayersAddNewLayerActivated (object sender, EventArgs e) |
2410 | + { |
2411 | + Document doc = PintaCore.Workspace.ActiveDocument; |
2412 | + PintaCore.Tools.Commit (); |
2413 | + |
2414 | + Layer l = doc.AddNewLayer (string.Empty); |
2415 | + |
2416 | + // Make new layer the current layer |
2417 | + doc.SetCurrentLayer (l); |
2418 | + |
2419 | + AddLayerHistoryItem hist = new AddLayerHistoryItem ("Menu.Layers.AddNewLayer.png", Catalog.GetString ("Add New Layer"), doc.Layers.IndexOf (l)); |
2420 | + doc.History.PushNewItem (hist); |
2421 | + } |
2422 | + #endregion |
2423 | + } |
2424 | +} |
2425 | |
2426 | === added file 'Pinta.Core/Actions/ViewActions.cs' |
2427 | --- Pinta.Core/Actions/ViewActions.cs 1970-01-01 00:00:00 +0000 |
2428 | +++ Pinta.Core/Actions/ViewActions.cs 2013-01-23 15:01:21 +0000 |
2429 | @@ -0,0 +1,276 @@ |
2430 | +// |
2431 | +// ViewActions.cs |
2432 | +// |
2433 | +// Author: |
2434 | +// Jonathan Pobst <monkey@jpobst.com> |
2435 | +// |
2436 | +// Copyright (c) 2010 Jonathan Pobst |
2437 | +// |
2438 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
2439 | +// of this software and associated documentation files (the "Software"), to deal |
2440 | +// in the Software without restriction, including without limitation the rights |
2441 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
2442 | +// copies of the Software, and to permit persons to whom the Software is |
2443 | +// furnished to do so, subject to the following conditions: |
2444 | +// |
2445 | +// The above copyright notice and this permission notice shall be included in |
2446 | +// all copies or substantial portions of the Software. |
2447 | +// |
2448 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
2449 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
2450 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
2451 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
2452 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
2453 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
2454 | +// THE SOFTWARE. |
2455 | + |
2456 | +using System; |
2457 | +using Mono.Unix; |
2458 | +using Gtk; |
2459 | + |
2460 | +namespace Pinta.Core |
2461 | +{ |
2462 | + public class ViewActions |
2463 | + { |
2464 | + public Gtk.Action ZoomIn { get; private set; } |
2465 | + public Gtk.Action ZoomOut { get; private set; } |
2466 | + public Gtk.Action ZoomToWindow { get; private set; } |
2467 | + public Gtk.Action ZoomToSelection { get; private set; } |
2468 | + public Gtk.Action ActualSize { get; private set; } |
2469 | + public Gtk.ToggleAction ToolBar { get; private set; } |
2470 | + public Gtk.ToggleAction PixelGrid { get; private set; } |
2471 | + public Gtk.ToggleAction Rulers { get; private set; } |
2472 | + public Gtk.RadioAction Pixels { get; private set; } |
2473 | + public Gtk.RadioAction Inches { get; private set; } |
2474 | + public Gtk.RadioAction Centimeters { get; private set; } |
2475 | + public Gtk.Action Fullscreen { get; private set; } |
2476 | + |
2477 | + public ToolBarComboBox ZoomComboBox { get; private set; } |
2478 | + public string[] ZoomCollection { get; private set; } |
2479 | + |
2480 | + private string old_zoom_text = ""; |
2481 | + private bool zoom_to_window_activated = false; |
2482 | + |
2483 | + public bool ZoomToWindowActivated { |
2484 | + get { return zoom_to_window_activated; } |
2485 | + set |
2486 | + { |
2487 | + zoom_to_window_activated = value; |
2488 | + old_zoom_text = ZoomComboBox.ComboBox.ActiveText; |
2489 | + } |
2490 | + } |
2491 | + |
2492 | + public ViewActions () |
2493 | + { |
2494 | + Gtk.IconFactory fact = new Gtk.IconFactory (); |
2495 | + fact.Add ("Menu.View.ActualSize.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.ActualSize.png"))); |
2496 | + fact.Add ("Menu.View.Grid.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.Grid.png"))); |
2497 | + fact.Add ("Menu.View.Rulers.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.Rulers.png"))); |
2498 | + fact.Add ("Menu.View.ZoomIn.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.ZoomIn.png"))); |
2499 | + fact.Add ("Menu.View.ZoomOut.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.ZoomOut.png"))); |
2500 | + fact.Add ("Menu.View.ZoomToSelection.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.ZoomToSelection.png"))); |
2501 | + fact.Add ("Menu.View.ZoomToWindow.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Menu.View.ZoomToWindow.png"))); |
2502 | + fact.AddDefault (); |
2503 | + |
2504 | + ZoomIn = new Gtk.Action ("ZoomIn", Catalog.GetString ("Zoom In"), null, Stock.ZoomIn); |
2505 | + ZoomOut = new Gtk.Action ("ZoomOut", Catalog.GetString ("Zoom Out"), null, Stock.ZoomOut); |
2506 | + ZoomToWindow = new Gtk.Action ("ZoomToWindow", Catalog.GetString ("Best Fit"), null, Stock.ZoomFit); |
2507 | + ZoomToSelection = new Gtk.Action ("ZoomToSelection", Catalog.GetString ("Zoom to Selection"), null, "Menu.View.ZoomToSelection.png"); |
2508 | + ActualSize = new Gtk.Action ("ActualSize", Catalog.GetString ("Normal Size"), null, Stock.Zoom100); |
2509 | + ToolBar = new Gtk.ToggleAction ("Toolbar", Catalog.GetString ("Toolbar"), null, null); |
2510 | + PixelGrid = new Gtk.ToggleAction ("PixelGrid", Catalog.GetString ("Pixel Grid"), null, "Menu.View.Grid.png"); |
2511 | + Rulers = new Gtk.ToggleAction ("Rulers", Catalog.GetString ("Rulers"), null, "Menu.View.Rulers.png"); |
2512 | + Pixels = new Gtk.RadioAction ("Pixels", Catalog.GetString ("Pixels"), null, null, 0); |
2513 | + Inches = new Gtk.RadioAction ("Inches", Catalog.GetString ("Inches"), null, null, 1); |
2514 | + Centimeters = new Gtk.RadioAction ("Centimeters", Catalog.GetString ("Centimeters"), null, null, 2); |
2515 | + Fullscreen = new Gtk.Action ("Fullscreen", Catalog.GetString ("Fullscreen"), null, Stock.Fullscreen); |
2516 | + |
2517 | + ZoomCollection = new string[] { "3600%", "2400%", "1600%", "1200%", "800%", "700%", "600%", "500%", "400%", "300%", "200%", "175%", "150%", "125%", "100%", "66%", "50%", "33%", "25%", "16%", "12%", "8%", "5%", Catalog.GetString ("Window") }; |
2518 | + ZoomComboBox = new ToolBarComboBox (75, DefaultZoomIndex(), true, ZoomCollection); |
2519 | + |
2520 | + // Make sure these are the same group so only one will be selected at a time |
2521 | + Inches.Group = Pixels.Group; |
2522 | + Centimeters.Group = Pixels.Group; |
2523 | + } |
2524 | + |
2525 | + #region Initialization |
2526 | + public void CreateMainMenu (Gtk.Menu menu) |
2527 | + { |
2528 | + MenuItem show_pad = (MenuItem)menu.Children[0]; |
2529 | + menu.Remove (show_pad); |
2530 | + |
2531 | + menu.Append (ToolBar.CreateMenuItem ()); |
2532 | + menu.Append (PixelGrid.CreateMenuItem ()); |
2533 | + menu.Append (Rulers.CreateMenuItem ()); |
2534 | + menu.AppendSeparator (); |
2535 | + |
2536 | + ImageMenuItem zoomin = ZoomIn.CreateAcceleratedMenuItem (Gdk.Key.plus, Gdk.ModifierType.ControlMask); |
2537 | + zoomin.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.equal, Gdk.ModifierType.ControlMask, AccelFlags.Visible)); |
2538 | + zoomin.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.KP_Add, Gdk.ModifierType.ControlMask, AccelFlags.Visible)); |
2539 | + menu.Append (zoomin); |
2540 | + |
2541 | + ImageMenuItem zoomout = ZoomOut.CreateAcceleratedMenuItem (Gdk.Key.minus, Gdk.ModifierType.ControlMask); |
2542 | + zoomout.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.underscore, Gdk.ModifierType.ControlMask, AccelFlags.Visible)); |
2543 | + zoomout.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.KP_Subtract, Gdk.ModifierType.ControlMask, AccelFlags.Visible)); |
2544 | + menu.Append (zoomout); |
2545 | + |
2546 | + ImageMenuItem actualsize = ActualSize.CreateAcceleratedMenuItem (Gdk.Key.Key_0, Gdk.ModifierType.ControlMask); |
2547 | + actualsize.AddAccelerator ("activate", PintaCore.Actions.AccelGroup, new AccelKey (Gdk.Key.A, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask, AccelFlags.Visible)); |
2548 | + menu.Append (actualsize); |
2549 | + menu.Append (ZoomToWindow.CreateAcceleratedMenuItem (Gdk.Key.B, Gdk.ModifierType.ControlMask)); |
2550 | + //menu.Append (ZoomToSelection.CreateAcceleratedMenuItem (Gdk.Key.B, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
2551 | + menu.Append (Fullscreen.CreateAcceleratedMenuItem (Gdk.Key.F11, Gdk.ModifierType.None)); |
2552 | + |
2553 | + menu.AppendSeparator (); |
2554 | + |
2555 | + Gtk.Action unit_action = new Gtk.Action ("RulerUnits", Mono.Unix.Catalog.GetString ("Ruler Units"), null, null); |
2556 | + Menu unit_menu = (Menu)menu.AppendItem (unit_action.CreateSubMenuItem ()).Submenu; |
2557 | + unit_menu.Append (Pixels.CreateMenuItem ()); |
2558 | + unit_menu.Append (Inches.CreateMenuItem ()); |
2559 | + unit_menu.Append (Centimeters.CreateMenuItem ()); |
2560 | + |
2561 | + menu.AppendSeparator (); |
2562 | + menu.Append (show_pad); |
2563 | + } |
2564 | + |
2565 | + public void CreateToolBar (Gtk.Toolbar toolbar) |
2566 | + { |
2567 | + toolbar.AppendItem (new Gtk.SeparatorToolItem ()); |
2568 | + toolbar.AppendItem (ZoomOut.CreateToolBarItem ()); |
2569 | + toolbar.AppendItem (ZoomComboBox); |
2570 | + toolbar.AppendItem (ZoomIn.CreateToolBarItem ()); |
2571 | + } |
2572 | + |
2573 | + public void RegisterHandlers () |
2574 | + { |
2575 | + ZoomIn.Activated += HandlePintaCoreActionsViewZoomInActivated; |
2576 | + ZoomOut.Activated += HandlePintaCoreActionsViewZoomOutActivated; |
2577 | + ZoomComboBox.ComboBox.Changed += HandlePintaCoreActionsViewZoomComboBoxComboBoxChanged; |
2578 | + (ZoomComboBox.ComboBox as Gtk.ComboBoxEntry).Entry.FocusOutEvent += new Gtk.FocusOutEventHandler (ComboBox_FocusOutEvent); |
2579 | + (ZoomComboBox.ComboBox as Gtk.ComboBoxEntry).Entry.FocusInEvent += new Gtk.FocusInEventHandler (Entry_FocusInEvent); |
2580 | + ActualSize.Activated += HandlePintaCoreActionsViewActualSizeActivated; |
2581 | + |
2582 | + PixelGrid.Toggled += delegate (object sender, EventArgs e) { |
2583 | + PintaCore.Workspace.Invalidate (); |
2584 | + }; |
2585 | + |
2586 | + var isFullscreen = false; |
2587 | + |
2588 | + Fullscreen.Activated += (foo, bar) => { |
2589 | + if (!isFullscreen) |
2590 | + PintaCore.Chrome.MainWindow.Fullscreen (); |
2591 | + else |
2592 | + PintaCore.Chrome.MainWindow.Unfullscreen (); |
2593 | + |
2594 | + isFullscreen = !isFullscreen; |
2595 | + }; |
2596 | + } |
2597 | + |
2598 | + private string temp_zoom; |
2599 | + private bool suspend_zoom_change; |
2600 | + |
2601 | + private void Entry_FocusInEvent (object o, Gtk.FocusInEventArgs args) |
2602 | + { |
2603 | + temp_zoom = PintaCore.Actions.View.ZoomComboBox.ComboBox.ActiveText; |
2604 | + } |
2605 | + |
2606 | + private void ComboBox_FocusOutEvent (object o, Gtk.FocusOutEventArgs args) |
2607 | + { |
2608 | + string text = PintaCore.Actions.View.ZoomComboBox.ComboBox.ActiveText; |
2609 | + double percent; |
2610 | + |
2611 | + if (!TryParsePercent (text, out percent)) { |
2612 | + (PintaCore.Actions.View.ZoomComboBox.ComboBox as Gtk.ComboBoxEntry).Entry.Text = temp_zoom; |
2613 | + return; |
2614 | + } |
2615 | + |
2616 | + if (percent > 3600) |
2617 | + PintaCore.Actions.View.ZoomComboBox.ComboBox.Active = 0; |
2618 | + } |
2619 | + #endregion |
2620 | + |
2621 | + /// <summary> |
2622 | + /// Converts the string representation of a percent (with or without a '%' sign) to a numeric value |
2623 | + /// </summary> |
2624 | + public static bool TryParsePercent (string text, out double percent) |
2625 | + { |
2626 | + return double.TryParse (text.Trim ('%'), out percent); |
2627 | + } |
2628 | + |
2629 | + public void SuspendZoomUpdate () |
2630 | + { |
2631 | + suspend_zoom_change = true; |
2632 | + } |
2633 | + |
2634 | + public void ResumeZoomUpdate () |
2635 | + { |
2636 | + suspend_zoom_change = false; |
2637 | + } |
2638 | + |
2639 | + public void UpdateCanvasScale () |
2640 | + { |
2641 | + string text = PintaCore.Actions.View.ZoomComboBox.ComboBox.ActiveText; |
2642 | + |
2643 | + // stay in "Zoom to Window" mode if this function was called without the zoom level being changed by the user (e.g. if the |
2644 | + // image was rotated or cropped) and "Zoom to Window" mode is active |
2645 | + if (text == Catalog.GetString ("Window") || (ZoomToWindowActivated && old_zoom_text == text)) |
2646 | + { |
2647 | + PintaCore.Actions.View.ZoomToWindow.Activate (); |
2648 | + ZoomToWindowActivated = true; |
2649 | + return; |
2650 | + } |
2651 | + else |
2652 | + { |
2653 | + ZoomToWindowActivated = false; |
2654 | + } |
2655 | + |
2656 | + double percent; |
2657 | + |
2658 | + if (!TryParsePercent (text, out percent)) |
2659 | + return; |
2660 | + |
2661 | + percent = Math.Min (percent, 3600); |
2662 | + percent = percent / 100.0; |
2663 | + |
2664 | + PintaCore.Workspace.Scale = percent; |
2665 | + } |
2666 | + |
2667 | + #region Action Handlers |
2668 | + private void HandlePintaCoreActionsViewActualSizeActivated (object sender, EventArgs e) |
2669 | + { |
2670 | + int default_zoom = DefaultZoomIndex (); |
2671 | + if (ZoomComboBox.ComboBox.Active != default_zoom) |
2672 | + { |
2673 | + ZoomComboBox.ComboBox.Active = default_zoom; |
2674 | + UpdateCanvasScale (); |
2675 | + } |
2676 | + } |
2677 | + |
2678 | + private void HandlePintaCoreActionsViewZoomComboBoxComboBoxChanged (object sender, EventArgs e) |
2679 | + { |
2680 | + if (suspend_zoom_change) |
2681 | + return; |
2682 | + |
2683 | + PintaCore.Workspace.ActiveDocument.Workspace.ZoomManually (); |
2684 | + } |
2685 | + |
2686 | + private void HandlePintaCoreActionsViewZoomOutActivated (object sender, EventArgs e) |
2687 | + { |
2688 | + PintaCore.Workspace.ActiveDocument.Workspace.ZoomOut (); |
2689 | + } |
2690 | + |
2691 | + private void HandlePintaCoreActionsViewZoomInActivated (object sender, EventArgs e) |
2692 | + { |
2693 | + PintaCore.Workspace.ActiveDocument.Workspace.ZoomIn (); |
2694 | + } |
2695 | + #endregion |
2696 | + |
2697 | + /// <summary> |
2698 | + /// Returns the index in the ZoomCollection of the default zoom level |
2699 | + /// </summary> |
2700 | + private int DefaultZoomIndex() |
2701 | + { |
2702 | + return Array.IndexOf(ZoomCollection, "100%"); |
2703 | + } |
2704 | + } |
2705 | +} |
2706 | \ No newline at end of file |
2707 | |
2708 | === added file 'Pinta.Core/Actions/WindowActions.cs' |
2709 | --- Pinta.Core/Actions/WindowActions.cs 1970-01-01 00:00:00 +0000 |
2710 | +++ Pinta.Core/Actions/WindowActions.cs 2013-01-23 15:01:21 +0000 |
2711 | @@ -0,0 +1,153 @@ |
2712 | +// |
2713 | +// WindowActions.cs |
2714 | +// |
2715 | +// Author: |
2716 | +// Jonathan Pobst <monkey@jpobst.com> |
2717 | +// |
2718 | +// Copyright (c) 2010 Jonathan Pobst |
2719 | +// |
2720 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
2721 | +// of this software and associated documentation files (the "Software"), to deal |
2722 | +// in the Software without restriction, including without limitation the rights |
2723 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
2724 | +// copies of the Software, and to permit persons to whom the Software is |
2725 | +// furnished to do so, subject to the following conditions: |
2726 | +// |
2727 | +// The above copyright notice and this permission notice shall be included in |
2728 | +// all copies or substantial portions of the Software. |
2729 | +// |
2730 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
2731 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
2732 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
2733 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
2734 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
2735 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
2736 | +// THE SOFTWARE. |
2737 | + |
2738 | +using System; |
2739 | +using System.Linq; |
2740 | +using Gtk; |
2741 | +using Mono.Unix; |
2742 | +using System.Collections.Generic; |
2743 | + |
2744 | +namespace Pinta.Core |
2745 | +{ |
2746 | + public class WindowActions |
2747 | + { |
2748 | + private Menu window_menu; |
2749 | + private Dictionary<RadioAction, CheckMenuItem> action_menu_items; |
2750 | + |
2751 | + public Gtk.Action SaveAll { get; private set; } |
2752 | + public Gtk.Action CloseAll { get; private set; } |
2753 | + |
2754 | + public WindowActions () |
2755 | + { |
2756 | + SaveAll = new Gtk.Action ("SaveAll", Catalog.GetString ("Save All"), null, Stock.Save); |
2757 | + CloseAll = new Gtk.Action ("CloseAll", Catalog.GetString ("Close All"), null, Stock.Close); |
2758 | + |
2759 | + OpenWindows = new List<RadioAction> (); |
2760 | + action_menu_items = new Dictionary<RadioAction,CheckMenuItem> (); |
2761 | + } |
2762 | + |
2763 | + public List<RadioAction> OpenWindows { get; private set; } |
2764 | + |
2765 | + #region Initialization |
2766 | + public void CreateMainMenu (Gtk.Menu menu) |
2767 | + { |
2768 | + window_menu = menu; |
2769 | + |
2770 | + menu.Append (SaveAll.CreateAcceleratedMenuItem (Gdk.Key.L, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
2771 | + menu.Append (CloseAll.CreateAcceleratedMenuItem (Gdk.Key.W, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask)); |
2772 | + menu.AppendSeparator (); |
2773 | + } |
2774 | + #endregion |
2775 | + |
2776 | + #region Public Methods |
2777 | + public RadioAction AddDocument (Document doc) |
2778 | + { |
2779 | + RadioAction action = new RadioAction (doc.Guid.ToString (), doc.Filename, string.Empty, null, 0); |
2780 | + |
2781 | + // Tie these all together as a radio group |
2782 | + if (OpenWindows.Count > 0) |
2783 | + action.Group = OpenWindows[0].Group; |
2784 | + |
2785 | + action.Active = true; |
2786 | + action.Activated += (o, e) => { if ((o as Gtk.ToggleAction).Active) PintaCore.Workspace.SetActiveDocumentInternal (doc); }; |
2787 | + |
2788 | + OpenWindows.Add (action); |
2789 | + CheckMenuItem menuitem; |
2790 | + |
2791 | + // We only assign accelerators up to Alt-9 |
2792 | + if (OpenWindows.Count < 10) |
2793 | + menuitem = action.CreateAcceleratedMenuItem (IntegerToNumKey (OpenWindows.Count), Gdk.ModifierType.Mod1Mask); |
2794 | + else |
2795 | + menuitem = (CheckMenuItem)action.CreateMenuItem (); |
2796 | + |
2797 | + action_menu_items.Add (action, menuitem); |
2798 | + window_menu.Add (menuitem); |
2799 | + |
2800 | + doc.Renamed += (o, e) => { UpdateMenuLabel (action, o as Document); }; |
2801 | + doc.IsDirtyChanged += (o, e) => { UpdateMenuLabel (action, o as Document); }; |
2802 | + |
2803 | + return action; |
2804 | + } |
2805 | + |
2806 | + public void RemoveDocument (Document doc) |
2807 | + { |
2808 | + // Remove from our list of actions |
2809 | + RadioAction act = OpenWindows.Where (p => p.Name == doc.Guid.ToString ()).FirstOrDefault (); |
2810 | + OpenWindows.Remove (act); |
2811 | + |
2812 | + // Remove all the menu items from the menu |
2813 | + foreach (var item in action_menu_items.Values) { |
2814 | + window_menu.Remove (item); |
2815 | + item.Dispose (); |
2816 | + } |
2817 | + |
2818 | + action_menu_items.Clear (); |
2819 | + |
2820 | + // Recreate all of our menu items |
2821 | + // I tried simply changing the accelerators, but could |
2822 | + // no get it to work. |
2823 | + CheckMenuItem menuitem; |
2824 | + |
2825 | + for (int i = 0; i < OpenWindows.Count; i++) { |
2826 | + RadioAction action = OpenWindows[i]; |
2827 | + |
2828 | + if (i < 9) |
2829 | + menuitem = action.CreateAcceleratedMenuItem (IntegerToNumKey (i + 1), Gdk.ModifierType.Mod1Mask); |
2830 | + else |
2831 | + menuitem = (CheckMenuItem)action.CreateMenuItem (); |
2832 | + |
2833 | + action_menu_items.Add (action, menuitem); |
2834 | + window_menu.Add (menuitem); |
2835 | + } |
2836 | + } |
2837 | + #endregion |
2838 | + |
2839 | + #region Private Methods |
2840 | + private Gdk.Key IntegerToNumKey (int i) |
2841 | + { |
2842 | + switch (i) { |
2843 | + case 1: return Gdk.Key.Key_1; |
2844 | + case 2: return Gdk.Key.Key_2; |
2845 | + case 3: return Gdk.Key.Key_3; |
2846 | + case 4: return Gdk.Key.Key_4; |
2847 | + case 5: return Gdk.Key.Key_5; |
2848 | + case 6: return Gdk.Key.Key_6; |
2849 | + case 7: return Gdk.Key.Key_7; |
2850 | + case 8: return Gdk.Key.Key_8; |
2851 | + case 9: return Gdk.Key.Key_9; |
2852 | + } |
2853 | + |
2854 | + throw new ArgumentOutOfRangeException (string.Format ("IntegerToNumKey does not support: {0}", i)); |
2855 | + } |
2856 | + |
2857 | + private void UpdateMenuLabel (RadioAction action, Document doc) |
2858 | + { |
2859 | + action.Label = string.Format ("{0}{1}", doc.Filename, doc.IsDirty ? "*" : string.Empty); |
2860 | + PintaCore.Workspace.ResetTitle (); |
2861 | + } |
2862 | + #endregion |
2863 | + } |
2864 | +} |
2865 | |
2866 | === added directory 'Pinta.Core/Classes' |
2867 | === added file 'Pinta.Core/Classes/Anchor.cs' |
2868 | --- Pinta.Core/Classes/Anchor.cs 1970-01-01 00:00:00 +0000 |
2869 | +++ Pinta.Core/Classes/Anchor.cs 2013-01-23 15:01:21 +0000 |
2870 | @@ -0,0 +1,43 @@ |
2871 | +// |
2872 | +// Anchor.cs |
2873 | +// |
2874 | +// Author: |
2875 | +// Jonathan Pobst <monkey@jpobst.com> |
2876 | +// |
2877 | +// Copyright (c) 2010 Jonathan Pobst |
2878 | +// |
2879 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
2880 | +// of this software and associated documentation files (the "Software"), to deal |
2881 | +// in the Software without restriction, including without limitation the rights |
2882 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
2883 | +// copies of the Software, and to permit persons to whom the Software is |
2884 | +// furnished to do so, subject to the following conditions: |
2885 | +// |
2886 | +// The above copyright notice and this permission notice shall be included in |
2887 | +// all copies or substantial portions of the Software. |
2888 | +// |
2889 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
2890 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
2891 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
2892 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
2893 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
2894 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
2895 | +// THE SOFTWARE. |
2896 | + |
2897 | +using System; |
2898 | + |
2899 | +namespace Pinta.Core |
2900 | +{ |
2901 | + public enum Anchor |
2902 | + { |
2903 | + NW, |
2904 | + N, |
2905 | + NE, |
2906 | + E, |
2907 | + SE, |
2908 | + S, |
2909 | + SW, |
2910 | + W, |
2911 | + Center |
2912 | + } |
2913 | +} |
2914 | |
2915 | === added file 'Pinta.Core/Classes/AsyncEffectRenderer.cs' |
2916 | --- Pinta.Core/Classes/AsyncEffectRenderer.cs 1970-01-01 00:00:00 +0000 |
2917 | +++ Pinta.Core/Classes/AsyncEffectRenderer.cs 2013-01-23 15:01:21 +0000 |
2918 | @@ -0,0 +1,361 @@ |
2919 | +// |
2920 | +// AsyncEffectRenderer.cs |
2921 | +// |
2922 | +// Author: |
2923 | +// Greg Lowe <greg@vis.net.nz> |
2924 | +// |
2925 | +// Copyright (c) 2010 Greg Lowe |
2926 | +// |
2927 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
2928 | +// of this software and associated documentation files (the "Software"), to deal |
2929 | +// in the Software without restriction, including without limitation the rights |
2930 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
2931 | +// copies of the Software, and to permit persons to whom the Software is |
2932 | +// furnished to do so, subject to the following conditions: |
2933 | +// |
2934 | +// The above copyright notice and this permission notice shall be included in |
2935 | +// all copies or substantial portions of the Software. |
2936 | +// |
2937 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
2938 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
2939 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
2940 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
2941 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
2942 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
2943 | +// THE SOFTWARE. |
2944 | + |
2945 | +#if (!LIVE_PREVIEW_DEBUG && DEBUG) |
2946 | +#undef DEBUG |
2947 | +#endif |
2948 | + |
2949 | +using System; |
2950 | +using System.Collections.Generic; |
2951 | +using System.Threading; |
2952 | +using Debug = System.Diagnostics.Debug; |
2953 | + |
2954 | +namespace Pinta.Core |
2955 | +{ |
2956 | + |
2957 | + // Only call methods on this class from a single thread (The UI thread). |
2958 | + internal abstract class AsyncEffectRenderer |
2959 | + { |
2960 | + Settings settings; |
2961 | + |
2962 | + internal struct Settings { |
2963 | + internal int ThreadCount { get; set; } |
2964 | + internal int TileWidth { get; set; } |
2965 | + internal int TileHeight { get; set; } |
2966 | + internal int UpdateMillis { get; set; } |
2967 | + internal ThreadPriority ThreadPriority { get; set; } |
2968 | + } |
2969 | + |
2970 | + BaseEffect effect; |
2971 | + Cairo.ImageSurface source_surface; |
2972 | + Cairo.ImageSurface dest_surface; |
2973 | + Gdk.Rectangle render_bounds; |
2974 | + |
2975 | + bool is_rendering; |
2976 | + bool cancel_render_flag; |
2977 | + bool restart_render_flag; |
2978 | + int render_id; |
2979 | + int current_tile; |
2980 | + int total_tiles; |
2981 | + List<Exception> render_exceptions; |
2982 | + |
2983 | + uint timer_tick_id; |
2984 | + |
2985 | + object updated_lock; |
2986 | + bool is_updated; |
2987 | + int updated_x1; |
2988 | + int updated_y1; |
2989 | + int updated_x2; |
2990 | + int updated_y2; |
2991 | + |
2992 | + internal AsyncEffectRenderer (Settings settings) |
2993 | + { |
2994 | + if (settings.ThreadCount < 1) |
2995 | + settings.ThreadCount = 1; |
2996 | + |
2997 | + if (settings.TileWidth < 1) |
2998 | + throw new ArgumentException ("EffectRenderSettings.TileWidth"); |
2999 | + |
3000 | + if (settings.TileHeight < 1) |
3001 | + throw new ArgumentException ("EffectRenderSettings.TileHeight"); |
3002 | + |
3003 | + if (settings.UpdateMillis <= 0) |
3004 | + settings.UpdateMillis = 100; |
3005 | + |
3006 | + effect = null; |
3007 | + source_surface = null; |
3008 | + dest_surface = null; |
3009 | + this.settings = settings; |
3010 | + |
3011 | + is_rendering = false; |
3012 | + render_id = 0; |
3013 | + updated_lock = new object (); |
3014 | + is_updated = false; |
3015 | + render_exceptions = new List<Exception> (); |
3016 | + |
3017 | + timer_tick_id = 0; |
3018 | + } |
3019 | + |
3020 | + internal bool IsRendering { |
3021 | + get { return is_rendering; } |
3022 | + } |
3023 | + |
3024 | + internal double Progress { |
3025 | + get { |
3026 | + if (total_tiles == 0 || current_tile < 0) |
3027 | + return 0; |
3028 | + else if (current_tile < total_tiles) |
3029 | + return (double)current_tile / (double)total_tiles; |
3030 | + else |
3031 | + return 1; |
3032 | + } |
3033 | + } |
3034 | + |
3035 | + internal void Start (BaseEffect effect, |
3036 | + Cairo.ImageSurface source, |
3037 | + Cairo.ImageSurface dest, |
3038 | + Gdk.Rectangle renderBounds) |
3039 | + { |
3040 | + Debug.WriteLine ("AsyncEffectRenderer.Start ()"); |
3041 | + |
3042 | + if (effect == null) |
3043 | + throw new ArgumentNullException ("effect"); |
3044 | + |
3045 | + if (source == null) |
3046 | + throw new ArgumentNullException ("source"); |
3047 | + |
3048 | + if (dest == null) |
3049 | + throw new ArgumentNullException ("dest"); |
3050 | + |
3051 | + if (renderBounds.IsEmpty) |
3052 | + throw new ArgumentException ("renderBounds.IsEmpty"); |
3053 | + |
3054 | + // It is important the effect's properties don't change during rendering. |
3055 | + // So a copy is made for the render. |
3056 | + this.effect = effect.Clone(); |
3057 | + |
3058 | + this.source_surface = source; |
3059 | + this.dest_surface = dest; |
3060 | + this.render_bounds = renderBounds; |
3061 | + |
3062 | + // If a render is already in progress, then cancel it, |
3063 | + // and start a new render. |
3064 | + if (IsRendering) { |
3065 | + cancel_render_flag = true; |
3066 | + restart_render_flag = true; |
3067 | + return; |
3068 | + } |
3069 | + |
3070 | + StartRender (); |
3071 | + } |
3072 | + |
3073 | + internal void Cancel () |
3074 | + { |
3075 | + Debug.WriteLine ("AsyncEffectRenderer.Cancel ()"); |
3076 | + cancel_render_flag = true; |
3077 | + restart_render_flag = false; |
3078 | + |
3079 | + if (!IsRendering) |
3080 | + HandleRenderCompletion (); |
3081 | + } |
3082 | + |
3083 | + protected abstract void OnUpdate (double progress, Gdk.Rectangle updatedBounds); |
3084 | + |
3085 | + protected abstract void OnCompletion (bool canceled, Exception[] exceptions); |
3086 | + |
3087 | + internal void Dispose () |
3088 | + { |
3089 | + if (timer_tick_id > 0) |
3090 | + GLib.Source.Remove (timer_tick_id); |
3091 | + } |
3092 | + |
3093 | + void StartRender () |
3094 | + { |
3095 | + is_rendering = true; |
3096 | + cancel_render_flag = false; |
3097 | + restart_render_flag = false; |
3098 | + is_updated = false; |
3099 | + |
3100 | + render_id++; |
3101 | + render_exceptions.Clear (); |
3102 | + |
3103 | + current_tile = -1; |
3104 | + |
3105 | + total_tiles = CalculateTotalTiles (); |
3106 | + |
3107 | + Debug.WriteLine ("AsyncEffectRenderer.Start () Render " + render_id + " starting."); |
3108 | + |
3109 | + // Copy the current render id. |
3110 | + int renderId = render_id; |
3111 | + |
3112 | + // Start slave render threads. |
3113 | + int threadCount = settings.ThreadCount; |
3114 | + var slaves = new Thread[threadCount - 1]; |
3115 | + for (int threadId = 1; threadId < threadCount; threadId++) |
3116 | + slaves[threadId - 1] = StartSlaveThread (renderId, threadId); |
3117 | + |
3118 | + // Start the master render thread. |
3119 | + var master = new Thread (() => { |
3120 | + |
3121 | + // Do part of the rendering on the master thread. |
3122 | + Render (renderId, 0); |
3123 | + |
3124 | + // Wait for slave threads to complete. |
3125 | + foreach (var slave in slaves) |
3126 | + slave.Join (); |
3127 | + |
3128 | + // Change back to the UI thread to notify of completion. |
3129 | + Gtk.Application.Invoke ((o,e) => HandleRenderCompletion ()); |
3130 | + }); |
3131 | + |
3132 | + master.Priority = settings.ThreadPriority; |
3133 | + master.Start (); |
3134 | + |
3135 | + // Start timer used to periodically fire update events on the UI thread. |
3136 | + timer_tick_id = GLib.Timeout.Add((uint) settings.UpdateMillis, HandleTimerTick); |
3137 | + } |
3138 | + |
3139 | + Thread StartSlaveThread (int renderId, int threadId) |
3140 | + { |
3141 | + var slave = new Thread(() => { |
3142 | + Render (renderId, threadId); |
3143 | + }); |
3144 | + |
3145 | + slave.Priority = settings.ThreadPriority; |
3146 | + slave.Start (); |
3147 | + |
3148 | + return slave; |
3149 | + } |
3150 | + |
3151 | + // Runs on a background thread. |
3152 | + void Render (int renderId, int threadId) |
3153 | + { |
3154 | + // Fetch the next tile index and render it. |
3155 | + for (;;) { |
3156 | + |
3157 | + int tileIndex = Interlocked.Increment (ref current_tile); |
3158 | + |
3159 | + if (tileIndex >= total_tiles || cancel_render_flag) |
3160 | + return; |
3161 | + |
3162 | + RenderTile (renderId, threadId, tileIndex); |
3163 | + } |
3164 | + } |
3165 | + |
3166 | + // Runs on a background thread. |
3167 | + void RenderTile (int renderId, int threadId, int tileIndex) |
3168 | + { |
3169 | + Exception exception = null; |
3170 | + Gdk.Rectangle bounds = new Gdk.Rectangle (); |
3171 | + |
3172 | + try { |
3173 | + |
3174 | + bounds = GetTileBounds (tileIndex); |
3175 | + |
3176 | + if (!cancel_render_flag) { |
3177 | + dest_surface.Flush (); |
3178 | + effect.Render (source_surface, dest_surface, new [] { bounds }); |
3179 | + dest_surface.MarkDirty (bounds.ToCairoRectangle ()); |
3180 | + } |
3181 | + |
3182 | + } catch (Exception ex) { |
3183 | + exception = ex; |
3184 | + Debug.WriteLine ("AsyncEffectRenderer Error while rendering effect: " + effect.Name + " exception: " + ex.Message + "\n" + ex.StackTrace); |
3185 | + } |
3186 | + |
3187 | + // Ignore completions of tiles after a cancel or from a previous render. |
3188 | + if (!IsRendering || renderId != render_id) |
3189 | + return; |
3190 | + |
3191 | + // Update bounds to be shown on next expose. |
3192 | + lock (updated_lock) { |
3193 | + if (is_updated) { |
3194 | + updated_x1 = Math.Min (bounds.X, updated_x1); |
3195 | + updated_y1 = Math.Min (bounds.Y, updated_y1); |
3196 | + updated_x2 = Math.Max (bounds.X + bounds.Width, updated_x2); |
3197 | + updated_y2 = Math.Max (bounds.Y + bounds.Height, updated_y2); |
3198 | + } else { |
3199 | + is_updated = true; |
3200 | + updated_x1 = bounds.X; |
3201 | + updated_y1 = bounds.Y; |
3202 | + updated_x2 = bounds.X + bounds.Width; |
3203 | + updated_y2 = bounds.Y + bounds.Height; |
3204 | + } |
3205 | + } |
3206 | + |
3207 | + if (exception != null) { |
3208 | + lock (render_exceptions) { |
3209 | + render_exceptions.Add (exception); |
3210 | + } |
3211 | + } |
3212 | + } |
3213 | + |
3214 | + // Runs on a background thread. |
3215 | + Gdk.Rectangle GetTileBounds (int tileIndex) |
3216 | + { |
3217 | + int horizTileCount = (int)Math.Ceiling((float)render_bounds.Width |
3218 | + / (float)settings.TileWidth); |
3219 | + |
3220 | + int x = ((tileIndex % horizTileCount) * settings.TileWidth) + render_bounds.X; |
3221 | + int y = ((tileIndex / horizTileCount) * settings.TileHeight) + render_bounds.Y; |
3222 | + int w = Math.Min(settings.TileWidth, render_bounds.Right - x); |
3223 | + int h = Math.Min(settings.TileHeight, render_bounds.Bottom - y); |
3224 | + |
3225 | + return new Gdk.Rectangle (x, y, w, h); |
3226 | + } |
3227 | + |
3228 | + int CalculateTotalTiles () |
3229 | + { |
3230 | + return (int)(Math.Ceiling((float)render_bounds.Width / (float)settings.TileWidth) |
3231 | + * Math.Ceiling((float)render_bounds.Height / (float)settings.TileHeight)); |
3232 | + } |
3233 | + |
3234 | + // Called on the UI thread. |
3235 | + bool HandleTimerTick () |
3236 | + { |
3237 | + Debug.WriteLine (DateTime.Now.ToString("HH:mm:ss:ffff") + " Timer tick."); |
3238 | + |
3239 | + Gdk.Rectangle bounds; |
3240 | + |
3241 | + lock (updated_lock) { |
3242 | + |
3243 | + if (!is_updated) |
3244 | + return true; |
3245 | + |
3246 | + is_updated = false; |
3247 | + |
3248 | + bounds = new Gdk.Rectangle (updated_x1, |
3249 | + updated_y1, |
3250 | + updated_x2 - updated_x1, |
3251 | + updated_y2 - updated_y1); |
3252 | + } |
3253 | + |
3254 | + if (IsRendering && !cancel_render_flag) |
3255 | + OnUpdate (Progress, bounds); |
3256 | + |
3257 | + return true; |
3258 | + } |
3259 | + |
3260 | + void HandleRenderCompletion () |
3261 | + { |
3262 | + var exceptions = (render_exceptions == null || render_exceptions.Count == 0) |
3263 | + ? null |
3264 | + : render_exceptions.ToArray (); |
3265 | + |
3266 | + HandleTimerTick (); |
3267 | + |
3268 | + if (timer_tick_id > 0) |
3269 | + GLib.Source.Remove (timer_tick_id); |
3270 | + |
3271 | + OnCompletion (cancel_render_flag, exceptions); |
3272 | + |
3273 | + if (restart_render_flag) |
3274 | + StartRender (); |
3275 | + else |
3276 | + is_rendering = false; |
3277 | + } |
3278 | + } |
3279 | +} |
3280 | |
3281 | === added file 'Pinta.Core/Classes/BaseExtension.cs' |
3282 | --- Pinta.Core/Classes/BaseExtension.cs 1970-01-01 00:00:00 +0000 |
3283 | +++ Pinta.Core/Classes/BaseExtension.cs 2013-01-23 15:01:21 +0000 |
3284 | @@ -0,0 +1,41 @@ |
3285 | +// |
3286 | +// BaseExtension.cs |
3287 | +// |
3288 | +// Author: |
3289 | +// Jonathan Pobst <monkey@jpobst.com> |
3290 | +// |
3291 | +// Copyright (c) 2010 Jonathan Pobst |
3292 | +// |
3293 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
3294 | +// of this software and associated documentation files (the "Software"), to deal |
3295 | +// in the Software without restriction, including without limitation the rights |
3296 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
3297 | +// copies of the Software, and to permit persons to whom the Software is |
3298 | +// furnished to do so, subject to the following conditions: |
3299 | +// |
3300 | +// The above copyright notice and this permission notice shall be included in |
3301 | +// all copies or substantial portions of the Software. |
3302 | +// |
3303 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
3304 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
3305 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
3306 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
3307 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
3308 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
3309 | +// THE SOFTWARE. |
3310 | + |
3311 | + |
3312 | +using System; |
3313 | + |
3314 | +namespace Pinta.Core |
3315 | +{ |
3316 | + public class BaseExtension |
3317 | + { |
3318 | + /// <summary> |
3319 | + /// Called during startup, perform any necessary initialization here |
3320 | + /// </summary> |
3321 | + public virtual void Initialize () |
3322 | + { |
3323 | + } |
3324 | + } |
3325 | +} |
3326 | |
3327 | === added file 'Pinta.Core/Classes/BasePaintBrush.cs' |
3328 | --- Pinta.Core/Classes/BasePaintBrush.cs 1970-01-01 00:00:00 +0000 |
3329 | +++ Pinta.Core/Classes/BasePaintBrush.cs 2013-01-23 15:01:21 +0000 |
3330 | @@ -0,0 +1,42 @@ |
3331 | +// |
3332 | +// BasePaintBrush.cs |
3333 | +// |
3334 | +// Author: |
3335 | +// Aaron Bockover <abockover@novell.com> |
3336 | +// |
3337 | +// Copyright (c) 2010 Novell, Inc. |
3338 | +// |
3339 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
3340 | +// of this software and associated documentation files (the "Software"), to deal |
3341 | +// in the Software without restriction, including without limitation the rights |
3342 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
3343 | +// copies of the Software, and to permit persons to whom the Software is |
3344 | +// furnished to do so, subject to the following conditions: |
3345 | +// |
3346 | +// The above copyright notice and this permission notice shall be included in |
3347 | +// all copies or substantial portions of the Software. |
3348 | +// |
3349 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
3350 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
3351 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
3352 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
3353 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
3354 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
3355 | +// THE SOFTWARE. |
3356 | + |
3357 | +using System; |
3358 | +using Mono.Addins; |
3359 | + |
3360 | +namespace Pinta.Core |
3361 | +{ |
3362 | + [TypeExtensionPoint] |
3363 | + public abstract class BasePaintBrush |
3364 | + { |
3365 | + public abstract string Name { get; } |
3366 | + |
3367 | + public virtual int Priority { |
3368 | + get { return 0; } |
3369 | + } |
3370 | + } |
3371 | +} |
3372 | + |
3373 | |
3374 | === added file 'Pinta.Core/Classes/BaseTool.cs' |
3375 | --- Pinta.Core/Classes/BaseTool.cs 1970-01-01 00:00:00 +0000 |
3376 | +++ Pinta.Core/Classes/BaseTool.cs 2013-01-23 15:01:21 +0000 |
3377 | @@ -0,0 +1,276 @@ |
3378 | +// |
3379 | +// BaseTool.cs |
3380 | +// |
3381 | +// Author: |
3382 | +// Jonathan Pobst <monkey@jpobst.com> |
3383 | +// |
3384 | +// Copyright (c) 2010 Jonathan Pobst |
3385 | +// |
3386 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
3387 | +// of this software and associated documentation files (the "Software"), to deal |
3388 | +// in the Software without restriction, including without limitation the rights |
3389 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
3390 | +// copies of the Software, and to permit persons to whom the Software is |
3391 | +// furnished to do so, subject to the following conditions: |
3392 | +// |
3393 | +// The above copyright notice and this permission notice shall be included in |
3394 | +// all copies or substantial portions of the Software. |
3395 | +// |
3396 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
3397 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
3398 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
3399 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
3400 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
3401 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
3402 | +// THE SOFTWARE. |
3403 | + |
3404 | +using System; |
3405 | +using Cairo; |
3406 | +using Gtk; |
3407 | +using System.IO; |
3408 | +using Mono.Unix; |
3409 | +using Mono.Addins; |
3410 | + |
3411 | +namespace Pinta.Core |
3412 | +{ |
3413 | + public delegate void MouseHandler (double x, double y, Gdk.ModifierType state); |
3414 | + |
3415 | + [TypeExtensionPoint] |
3416 | + public abstract class BaseTool |
3417 | + { |
3418 | + protected const int DEFAULT_BRUSH_WIDTH = 2; |
3419 | + |
3420 | + protected static Point point_empty = new Point (-500, -500); |
3421 | + |
3422 | + protected ToggleToolButton tool_item; |
3423 | + protected ToolItem tool_label; |
3424 | + protected ToolItem tool_image; |
3425 | + protected ToolItem tool_sep; |
3426 | + protected ToolBarDropDownButton antialiasing_button; |
3427 | + protected ToolBarDropDownButton alphablending_button; |
3428 | + public event MouseHandler MouseMoved; |
3429 | + public event MouseHandler MousePressed; |
3430 | + public event MouseHandler MouseReleased; |
3431 | + |
3432 | + protected BaseTool () |
3433 | + { |
3434 | + } |
3435 | + |
3436 | + static BaseTool () |
3437 | + { |
3438 | + Gtk.IconFactory fact = new Gtk.IconFactory (); |
3439 | + fact.Add ("Toolbar.AntiAliasingEnabledIcon.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Toolbar.AntiAliasingEnabledIcon.png"))); |
3440 | + fact.Add ("Toolbar.AntiAliasingDisabledIcon.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Toolbar.AntiAliasingDisabledIcon.png"))); |
3441 | + fact.Add ("Toolbar.BlendingEnabledIcon.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Toolbar.BlendingEnabledIcon.png"))); |
3442 | + fact.Add ("Toolbar.BlendingOverwriteIcon.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Toolbar.BlendingOverwriteIcon.png"))); |
3443 | + fact.Add ("Tools.FreeformShape.png", new Gtk.IconSet (PintaCore.Resources.GetIcon ("Tools.FreeformShape.png"))); |
3444 | + fact.AddDefault (); |
3445 | + } |
3446 | + |
3447 | + public virtual string Name { get { throw new ApplicationException ("Tool didn't override Name"); } } |
3448 | + public virtual string Icon { get { throw new ApplicationException ("Tool didn't override Icon"); } } |
3449 | + public virtual string ToolTip { get { throw new ApplicationException ("Tool didn't override ToolTip"); } } |
3450 | + public virtual string StatusBarText { get { return string.Empty; } } |
3451 | + public virtual ToggleToolButton ToolItem { get { if (tool_item == null) tool_item = CreateToolButton (); return tool_item; } } |
3452 | + public virtual bool Enabled { get { return true; } } |
3453 | + public virtual Gdk.Cursor DefaultCursor { get { return null; } } |
3454 | + public virtual Gdk.Key ShortcutKey { get { return (Gdk.Key)0; } } |
3455 | + public virtual bool UseAntialiasing { get { return ShowAntialiasingButton && (bool)antialiasing_button.SelectedItem.Tag; } } |
3456 | + public virtual bool UseAlphaBlending { get { return ShowAlphaBlendingButton && (bool)alphablending_button.SelectedItem.Tag; } } |
3457 | + public virtual int Priority { get { return 75; } } |
3458 | + |
3459 | + protected virtual bool ShowAntialiasingButton { get { return false; } } |
3460 | + protected virtual bool ShowAlphaBlendingButton { get { return false; } } |
3461 | + |
3462 | + #region Public Methods |
3463 | + public void DoMouseMove (object o, MotionNotifyEventArgs args, Cairo.PointD point) |
3464 | + { |
3465 | + if (MouseMoved != null) |
3466 | + MouseMoved (point.X, point.Y, args.Event.State); |
3467 | + OnMouseMove (o, args, point); |
3468 | + } |
3469 | + |
3470 | + public void DoBuildToolBar (Toolbar tb) |
3471 | + { |
3472 | + OnBuildToolBar (tb); |
3473 | + BuildRasterizationToolItems (tb); |
3474 | + } |
3475 | + |
3476 | + public void DoClearToolBar (Toolbar tb) |
3477 | + { |
3478 | + OnClearToolBar (tb); |
3479 | + } |
3480 | + |
3481 | + public void DoMouseDown (DrawingArea canvas, ButtonPressEventArgs args, Cairo.PointD point) |
3482 | + { |
3483 | + if (MousePressed != null) |
3484 | + MousePressed (point.X, point.Y, args.Event.State); |
3485 | + OnMouseDown (canvas, args, point); |
3486 | + } |
3487 | + |
3488 | + public void DoMouseUp (DrawingArea canvas, ButtonReleaseEventArgs args, Cairo.PointD point) |
3489 | + { |
3490 | + if (MouseReleased != null) |
3491 | + MouseReleased (point.X, point.Y, args.Event.State); |
3492 | + OnMouseUp (canvas, args, point); |
3493 | + } |
3494 | + |
3495 | + public void DoCommit () |
3496 | + { |
3497 | + OnCommit (); |
3498 | + } |
3499 | + |
3500 | + public void DoActivated () |
3501 | + { |
3502 | + OnActivated (); |
3503 | + } |
3504 | + |
3505 | + public void DoDeactivated () |
3506 | + { |
3507 | + OnDeactivated (); |
3508 | + } |
3509 | + |
3510 | + // Return true if the key was consumed. |
3511 | + public void DoKeyPress (DrawingArea canvas, KeyPressEventArgs args) |
3512 | + { |
3513 | + OnKeyDown (canvas, args); |
3514 | + } |
3515 | + |
3516 | + public void DoKeyRelease (DrawingArea canvas, KeyReleaseEventArgs args) |
3517 | + { |
3518 | + OnKeyUp (canvas, args); |
3519 | + } |
3520 | + #endregion |
3521 | + |
3522 | + #region Protected Methods |
3523 | + protected virtual void OnMouseMove (object o, Gtk.MotionNotifyEventArgs args, Cairo.PointD point) |
3524 | + { |
3525 | + } |
3526 | + |
3527 | + protected virtual void BuildRasterizationToolItems (Toolbar tb) |
3528 | + { |
3529 | + if (ShowAlphaBlendingButton || ShowAntialiasingButton) |
3530 | + tb.AppendItem (new SeparatorToolItem ()); |
3531 | + |
3532 | + if (ShowAntialiasingButton) |
3533 | + BuildAntialiasingTool (tb); |
3534 | + if (ShowAlphaBlendingButton) |
3535 | + BuildAlphaBlending (tb); |
3536 | + } |
3537 | + |
3538 | + protected virtual void OnBuildToolBar (Toolbar tb) |
3539 | + { |
3540 | + if (tool_label == null) |
3541 | + tool_label = new ToolBarLabel (string.Format (" {0}: ", Catalog.GetString ("Tool"))); |
3542 | + |
3543 | + tb.AppendItem (tool_label); |
3544 | + |
3545 | + if (tool_image == null) |
3546 | + tool_image = new ToolBarImage (Icon); |
3547 | + |
3548 | + tb.AppendItem (tool_image); |
3549 | + |
3550 | + if (tool_sep == null) |
3551 | + tool_sep = new SeparatorToolItem (); |
3552 | + |
3553 | + tb.AppendItem (tool_sep); |
3554 | + } |
3555 | + |
3556 | + protected virtual void OnClearToolBar (Toolbar tb) |
3557 | + { |
3558 | + while (tb.NItems > 0) |
3559 | + tb.Remove (tb.Children[tb.NItems - 1]); |
3560 | + } |
3561 | + |
3562 | + protected virtual void OnMouseDown (DrawingArea canvas, Gtk.ButtonPressEventArgs args, Cairo.PointD point) |
3563 | + { |
3564 | + } |
3565 | + |
3566 | + protected virtual void OnMouseUp (DrawingArea canvas, Gtk.ButtonReleaseEventArgs args, Cairo.PointD point) |
3567 | + { |
3568 | + } |
3569 | + |
3570 | + protected virtual void OnKeyDown (DrawingArea canvas, Gtk.KeyPressEventArgs args) |
3571 | + { |
3572 | + } |
3573 | + |
3574 | + protected virtual void OnKeyUp (DrawingArea canvas, Gtk.KeyReleaseEventArgs args) |
3575 | + { |
3576 | + } |
3577 | + |
3578 | + /// <summary> |
3579 | + /// This is called whenever a menu option is called, for |
3580 | + /// tools that are in a temporary state while being used, and |
3581 | + /// need to commit their work when another option is selected. |
3582 | + /// </summary> |
3583 | + protected virtual void OnCommit () |
3584 | + { |
3585 | + } |
3586 | + |
3587 | + protected virtual void OnActivated () |
3588 | + { |
3589 | + SetCursor (DefaultCursor); |
3590 | + } |
3591 | + |
3592 | + protected virtual void OnDeactivated () |
3593 | + { |
3594 | + SetCursor (null); |
3595 | + } |
3596 | + |
3597 | + protected virtual ToggleToolButton CreateToolButton () |
3598 | + { |
3599 | + Image i2 = new Image (PintaCore.Resources.GetIcon (Icon)); |
3600 | + i2.Show (); |
3601 | + |
3602 | + ToggleToolButton tool_item = new ToggleToolButton (); |
3603 | + tool_item.IconWidget = i2; |
3604 | + tool_item.Show (); |
3605 | + tool_item.Label = Name; |
3606 | + |
3607 | + if (ShortcutKey != (Gdk.Key)0) |
3608 | + tool_item.TooltipText = string.Format ("{0}\n{2}: {1}\n\n{3}", Name, ShortcutKey.ToString ().ToUpperInvariant (), Catalog.GetString ("Shortcut key"), StatusBarText); |
3609 | + else |
3610 | + tool_item.TooltipText = Name; |
3611 | + |
3612 | + return tool_item; |
3613 | + } |
3614 | + |
3615 | + protected void SetCursor (Gdk.Cursor cursor) |
3616 | + { |
3617 | + PintaCore.Chrome.Canvas.GdkWindow.Cursor = cursor; |
3618 | + } |
3619 | + #endregion |
3620 | + |
3621 | + #region Private Methods |
3622 | + private void BuildAlphaBlending (Toolbar tb) |
3623 | + { |
3624 | + if (alphablending_button != null) { |
3625 | + tb.AppendItem (alphablending_button); |
3626 | + return; |
3627 | + } |
3628 | + |
3629 | + alphablending_button = new ToolBarDropDownButton (); |
3630 | + |
3631 | + alphablending_button.AddItem (Catalog.GetString ("Normal Blending"), "Toolbar.BlendingEnabledIcon.png", true); |
3632 | + alphablending_button.AddItem (Catalog.GetString ("Overwrite"), "Toolbar.BlendingOverwriteIcon.png", false); |
3633 | + |
3634 | + tb.AppendItem (alphablending_button); |
3635 | + } |
3636 | + |
3637 | + private void BuildAntialiasingTool (Toolbar tb) |
3638 | + { |
3639 | + if (antialiasing_button != null) { |
3640 | + tb.AppendItem (antialiasing_button); |
3641 | + return; |
3642 | + } |
3643 | + |
3644 | + antialiasing_button = new ToolBarDropDownButton (); |
3645 | + |
3646 | + antialiasing_button.AddItem (Catalog.GetString ("Antialiasing On"), "Toolbar.AntiAliasingEnabledIcon.png", true); |
3647 | + antialiasing_button.AddItem (Catalog.GetString ("Antialiasing Off"), "Toolbar.AntiAliasingDisabledIcon.png", false); |
3648 | + |
3649 | + tb.AppendItem (antialiasing_button); |
3650 | + } |
3651 | + #endregion |
3652 | + } |
3653 | +} |
3654 | |
3655 | === added file 'Pinta.Core/Classes/Document.cs' |
3656 | --- Pinta.Core/Classes/Document.cs 1970-01-01 00:00:00 +0000 |
3657 | +++ Pinta.Core/Classes/Document.cs 2013-01-23 15:01:21 +0000 |
3658 | @@ -0,0 +1,735 @@ |
3659 | +// |
3660 | +// Document.cs |
3661 | +// |
3662 | +// Author: |
3663 | +// Jonathan Pobst <monkey@jpobst.com> |
3664 | +// |
3665 | +// Copyright (c) 2010 Jonathan Pobst |
3666 | +// |
3667 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
3668 | +// of this software and associated documentation files (the "Software"), to deal |
3669 | +// in the Software without restriction, including without limitation the rights |
3670 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
3671 | +// copies of the Software, and to permit persons to whom the Software is |
3672 | +// furnished to do so, subject to the following conditions: |
3673 | +// |
3674 | +// The above copyright notice and this permission notice shall be included in |
3675 | +// all copies or substantial portions of the Software. |
3676 | +// |
3677 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
3678 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
3679 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
3680 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
3681 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
3682 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
3683 | +// THE SOFTWARE. |
3684 | + |
3685 | +using System; |
3686 | +using System.Linq; |
3687 | +using Mono.Unix; |
3688 | +using Gdk; |
3689 | +using System.Collections.Generic; |
3690 | +using Cairo; |
3691 | +using System.ComponentModel; |
3692 | + |
3693 | +namespace Pinta.Core |
3694 | +{ |
3695 | + // The differentiation between Document and DocumentWorkspace is |
3696 | + // somewhat arbitrary. In general: |
3697 | + // Document - Data about the image itself |
3698 | + // Workspace - Data about Pinta's state for the image |
3699 | + public class Document |
3700 | + { |
3701 | + private string filename; |
3702 | + private bool is_dirty; |
3703 | + private int layer_name_int = 2; |
3704 | + private int current_layer = -1; |
3705 | + |
3706 | + // The layer for tools to use until their output is committed |
3707 | + private Layer tool_layer; |
3708 | + // The layer used for selections |
3709 | + private Layer selection_layer; |
3710 | + |
3711 | + private int selection_layer_index; |
3712 | + private Path selection_path; |
3713 | + private bool show_selection; |
3714 | + |
3715 | + public Document (Gdk.Size size) |
3716 | + { |
3717 | + Guid = Guid.NewGuid (); |
3718 | + |
3719 | + Workspace = new DocumentWorkspace (this); |
3720 | + IsDirty = false; |
3721 | + HasFile = false; |
3722 | + ImageSize = size; |
3723 | + |
3724 | + Layers = new List<Layer> (); |
3725 | + |
3726 | + tool_layer = CreateLayer ("Tool Layer"); |
3727 | + tool_layer.Hidden = true; |
3728 | + |
3729 | + selection_layer = CreateLayer ("Selection Layer"); |
3730 | + selection_layer.Hidden = true; |
3731 | + |
3732 | + ResetSelectionPath (); |
3733 | + } |
3734 | + |
3735 | + #region Public Properties |
3736 | + public Layer CurrentLayer { |
3737 | + get { return Layers[current_layer]; } |
3738 | + } |
3739 | + |
3740 | + public int CurrentLayerIndex { |
3741 | + get { return current_layer; } |
3742 | + } |
3743 | + |
3744 | + /// <summary> |
3745 | + /// Just the file name, like "dog.jpg". |
3746 | + /// </summary> |
3747 | + public string Filename { |
3748 | + get { return filename; } |
3749 | + set { |
3750 | + if (filename != value) { |
3751 | + filename = value; |
3752 | + OnRenamed (); |
3753 | + } |
3754 | + } |
3755 | + } |
3756 | + |
3757 | + public Guid Guid { get; private set; } |
3758 | + |
3759 | + public bool HasFile { get; set; } |
3760 | + |
3761 | + public DocumentWorkspaceHistory History { get { return Workspace.History; } } |
3762 | + |
3763 | + public Gdk.Size ImageSize { get; set; } |
3764 | + |
3765 | + public bool IsDirty { |
3766 | + get { return is_dirty; } |
3767 | + set { |
3768 | + if (is_dirty != value) { |
3769 | + is_dirty = value; |
3770 | + OnIsDirtyChanged (); |
3771 | + } |
3772 | + } |
3773 | + } |
3774 | + |
3775 | + public List<Layer> Layers { get; private set; } |
3776 | + |
3777 | + /// <summary> |
3778 | + /// Just the directory name, like "C:\MyPictures". |
3779 | + /// </summary> |
3780 | + public string Pathname { get; set; } |
3781 | + |
3782 | + /// <summary> |
3783 | + /// Directory and file name, like "C:\MyPictures\dog.jpg". |
3784 | + /// </summary> |
3785 | + public string PathAndFileName { |
3786 | + get { return System.IO.Path.Combine (Pathname, Filename); } |
3787 | + set { |
3788 | + if (string.IsNullOrEmpty (value)) { |
3789 | + Pathname = string.Empty; |
3790 | + Filename = string.Empty; |
3791 | + } else { |
3792 | + Pathname = System.IO.Path.GetDirectoryName (value); |
3793 | + Filename = System.IO.Path.GetFileName (value); |
3794 | + } |
3795 | + } |
3796 | + } |
3797 | + |
3798 | + public Layer SelectionLayer { |
3799 | + get { return selection_layer; } |
3800 | + } |
3801 | + |
3802 | + public Path SelectionPath { |
3803 | + get { return selection_path; } |
3804 | + set { |
3805 | + if (selection_path == value) |
3806 | + return; |
3807 | + |
3808 | + selection_path = value; |
3809 | + } |
3810 | + } |
3811 | + |
3812 | + public bool ShowSelection { |
3813 | + get { return show_selection; } |
3814 | + set { |
3815 | + show_selection = value; |
3816 | + PintaCore.Actions.Edit.Deselect.Sensitive = show_selection; |
3817 | + PintaCore.Actions.Edit.EraseSelection.Sensitive = show_selection; |
3818 | + PintaCore.Actions.Edit.FillSelection.Sensitive = show_selection; |
3819 | + PintaCore.Actions.Image.CropToSelection.Sensitive = show_selection; |
3820 | + } |
3821 | + } |
3822 | + |
3823 | + public bool ShowSelectionLayer { get; set; } |
3824 | + |
3825 | + public Layer ToolLayer { |
3826 | + get { |
3827 | + if (tool_layer.Surface.Width != ImageSize.Width || tool_layer.Surface.Height != ImageSize.Height) { |
3828 | + (tool_layer.Surface as IDisposable).Dispose (); |
3829 | + tool_layer = CreateLayer ("Tool Layer"); |
3830 | + tool_layer.Hidden = true; |
3831 | + } |
3832 | + |
3833 | + return tool_layer; |
3834 | + } |
3835 | + } |
3836 | + |
3837 | + public DocumentWorkspace Workspace { get; private set; } |
3838 | + #endregion |
3839 | + |
3840 | + #region Public Methods |
3841 | + // Adds a new layer above the current one |
3842 | + public Layer AddNewLayer (string name) |
3843 | + { |
3844 | + Layer layer; |
3845 | + |
3846 | + if (string.IsNullOrEmpty (name)) |
3847 | + layer = CreateLayer (); |
3848 | + else |
3849 | + layer = CreateLayer (name); |
3850 | + |
3851 | + Layers.Insert (current_layer + 1, layer); |
3852 | + |
3853 | + if (Layers.Count == 1) |
3854 | + current_layer = 0; |
3855 | + |
3856 | + layer.PropertyChanged += RaiseLayerPropertyChangedEvent; |
3857 | + |
3858 | + PintaCore.Layers.OnLayerAdded (); |
3859 | + return layer; |
3860 | + } |
3861 | + |
3862 | + public Gdk.Rectangle ClampToImageSize (Gdk.Rectangle r) |
3863 | + { |
3864 | + int x = Utility.Clamp (r.X, 0, ImageSize.Width); |
3865 | + int y = Utility.Clamp (r.Y, 0, ImageSize.Height); |
3866 | + int width = Math.Min (r.Width, ImageSize.Width - x); |
3867 | + int height = Math.Min (r.Height, ImageSize.Height - y); |
3868 | + |
3869 | + return new Gdk.Rectangle (x, y, width, height); |
3870 | + } |
3871 | + |
3872 | + public void Clear () |
3873 | + { |
3874 | + while (Layers.Count > 0) { |
3875 | + Layer l = Layers[Layers.Count - 1]; |
3876 | + Layers.RemoveAt (Layers.Count - 1); |
3877 | + (l.Surface as IDisposable).Dispose (); |
3878 | + } |
3879 | + |
3880 | + current_layer = -1; |
3881 | + PintaCore.Layers.OnLayerRemoved (); |
3882 | + } |
3883 | + |
3884 | + // Clean up any native resources we had |
3885 | + public void Close () |
3886 | + { |
3887 | + // Dispose all of our layers |
3888 | + while (Layers.Count > 0) { |
3889 | + Layer l = Layers[Layers.Count - 1]; |
3890 | + Layers.RemoveAt (Layers.Count - 1); |
3891 | + (l.Surface as IDisposable).Dispose (); |
3892 | + } |
3893 | + |
3894 | + current_layer = -1; |
3895 | + |
3896 | + if (tool_layer != null) |
3897 | + (tool_layer.Surface as IDisposable).Dispose (); |
3898 | + |
3899 | + if (selection_layer != null) |
3900 | + (selection_layer.Surface as IDisposable).Dispose (); |
3901 | + |
3902 | + if (selection_path != null) |
3903 | + (selection_path as IDisposable).Dispose (); |
3904 | + } |
3905 | + |
3906 | + public Context CreateClippedContext () |
3907 | + { |
3908 | + Context g = new Context (CurrentLayer.Surface); |
3909 | + |
3910 | + g.AppendPath (SelectionPath); |
3911 | + g.FillRule = Cairo.FillRule.EvenOdd; |
3912 | + g.Clip (); |
3913 | + |
3914 | + return g; |
3915 | + } |
3916 | + |
3917 | + public Context CreateClippedContext (bool antialias) |
3918 | + { |
3919 | + Context g = new Context (CurrentLayer.Surface); |
3920 | + |
3921 | + g.AppendPath (SelectionPath); |
3922 | + g.FillRule = Cairo.FillRule.EvenOdd; |
3923 | + g.Clip (); |
3924 | + |
3925 | + g.Antialias = antialias ? Antialias.Subpixel : Antialias.None; |
3926 | + |
3927 | + return g; |
3928 | + } |
3929 | + |
3930 | + public Context CreateClippedToolContext () |
3931 | + { |
3932 | + Context g = new Context (ToolLayer.Surface); |
3933 | + |
3934 | + g.AppendPath (SelectionPath); |
3935 | + g.FillRule = Cairo.FillRule.EvenOdd; |
3936 | + g.Clip (); |
3937 | + |
3938 | + return g; |
3939 | + } |
3940 | + |
3941 | + public Context CreateClippedToolContext (bool antialias) |
3942 | + { |
3943 | + Context g = new Context (ToolLayer.Surface); |
3944 | + |
3945 | + g.AppendPath (SelectionPath); |
3946 | + g.FillRule = Cairo.FillRule.EvenOdd; |
3947 | + g.Clip (); |
3948 | + |
3949 | + g.Antialias = antialias ? Antialias.Subpixel : Antialias.None; |
3950 | + |
3951 | + return g; |
3952 | + } |
3953 | + |
3954 | + public Layer CreateLayer () |
3955 | + { |
3956 | + return CreateLayer (string.Format ("{0} {1}", Catalog.GetString ("Layer"), layer_name_int++)); |
3957 | + } |
3958 | + |
3959 | + public Layer CreateLayer (string name) |
3960 | + { |
3961 | + return CreateLayer (name, ImageSize.Width, ImageSize.Height); |
3962 | + } |
3963 | + |
3964 | + public Layer CreateLayer (string name, int width, int height) |
3965 | + { |
3966 | + Cairo.ImageSurface surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height); |
3967 | + Layer layer = new Layer (surface) { Name = name }; |
3968 | + |
3969 | + return layer; |
3970 | + } |
3971 | + |
3972 | + public void CreateSelectionLayer () |
3973 | + { |
3974 | + Layer old = selection_layer; |
3975 | + |
3976 | + selection_layer = CreateLayer (); |
3977 | + selection_layer_index = current_layer + 1; |
3978 | + |
3979 | + if (old != null) |
3980 | + (old.Surface as IDisposable).Dispose (); |
3981 | + } |
3982 | + |
3983 | + // Delete the current layer |
3984 | + public void DeleteCurrentLayer () |
3985 | + { |
3986 | + Layer layer = CurrentLayer; |
3987 | + |
3988 | + Layers.RemoveAt (current_layer); |
3989 | + |
3990 | + // Only change this if this wasn't already the bottom layer |
3991 | + if (current_layer > 0) |
3992 | + current_layer--; |
3993 | + |
3994 | + layer.PropertyChanged -= RaiseLayerPropertyChangedEvent; |
3995 | + |
3996 | + PintaCore.Layers.OnLayerRemoved (); |
3997 | + } |
3998 | + |
3999 | + // Delete the layer |
4000 | + public void DeleteLayer (int index, bool dispose) |
4001 | + { |
4002 | + Layer layer = Layers[index]; |
4003 | + |
4004 | + Layers.RemoveAt (index); |
4005 | + |
4006 | + if (dispose) |
4007 | + (layer.Surface as IDisposable).Dispose (); |
4008 | + |
4009 | + // Only change this if this wasn't already the bottom layer |
4010 | + if (current_layer > 0) |
4011 | + current_layer--; |
4012 | + |
4013 | + layer.PropertyChanged -= RaiseLayerPropertyChangedEvent; |
4014 | + |
4015 | + PintaCore.Layers.OnLayerRemoved (); |
4016 | + } |
4017 | + |
4018 | + public void DestroySelectionLayer () |
4019 | + { |
4020 | + ShowSelectionLayer = false; |
4021 | + SelectionLayer.Clear (); |
4022 | + SelectionLayer.Offset = new PointD (0, 0); |
4023 | + } |
4024 | + |
4025 | + // Duplicate current layer |
4026 | + public Layer DuplicateCurrentLayer () |
4027 | + { |
4028 | + Layer source = CurrentLayer; |
4029 | + Layer layer = CreateLayer (string.Format ("{0} {1}", source.Name, Catalog.GetString ("copy"))); |
4030 | + |
4031 | + using (Cairo.Context g = new Cairo.Context (layer.Surface)) { |
4032 | + g.SetSource (source.Surface); |
4033 | + g.Paint (); |
4034 | + } |
4035 | + |
4036 | + layer.Hidden = source.Hidden; |
4037 | + layer.Opacity = source.Opacity; |
4038 | + layer.Tiled = source.Tiled; |
4039 | + |
4040 | + Layers.Insert (++current_layer, layer); |
4041 | + |
4042 | + layer.PropertyChanged += RaiseLayerPropertyChangedEvent; |
4043 | + |
4044 | + PintaCore.Layers.OnLayerAdded (); |
4045 | + |
4046 | + return layer; |
4047 | + } |
4048 | + |
4049 | + public void FinishSelection () |
4050 | + { |
4051 | + // We don't have an uncommitted layer, abort |
4052 | + if (!ShowSelectionLayer) |
4053 | + return; |
4054 | + |
4055 | + FinishPixelsHistoryItem hist = new FinishPixelsHistoryItem (); |
4056 | + hist.TakeSnapshot (); |
4057 | + |
4058 | + Layer layer = SelectionLayer; |
4059 | + |
4060 | + using (Cairo.Context g = new Cairo.Context (CurrentLayer.Surface)) { |
4061 | + g.Save (); |
4062 | + |
4063 | + g.SetSourceSurface (layer.Surface, (int)layer.Offset.X, (int)layer.Offset.Y); |
4064 | + g.PaintWithAlpha (layer.Opacity); |
4065 | + |
4066 | + g.Restore (); |
4067 | + } |
4068 | + |
4069 | + DestroySelectionLayer (); |
4070 | + Workspace.Invalidate (); |
4071 | + |
4072 | + Workspace.History.PushNewItem (hist); |
4073 | + } |
4074 | + |
4075 | + // Flatten image |
4076 | + public void FlattenImage () |
4077 | + { |
4078 | + if (Layers.Count < 2) |
4079 | + throw new InvalidOperationException ("Cannot flatten image because there is only one layer."); |
4080 | + |
4081 | + Layer dest = Layers[0]; |
4082 | + |
4083 | + using (Cairo.Context g = new Cairo.Context (dest.Surface)) { |
4084 | + for (int i = 1; i < Layers.Count; i++) { |
4085 | + Layer source = Layers[i]; |
4086 | + g.SetSource (source.Surface); |
4087 | + g.PaintWithAlpha (source.Opacity); |
4088 | + } |
4089 | + } |
4090 | + |
4091 | + current_layer = 0; |
4092 | + |
4093 | + while (Layers.Count > 1) { |
4094 | + Layer l = Layers[1]; |
4095 | + |
4096 | + Layers.RemoveAt (1); |
4097 | + } |
4098 | + |
4099 | + PintaCore.Layers.OnLayerRemoved (); |
4100 | + Workspace.Invalidate (); |
4101 | + } |
4102 | + |
4103 | + // Flip image horizontally |
4104 | + public void FlipImageHorizontal () |
4105 | + { |
4106 | + foreach (var layer in Layers) |
4107 | + layer.FlipHorizontal (); |
4108 | + |
4109 | + Workspace.Invalidate (); |
4110 | + } |
4111 | + |
4112 | + // Flip image vertically |
4113 | + public void FlipImageVertical () |
4114 | + { |
4115 | + foreach (var layer in Layers) |
4116 | + layer.FlipVertical (); |
4117 | + |
4118 | + Workspace.Invalidate (); |
4119 | + } |
4120 | + |
4121 | + public ImageSurface GetClippedLayer (int index) |
4122 | + { |
4123 | + Cairo.ImageSurface surf = new Cairo.ImageSurface (Cairo.Format.Argb32, ImageSize.Width, ImageSize.Height); |
4124 | + |
4125 | + using (Cairo.Context g = new Cairo.Context (surf)) { |
4126 | + g.AppendPath (SelectionPath); |
4127 | + g.Clip (); |
4128 | + |
4129 | + g.SetSource (Layers[index].Surface); |
4130 | + g.Paint (); |
4131 | + } |
4132 | + |
4133 | + return surf; |
4134 | + } |
4135 | + |
4136 | + public ImageSurface GetFlattenedImage () |
4137 | + { |
4138 | + Cairo.ImageSurface surf = new Cairo.ImageSurface (Cairo.Format.Argb32, ImageSize.Width, ImageSize.Height); |
4139 | + |
4140 | + using (Cairo.Context g = new Cairo.Context (surf)) { |
4141 | + foreach (var layer in GetLayersToPaint ()) { |
4142 | + g.SetSource (layer.Surface); |
4143 | + g.PaintWithAlpha (layer.Opacity); |
4144 | + } |
4145 | + } |
4146 | + |
4147 | + return surf; |
4148 | + } |
4149 | + |
4150 | + public List<Layer> GetLayersToPaint () |
4151 | + { |
4152 | + List<Layer> paint = new List<Layer> (); |
4153 | + |
4154 | + foreach (var layer in Layers) { |
4155 | + if (!layer.Hidden) |
4156 | + paint.Add (layer); |
4157 | + |
4158 | + if (layer == CurrentLayer) { |
4159 | + if (!tool_layer.Hidden) |
4160 | + paint.Add (tool_layer); |
4161 | + |
4162 | + if (ShowSelectionLayer) |
4163 | + paint.Add (selection_layer); |
4164 | + } |
4165 | + } |
4166 | + |
4167 | + return paint; |
4168 | + } |
4169 | + |
4170 | + /// <param name="canvasOnly">false for the whole selection, true for the part only on our canvas</param> |
4171 | + public Gdk.Rectangle GetSelectedBounds (bool canvasOnly) |
4172 | + { |
4173 | + var bounds = SelectionPath.GetBounds (); |
4174 | + |
4175 | + if (canvasOnly) |
4176 | + bounds = ClampToImageSize (bounds); |
4177 | + |
4178 | + return bounds; |
4179 | + } |
4180 | + |
4181 | + public int IndexOf (Layer layer) |
4182 | + { |
4183 | + return Layers.IndexOf (layer); |
4184 | + } |
4185 | + |
4186 | + // Adds a new layer above the current one |
4187 | + public void Insert (Layer layer, int index) |
4188 | + { |
4189 | + Layers.Insert (index, layer); |
4190 | + |
4191 | + if (Layers.Count == 1) |
4192 | + current_layer = 0; |
4193 | + |
4194 | + layer.PropertyChanged += RaiseLayerPropertyChangedEvent; |
4195 | + |
4196 | + PintaCore.Layers.OnLayerAdded (); |
4197 | + } |
4198 | + |
4199 | + // Flatten current layer |
4200 | + public void MergeCurrentLayerDown () |
4201 | + { |
4202 | + if (current_layer == 0) |
4203 | + throw new InvalidOperationException ("Cannot flatten layer because current layer is the bottom layer."); |
4204 | + |
4205 | + Layer source = CurrentLayer; |
4206 | + Layer dest = Layers[current_layer - 1]; |
4207 | + |
4208 | + using (Cairo.Context g = new Cairo.Context (dest.Surface)) { |
4209 | + g.SetSource (source.Surface); |
4210 | + g.PaintWithAlpha (source.Opacity); |
4211 | + } |
4212 | + |
4213 | + DeleteCurrentLayer (); |
4214 | + } |
4215 | + |
4216 | + // Move current layer down |
4217 | + public void MoveCurrentLayerDown () |
4218 | + { |
4219 | + if (current_layer == 0) |
4220 | + throw new InvalidOperationException ("Cannot move layer down because current layer is the bottom layer."); |
4221 | + |
4222 | + Layer layer = CurrentLayer; |
4223 | + Layers.RemoveAt (current_layer); |
4224 | + Layers.Insert (--current_layer, layer); |
4225 | + |
4226 | + PintaCore.Layers.OnSelectedLayerChanged (); |
4227 | + |
4228 | + Workspace.Invalidate (); |
4229 | + } |
4230 | + |
4231 | + // Move current layer up |
4232 | + public void MoveCurrentLayerUp () |
4233 | + { |
4234 | + if (current_layer == Layers.Count) |
4235 | + throw new InvalidOperationException ("Cannot move layer up because current layer is the top layer."); |
4236 | + |
4237 | + Layer layer = CurrentLayer; |
4238 | + Layers.RemoveAt (current_layer); |
4239 | + Layers.Insert (++current_layer, layer); |
4240 | + |
4241 | + PintaCore.Layers.OnSelectedLayerChanged (); |
4242 | + |
4243 | + Workspace.Invalidate (); |
4244 | + } |
4245 | + |
4246 | + public void ResetSelectionPath () |
4247 | + { |
4248 | + Path old = SelectionPath; |
4249 | + |
4250 | + using (Cairo.Context g = new Cairo.Context (selection_layer.Surface)) |
4251 | + SelectionPath = g.CreateRectanglePath (new Cairo.Rectangle (0, 0, ImageSize.Width, ImageSize.Height)); |
4252 | + |
4253 | + if (old != null) |
4254 | + (old as IDisposable).Dispose (); |
4255 | + |
4256 | + ShowSelection = false; |
4257 | + } |
4258 | + |
4259 | + public void ResizeCanvas (int width, int height, Anchor anchor) |
4260 | + { |
4261 | + double scale; |
4262 | + |
4263 | + if (ImageSize.Width == width && ImageSize.Height == height) |
4264 | + return; |
4265 | + |
4266 | + PintaCore.Tools.Commit (); |
4267 | + |
4268 | + ResizeHistoryItem hist = new ResizeHistoryItem (ImageSize); |
4269 | + hist.Icon = "Menu.Image.CanvasSize.png"; |
4270 | + hist.Text = Catalog.GetString ("Resize Canvas"); |
4271 | + hist.TakeSnapshotOfImage (); |
4272 | + |
4273 | + scale = Workspace.Scale; |
4274 | + |
4275 | + ImageSize = new Gdk.Size (width, height); |
4276 | + |
4277 | + foreach (var layer in Layers) |
4278 | + layer.ResizeCanvas (width, height, anchor); |
4279 | + |
4280 | + Workspace.History.PushNewItem (hist); |
4281 | + |
4282 | + ResetSelectionPath (); |
4283 | + |
4284 | + Workspace.Scale = scale; |
4285 | + } |
4286 | + |
4287 | + public void ResizeImage (int width, int height) |
4288 | + { |
4289 | + double scale; |
4290 | + |
4291 | + if (ImageSize.Width == width && ImageSize.Height == height) |
4292 | + return; |
4293 | + |
4294 | + PintaCore.Tools.Commit (); |
4295 | + |
4296 | + ResizeHistoryItem hist = new ResizeHistoryItem (ImageSize); |
4297 | + hist.TakeSnapshotOfImage (); |
4298 | + |
4299 | + scale = Workspace.Scale; |
4300 | + |
4301 | + ImageSize = new Gdk.Size (width, height); |
4302 | + |
4303 | + foreach (var layer in Layers) |
4304 | + layer.Resize (width, height); |
4305 | + |
4306 | + Workspace.History.PushNewItem (hist); |
4307 | + |
4308 | + ResetSelectionPath (); |
4309 | + |
4310 | + Workspace.Scale = scale; |
4311 | + } |
4312 | + |
4313 | + // Rotate image 180 degrees (flip H+V) |
4314 | + public void RotateImage180 () |
4315 | + { |
4316 | + RotateImage (180); |
4317 | + } |
4318 | + |
4319 | + public void RotateImageCW () |
4320 | + { |
4321 | + RotateImage (90); |
4322 | + } |
4323 | + |
4324 | + public void RotateImageCCW () |
4325 | + { |
4326 | + RotateImage (-90); |
4327 | + } |
4328 | + |
4329 | + /// <summary> |
4330 | + /// Rotates the image by the specified angle (in degrees) |
4331 | + /// </summary> |
4332 | + private void RotateImage (double angle) |
4333 | + { |
4334 | + foreach (var layer in Layers) |
4335 | + { |
4336 | + layer.Rotate (angle); |
4337 | + } |
4338 | + |
4339 | + ImageSize = Layer.RotateDimensions (ImageSize, angle); |
4340 | + Workspace.CanvasSize = Layer.RotateDimensions (Workspace.CanvasSize, angle); |
4341 | + |
4342 | + PintaCore.Actions.View.UpdateCanvasScale (); |
4343 | + Workspace.Invalidate (); |
4344 | + } |
4345 | + |
4346 | + // Returns true if successful, false if canceled |
4347 | + public bool Save (bool saveAs) |
4348 | + { |
4349 | + return PintaCore.Actions.File.RaiseSaveDocument (this, saveAs); |
4350 | + } |
4351 | + |
4352 | + public void SetCurrentLayer (int i) |
4353 | + { |
4354 | + current_layer = i; |
4355 | + |
4356 | + PintaCore.Layers.OnSelectedLayerChanged (); |
4357 | + } |
4358 | + |
4359 | + public void SetCurrentLayer (Layer layer) |
4360 | + { |
4361 | + current_layer = Layers.IndexOf (layer); |
4362 | + |
4363 | + PintaCore.Layers.OnSelectedLayerChanged (); |
4364 | + } |
4365 | + #endregion |
4366 | + |
4367 | + #region Protected Methods |
4368 | + protected void OnIsDirtyChanged () |
4369 | + { |
4370 | + if (IsDirtyChanged != null) |
4371 | + IsDirtyChanged (this, EventArgs.Empty); |
4372 | + } |
4373 | + |
4374 | + protected void OnRenamed () |
4375 | + { |
4376 | + if (Renamed != null) |
4377 | + Renamed (this, EventArgs.Empty); |
4378 | + } |
4379 | + #endregion |
4380 | + |
4381 | + #region Private Methods |
4382 | + private void RaiseLayerPropertyChangedEvent (object sender, PropertyChangedEventArgs e) |
4383 | + { |
4384 | + PintaCore.Layers.RaiseLayerPropertyChangedEvent (sender, e); |
4385 | + } |
4386 | + #endregion |
4387 | + |
4388 | + #region Public Events |
4389 | + public event EventHandler IsDirtyChanged; |
4390 | + public event EventHandler Renamed; |
4391 | + #endregion |
4392 | + } |
4393 | +} |
4394 | |
4395 | === added file 'Pinta.Core/Classes/DocumentWorkspace.cs' |
4396 | --- Pinta.Core/Classes/DocumentWorkspace.cs 1970-01-01 00:00:00 +0000 |
4397 | +++ Pinta.Core/Classes/DocumentWorkspace.cs 2013-01-23 15:01:21 +0000 |
4398 | @@ -0,0 +1,273 @@ |
4399 | +// |
4400 | +// DocumentWorkspace.cs |
4401 | +// |
4402 | +// Author: |
4403 | +// Jonathan Pobst <monkey@jpobst.com> |
4404 | +// |
4405 | +// Copyright (c) 2010 Jonathan Pobst |
4406 | +// |
4407 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
4408 | +// of this software and associated documentation files (the "Software"), to deal |
4409 | +// in the Software without restriction, including without limitation the rights |
4410 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
4411 | +// copies of the Software, and to permit persons to whom the Software is |
4412 | +// furnished to do so, subject to the following conditions: |
4413 | +// |
4414 | +// The above copyright notice and this permission notice shall be included in |
4415 | +// all copies or substantial portions of the Software. |
4416 | +// |
4417 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
4418 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
4419 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
4420 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
4421 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
4422 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
4423 | +// THE SOFTWARE. |
4424 | + |
4425 | +using System; |
4426 | +using Gdk; |
4427 | +using Mono.Unix; |
4428 | + |
4429 | +namespace Pinta.Core |
4430 | +{ |
4431 | + public class DocumentWorkspace |
4432 | + { |
4433 | + private Document document; |
4434 | + private Size canvas_size; |
4435 | + private enum ZoomType |
4436 | + { |
4437 | + ZoomIn, |
4438 | + ZoomOut, |
4439 | + ZoomManually |
4440 | + } |
4441 | + |
4442 | + internal DocumentWorkspace (Document document) |
4443 | + { |
4444 | + this.document = document; |
4445 | + History = new DocumentWorkspaceHistory (document, this); |
4446 | + } |
4447 | + |
4448 | + #region Public Properties |
4449 | + public bool CanvasFitsInWindow { |
4450 | + get { |
4451 | + Gtk.Viewport view = (Gtk.Viewport)PintaCore.Chrome.Canvas.Parent; |
4452 | + |
4453 | + int window_x = view.Allocation.Width; |
4454 | + int window_y = view.Children[0].Allocation.Height; |
4455 | + |
4456 | + if (CanvasSize.Width <= window_x && CanvasSize.Height <= window_y) |
4457 | + return true; |
4458 | + |
4459 | + return false; |
4460 | + } |
4461 | + } |
4462 | + |
4463 | + public Size CanvasSize { |
4464 | + get { return canvas_size; } |
4465 | + set { |
4466 | + if (canvas_size.Width != value.Width || canvas_size.Height != value.Height) { |
4467 | + canvas_size = value; |
4468 | + PintaCore.Workspace.OnCanvasSizeChanged (); |
4469 | + } |
4470 | + } |
4471 | + } |
4472 | + |
4473 | + public DocumentWorkspaceHistory History { get; private set; } |
4474 | + |
4475 | + public bool ImageFitsInWindow { |
4476 | + get { |
4477 | + Gtk.Viewport view = (Gtk.Viewport)PintaCore.Chrome.Canvas.Parent; |
4478 | + |
4479 | + int window_x = view.Allocation.Width; |
4480 | + int window_y = view.Children[0].Allocation.Height; |
4481 | + |
4482 | + if (document.ImageSize.Width <= window_x && document.ImageSize.Height <= window_y) |
4483 | + return true; |
4484 | + |
4485 | + return false; |
4486 | + } |
4487 | + } |
4488 | + |
4489 | + public Cairo.PointD Offset { |
4490 | + get { return new Cairo.PointD ((PintaCore.Chrome.Canvas.Allocation.Width - canvas_size.Width) / 2, (PintaCore.Chrome.Canvas.Allocation.Height - canvas_size.Height) / 2); } |
4491 | + } |
4492 | + |
4493 | + public double Scale { |
4494 | + get { return (double)CanvasSize.Width / (double)document.ImageSize.Width; } |
4495 | + set { |
4496 | + if (value != (double)CanvasSize.Width / (double)document.ImageSize.Width || value != (double)CanvasSize.Height / (double)document.ImageSize.Height) { |
4497 | + int new_x = Math.Max ((int)(document.ImageSize.Width * value), 1); |
4498 | + int new_y = Math.Max ((int)((new_x * document.ImageSize.Height) / document.ImageSize.Width), 1); |
4499 | + |
4500 | + CanvasSize = new Gdk.Size (new_x, new_y); |
4501 | + Invalidate (); |
4502 | + } |
4503 | + } |
4504 | + } |
4505 | + |
4506 | + #endregion |
4507 | + |
4508 | + #region Public Methods |
4509 | + public void Invalidate () |
4510 | + { |
4511 | + PintaCore.Workspace.OnCanvasInvalidated (new CanvasInvalidatedEventArgs ()); |
4512 | + } |
4513 | + |
4514 | + public void Invalidate (Gdk.Rectangle rect) |
4515 | + { |
4516 | + rect = new Gdk.Rectangle ((int)((rect.X) * Scale + Offset.X), (int)((rect.Y) * Scale + Offset.Y), (int)(rect.Width * Scale), (int)(rect.Height * Scale)); |
4517 | + PintaCore.Workspace.OnCanvasInvalidated (new CanvasInvalidatedEventArgs (rect)); |
4518 | + } |
4519 | + |
4520 | + public bool PointInCanvas (Cairo.PointD point) |
4521 | + { |
4522 | + if (point.X < 0 || point.Y < 0) |
4523 | + return false; |
4524 | + |
4525 | + if (point.X >= document.ImageSize.Width || point.Y >= document.ImageSize.Height) |
4526 | + return false; |
4527 | + |
4528 | + return true; |
4529 | + } |
4530 | + |
4531 | + public void RecenterView (double x, double y) |
4532 | + { |
4533 | + Gtk.Viewport view = (Gtk.Viewport)PintaCore.Chrome.Canvas.Parent; |
4534 | + |
4535 | + view.Hadjustment.Value = Utility.Clamp (x * Scale - view.Hadjustment.PageSize / 2, view.Hadjustment.Lower, view.Hadjustment.Upper); |
4536 | + view.Vadjustment.Value = Utility.Clamp (y * Scale - view.Vadjustment.PageSize / 2, view.Vadjustment.Lower, view.Vadjustment.Upper); |
4537 | + } |
4538 | + |
4539 | + public void ScrollCanvas (int dx, int dy) |
4540 | + { |
4541 | + Gtk.Viewport view = (Gtk.Viewport)PintaCore.Chrome.Canvas.Parent; |
4542 | + |
4543 | + view.Hadjustment.Value = Utility.Clamp (dx + view.Hadjustment.Value, view.Hadjustment.Lower, view.Hadjustment.Upper - view.Hadjustment.PageSize); |
4544 | + view.Vadjustment.Value = Utility.Clamp (dy + view.Vadjustment.Value, view.Vadjustment.Lower, view.Vadjustment.Upper - view.Vadjustment.PageSize); |
4545 | + } |
4546 | + |
4547 | + public Cairo.PointD WindowPointToCanvas (double x, double y) |
4548 | + { |
4549 | + return new Cairo.PointD (Math.Floor ((x - Offset.X) / PintaCore.Workspace.Scale), Math.Floor ((y - Offset.Y) / PintaCore.Workspace.Scale)); |
4550 | + } |
4551 | + |
4552 | + public void ZoomIn () |
4553 | + { |
4554 | + ZoomAndRecenterView (ZoomType.ZoomIn, new Cairo.PointD (-1, -1)); // Zoom in relative to the center of the viewport. |
4555 | + } |
4556 | + |
4557 | + public void ZoomOut () |
4558 | + { |
4559 | + ZoomAndRecenterView (ZoomType.ZoomOut, new Cairo.PointD (-1, -1)); // Zoom out relative to the center of the viewport. |
4560 | + } |
4561 | + |
4562 | + public void ZoomInFromMouseScroll (Cairo.PointD point) |
4563 | + { |
4564 | + ZoomAndRecenterView (ZoomType.ZoomIn, point); // Zoom in relative to mouse position. |
4565 | + } |
4566 | + |
4567 | + public void ZoomOutFromMouseScroll (Cairo.PointD point) |
4568 | + { |
4569 | + ZoomAndRecenterView (ZoomType.ZoomOut, point); // Zoom out relative to mouse position. |
4570 | + } |
4571 | + |
4572 | + public void ZoomManually () |
4573 | + { |
4574 | + ZoomAndRecenterView (ZoomType.ZoomManually, new Cairo.PointD (-1, -1)); |
4575 | + } |
4576 | + |
4577 | + public void ZoomToRectangle (Cairo.Rectangle rect) |
4578 | + { |
4579 | + double ratio; |
4580 | + |
4581 | + if (document.ImageSize.Width / rect.Width <= document.ImageSize.Height / rect.Height) |
4582 | + ratio = document.ImageSize.Width / rect.Width; |
4583 | + else |
4584 | + ratio = document.ImageSize.Height / rect.Height; |
4585 | + |
4586 | + (PintaCore.Actions.View.ZoomComboBox.ComboBox as Gtk.ComboBoxEntry).Entry.Text = String.Format ("{0:F}%", ratio * 100.0); |
4587 | + Gtk.Main.Iteration (); //Force update of scrollbar upper before recenter |
4588 | + RecenterView (rect.X + rect.Width / 2, rect.Y + rect.Height / 2); |
4589 | + } |
4590 | + #endregion |
4591 | + |
4592 | + #region Private Methods |
4593 | + private void ZoomAndRecenterView (ZoomType zoomType, Cairo.PointD point) |
4594 | + { |
4595 | + if (zoomType == ZoomType.ZoomOut && (CanvasSize.Width == 1 || CanvasSize.Height ==1)) |
4596 | + return; //Can't zoom in past a 1x1 px canvas |
4597 | + |
4598 | + double zoom; |
4599 | + |
4600 | + if (!ViewActions.TryParsePercent (PintaCore.Actions.View.ZoomComboBox.ComboBox.ActiveText, out zoom)) |
4601 | + zoom = Scale * 100; |
4602 | + |
4603 | + zoom = Math.Min (zoom, 3600); |
4604 | + |
4605 | + PintaCore.Chrome.Canvas.GdkWindow.FreezeUpdates (); |
4606 | + PintaCore.Actions.View.SuspendZoomUpdate (); |
4607 | + |
4608 | + Gtk.Viewport view = (Gtk.Viewport)PintaCore.Chrome.Canvas.Parent; |
4609 | + |
4610 | + bool adjustOnMousePosition = point.X >= 0.0 && point.Y >= 0.0; |
4611 | + |
4612 | + double center_x = adjustOnMousePosition ? |
4613 | + point.X : view.Hadjustment.Value + (view.Hadjustment.PageSize / 2.0); |
4614 | + double center_y = adjustOnMousePosition ? |
4615 | + point.Y : view.Vadjustment.Value + (view.Vadjustment.PageSize / 2.0); |
4616 | + |
4617 | + center_x = (center_x - Offset.X) / Scale; |
4618 | + center_y = (center_y - Offset.Y) / Scale; |
4619 | + |
4620 | + if (zoomType == ZoomType.ZoomIn || zoomType == ZoomType.ZoomOut) { |
4621 | + int i = 0; |
4622 | + |
4623 | + Predicate<string> UpdateZoomLevel = zoomInList => |
4624 | + { |
4625 | + switch (zoomType) { |
4626 | + case ZoomType.ZoomIn: |
4627 | + if (zoomInList == Catalog.GetString ("Window") || int.Parse (zoomInList.Trim ('%')) <= zoom) { |
4628 | + PintaCore.Actions.View.ZoomComboBox.ComboBox.Active = i - 1; |
4629 | + return true; |
4630 | + } |
4631 | + |
4632 | + break; |
4633 | + |
4634 | + case ZoomType.ZoomOut: |
4635 | + if (zoomInList == Catalog.GetString ("Window")) |
4636 | + return true; |
4637 | + |
4638 | + if (int.Parse (zoomInList.Trim ('%')) < zoom) { |
4639 | + PintaCore.Actions.View.ZoomComboBox.ComboBox.Active = i; |
4640 | + return true; |
4641 | + } |
4642 | + |
4643 | + break; |
4644 | + } |
4645 | + |
4646 | + return false; |
4647 | + }; |
4648 | + |
4649 | + foreach (string item in PintaCore.Actions.View.ZoomCollection) { |
4650 | + if (UpdateZoomLevel (item)) |
4651 | + break; |
4652 | + |
4653 | + i++; |
4654 | + } |
4655 | + } |
4656 | + |
4657 | + PintaCore.Actions.View.UpdateCanvasScale (); |
4658 | + |
4659 | + // Quick fix : need to manually update Upper limit because the value is not changing after updating the canvas scale. |
4660 | + // TODO : I think there is an event need to be fired so that those values updated automatically. |
4661 | + view.Hadjustment.Upper = CanvasSize.Width < view.Hadjustment.PageSize ? view.Hadjustment.PageSize : CanvasSize.Width; |
4662 | + view.Vadjustment.Upper = CanvasSize.Height < view.Vadjustment.PageSize ? view.Vadjustment.PageSize : CanvasSize.Height; |
4663 | + |
4664 | + RecenterView (center_x, center_y); |
4665 | + |
4666 | + PintaCore.Actions.View.ResumeZoomUpdate (); |
4667 | + PintaCore.Chrome.Canvas.GdkWindow.ThawUpdates (); |
4668 | + } |
4669 | + #endregion |
4670 | + } |
4671 | +} |
4672 | |
4673 | === added file 'Pinta.Core/Classes/DocumentWorkspaceHistory.cs' |
4674 | --- Pinta.Core/Classes/DocumentWorkspaceHistory.cs 1970-01-01 00:00:00 +0000 |
4675 | +++ Pinta.Core/Classes/DocumentWorkspaceHistory.cs 2013-01-23 15:01:21 +0000 |
4676 | @@ -0,0 +1,172 @@ |
4677 | +// |
4678 | +// DocumentWorkspace.cs |
4679 | +// |
4680 | +// Author: |
4681 | +// Jonathan Pobst <monkey@jpobst.com> |
4682 | +// |
4683 | +// Copyright (c) 2010 Jonathan Pobst |
4684 | +// |
4685 | +// Permission is hereby granted, free of charge, to any person obtaining a copy |
4686 | +// of this software and associated documentation files (the "Software"), to deal |
4687 | +// in the Software without restriction, including without limitation the rights |
4688 | +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
4689 | +// copies of the Software, and to permit persons to whom the Software is |
4690 | +// furnished to do so, subject to the following conditions: |
4691 | +// |
4692 | +// The above copyright notice and this permission notice shall be included in |
4693 | +// all copies or substantial portions of the Software. |
4694 | +// |
4695 | +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
4696 | +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
4697 | +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
4698 | +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
4699 | +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
4700 | +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
4701 | +// THE SOFTWARE. |
4702 | + |
4703 | +using System; |
4704 | +using System.Collections.Generic; |
4705 | +using Gtk; |
4706 | + |
4707 | +namespace Pinta.Core |
4708 | +{ |
4709 | + public class DocumentWorkspaceHistory |
4710 | + { |
4711 | + private Document document; |
4712 | + private DocumentWorkspace workspace; |
4713 | + List<BaseHistoryItem> history = new List<BaseHistoryItem> (); |
4714 | + int historyPointer = -1; |
4715 | + |
4716 | + internal DocumentWorkspaceHistory (Document document, DocumentWorkspace workspace) |
4717 | + { |
4718 | + this.document = document; |
4719 | + this.workspace = workspace; |
4720 | + ListStore = new ListStore (typeof (BaseHistoryItem)); |
4721 | + } |
4722 | + |
4723 | + public Gtk.ListStore ListStore { get; private set; } |
4724 | + |
4725 | + public int Pointer { |
4726 | + get { return historyPointer; } |
4727 | + } |
4728 | + |
4729 | + public BaseHistoryItem Current { |
4730 | + get { |
4731 | + if (historyPointer > -1 && historyPointer < history.Count) |
4732 | + return history[historyPointer]; |
4733 | + else |
4734 | + return null; |
4735 | + } |
4736 | + } |
4737 | + |
4738 | + public void PushNewItem (BaseHistoryItem newItem) |
4739 | + { |
4740 | + |
4741 | + //Remove all old redos starting from the end of the list |
4742 | + for (int i = history.Count - 1; i >= 0; i--) { |
4743 | + |
4744 | + BaseHistoryItem item = history[i]; |
4745 | + |
4746 | + if (item.State == HistoryItemState.Redo) { |
4747 | + history.RemoveAt(i); |
4748 | + item.Dispose(); |
4749 | + //Remove from ListStore |
4750 | + ListStore.Remove (ref item.Id); |
4751 | + |
4752 | + } else if (item.State == HistoryItemState.Undo) { |
4753 | + break; |
4754 | + } |
4755 | + } |
4756 | + |
4757 | + //Add new undo to ListStore |
4758 | + newItem.Id = ListStore.AppendValues (newItem); |
4759 | + history.Add (newItem); |
4760 | + historyPointer = history.Count - 1; |
4761 | + |
4762 | + if (newItem.CausesDirty) |
4763 | + document.IsDirty = true; |
4764 | + |
4765 | + if (history.Count > 1) { |
4766 | + PintaCore.Actions.Edit.Undo.Sensitive = true; |
4767 | + CanUndo = true; |
4768 | + } |
4769 | + |
4770 | + PintaCore.Actions.Edit.Redo.Sensitive = false; |
4771 | + CanRedo = false; |
4772 | + PintaCore.History.OnHistoryItemAdded (newItem); |
4773 | + } |
4774 | + |
4775 | + public void Undo () |
4776 | + { |
4777 | + // ensure that the current tool's modifications are added to the history first (e.g. editing text) |
4778 | + PintaCore.Tools.CurrentTool.DoCommit (); |
4779 | + |
4780 | + if (historyPointer < 0) { |
4781 | + throw new InvalidOperationException ("Undo stack is empty"); |
4782 | + } else { |
4783 | + BaseHistoryItem item = history[historyPointer]; |
4784 | + item.Undo (); |
4785 | + item.State = HistoryItemState.Redo; |
4786 | + ListStore.SetValue (item.Id, 0, item); |
4787 | + history[historyPointer] = item; |
4788 | + historyPointer--; |
4789 | + } |
4790 | + |
4791 | + if (historyPointer == 0) { |
4792 | + document.IsDirty = false; |
4793 | + PintaCore.Actions.Edit.Undo.Sensitive = false; |
4794 | + CanUndo = false; |
4795 | + } |
4796 | + |
4797 | + PintaCore.Actions.Edit.Redo.Sensitive = true; |
4798 | + CanRedo = true; |
4799 | + PintaCore.History.OnActionUndone (); |
4800 | + } |
4801 | + |
4802 | + public void Redo () |
4803 | + { |
4804 | + if (historyPointer >= history.Count - 1) |
4805 | + throw new InvalidOperationException ("Redo stack is empty"); |
4806 | + |
4807 | + historyPointer++; |
4808 | + BaseHistoryItem item = history[historyPointer]; |
4809 | + item.Redo (); |
4810 | + item.State = HistoryItemState.Undo; |
4811 | + ListStore.SetValue (item.Id, 0, item); |
4812 | + history[historyPointer] = item; |
4813 | + |
4814 | + if (historyPointer == history.Count - 1) { |
4815 | + PintaCore.Actions.Edit.Redo.Sensitive = false; |
4816 | + CanRedo = false; |
4817 | + } |
4818 | + |
4819 | + if (item.CausesDirty) |
4820 | + document.IsDirty = true; |
4821 | + |
4822 | + if (history.Count > 1) { |
4823 | + PintaCore.Actions.Edit.Undo.Sensitive = true; |
4824 | + CanUndo = true; |
4825 | + } |
4826 | + |
4827 | + PintaCore.History.OnActionRedone (); |
4828 | + } |
4829 | + |
4830 | + public void Clear () |
4831 | + { |
4832 | + history.ForEach (delegate(BaseHistoryItem item) { item.Dispose (); } ); |
4833 | + history.Clear(); |
4834 | + ListStore.Clear (); |
4835 | + historyPointer = -1; |
4836 | + |
4837 | + document.IsDirty = false; |
4838 | + PintaCore.Actions.Edit.Redo.Sensitive = false; |
4839 | + PintaCore.Actions.Edit.Undo.Sensitive = false; |
4840 | + |
4841 | + CanRedo = false; |
4842 | + CanUndo = false; |
4843 | + } |
4844 | + |
4845 | + public bool CanRedo { get; private set; } |
4846 | + public bool CanUndo { get; private set; } |
4847 | + } |
4848 | +} |
4849 | |
4850 | === added file 'Pinta.Core/Classes/GradientRenderer.cs' |
4851 | --- Pinta.Core/Classes/GradientRenderer.cs 1970-01-01 00:00:00 +0000 |
4852 | +++ Pinta.Core/Classes/GradientRenderer.cs 2013-01-23 15:01:21 +0000 |
4853 | @@ -0,0 +1,229 @@ |
4854 | +///////////////////////////////////////////////////////////////////////////////// |
4855 | +// Paint.NET // |
4856 | +// Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. // |
4857 | +// Portions Copyright (C) Microsoft Corporation. All Rights Reserved. // |
4858 | +// See license-pdn.txt for full licensing and attribution details. // |
4859 | +///////////////////////////////////////////////////////////////////////////////// |
4860 | + |
4861 | +using System; |
4862 | +using System.Threading.Tasks; |
4863 | +using System.Collections.Generic; |
4864 | +using Cairo; |
4865 | +using Rectangle = Gdk.Rectangle; |
4866 | + |
4867 | +namespace Pinta.Core |
4868 | +{ |
4869 | + public abstract class GradientRenderer |
4870 | + { |
4871 | + private BinaryPixelOp normalBlendOp; |
4872 | + private ColorBgra startColor; |
4873 | + private ColorBgra endColor; |
4874 | + private PointD startPoint; |
4875 | + private PointD endPoint; |
4876 | + private bool alphaBlending; |
4877 | + private bool alphaOnly; |
4878 | + |
4879 | + private bool lerpCacheIsValid = false; |
4880 | + private byte[] lerpAlphas; |
4881 | + private ColorBgra[] lerpColors; |
4882 | + |
4883 | + public ColorBgra StartColor { |
4884 | + get { return this.startColor; } |
4885 | + |
4886 | + set { |
4887 | + if (this.startColor != value) { |
4888 | + this.startColor = value; |
4889 | + this.lerpCacheIsValid = false; |
4890 | + } |
4891 | + } |
4892 | + } |
4893 | + |
4894 | + public ColorBgra EndColor { |
4895 | + get { return this.endColor; } |
4896 | + |
4897 | + set { |
4898 | + if (this.endColor != value) { |
4899 | + this.endColor = value; |
4900 | + this.lerpCacheIsValid = false; |
4901 | + } |
4902 | + } |
4903 | + } |
4904 | + |
4905 | + public PointD StartPoint { |
4906 | + get { return this.startPoint; } |
4907 | + |
4908 | + set { this.startPoint = value; } |
4909 | + } |
4910 | + |
4911 | + public PointD EndPoint { |
4912 | + get { return this.endPoint; } |
4913 | + |
4914 | + set { this.endPoint = value; } |
4915 | + } |
4916 | + |
4917 | + public bool AlphaBlending { |
4918 | + get { return this.alphaBlending; } |
4919 | + |
4920 | + set { this.alphaBlending = value; } |
4921 | + } |
4922 | + |
4923 | + public bool AlphaOnly { |
4924 | + get { return this.alphaOnly; } |
4925 | + |
4926 | + set { this.alphaOnly = value; } |
4927 | + } |
4928 | + |
4929 | + public virtual void BeforeRender () |
4930 | + { |
4931 | + if (!this.lerpCacheIsValid) { |
4932 | + byte startAlpha; |
4933 | + byte endAlpha; |
4934 | + |
4935 | + if (this.alphaOnly) { |
4936 | + ComputeAlphaOnlyValuesFromColors (this.startColor, this.endColor, out startAlpha, out endAlpha); |
4937 | + } else { |
4938 | + startAlpha = this.startColor.A; |
4939 | + endAlpha = this.endColor.A; |
4940 | + } |
4941 | + |
4942 | + this.lerpAlphas = new byte[256]; |
4943 | + this.lerpColors = new ColorBgra[256]; |
4944 | + |
4945 | + for (int i = 0; i < 256; ++i) { |
4946 | + byte a = (byte)i; |
4947 | + this.lerpColors[a] = ColorBgra.Blend (this.startColor, this.endColor, a); |
4948 | + this.lerpAlphas[a] = (byte)(startAlpha + ((endAlpha - startAlpha) * a) / 255); |
4949 | + } |
4950 | + |
4951 | + this.lerpCacheIsValid = true; |
4952 | + } |
4953 | + } |
4954 | + |
4955 | + public abstract byte ComputeByteLerp(int x, int y); |
4956 | + |
4957 | + public virtual void AfterRender () |
4958 | + { |
4959 | + } |
4960 | + |
4961 | + private static void ComputeAlphaOnlyValuesFromColors (ColorBgra startColor, ColorBgra endColor, out byte startAlpha, out byte endAlpha) |
4962 | + { |
4963 | + startAlpha = startColor.A; |
4964 | + endAlpha = (byte)(255 - endColor.A); |
4965 | + } |
4966 | + |
4967 | + unsafe public void Render (ImageSurface surface, Gdk.Rectangle[] rois) |
4968 | + { |
4969 | + byte startAlpha; |
4970 | + byte endAlpha; |
4971 | + |
4972 | + if (this.alphaOnly) { |
4973 | + ComputeAlphaOnlyValuesFromColors (this.startColor, this.endColor, out startAlpha, out endAlpha); |
4974 | + } else { |
4975 | + startAlpha = this.startColor.A; |
4976 | + endAlpha = this.endColor.A; |
4977 | + } |
4978 | + |
4979 | + surface.Flush (); |
4980 | + |
4981 | + ColorBgra* src_data_ptr = (ColorBgra*)surface.DataPtr; |
4982 | + int src_width = surface.Width; |
4983 | + |
4984 | + for (int ri = 0; ri < rois.Length; ++ri) { |
4985 | + Gdk.Rectangle rect = rois[ri]; |
4986 | + |
4987 | + if (this.startPoint.X == this.endPoint.X && this.startPoint.Y == this.endPoint.Y) { |
4988 | + // Start and End point are the same ... fill with solid color. |
4989 | + for (int y = rect.Top; y < rect.Bottom; ++y) { |
4990 | + ColorBgra* pixelPtr = surface.GetPointAddress(rect.Left, y); |
4991 | + |
4992 | + for (int x = rect.Left; x < rect.Right; ++x) { |
4993 | + ColorBgra result; |
4994 | + |
4995 | + if (this.alphaOnly && this.alphaBlending) { |
4996 | + byte resultAlpha = (byte)Utility.FastDivideShortByByte ((ushort)(pixelPtr->A * endAlpha), 255); |
4997 | + result = *pixelPtr; |
4998 | + result.A = resultAlpha; |
4999 | + } else if (this.alphaOnly && !this.alphaBlending) { |
5000 | + result = *pixelPtr; |
I'm not sure this is right place to merge these changes. This repository is just a mirror of Pinta's Github repository, and is only used for the daily builds PPA. Based on Marc's comment on the bug report, I think you should be proposing this change to the raring branch of lp:ubuntu/pinta