Initial checkin of Pika from heckimp
This commit is contained in:
148
app/tools/meson.build
Normal file
148
app/tools/meson.build
Normal file
@ -0,0 +1,148 @@
|
||||
stamp_tools_enums = custom_target('stamp-tools-enums.h',
|
||||
input : [
|
||||
files(
|
||||
'tools-enums.h'
|
||||
),
|
||||
],
|
||||
output: [ 'stamp-tools-enums.h', ],
|
||||
command: [
|
||||
mkenums_wrap, perl,
|
||||
meson.project_source_root(), meson.current_source_dir(),
|
||||
meson.current_build_dir(),
|
||||
'tools-',
|
||||
'#include <gio/gio.h>\n' +
|
||||
'#include "libpikabase/pikabase.h"\n' +
|
||||
'#include "core/core-enums.h"\n',
|
||||
'#include "pika-intl.h"'
|
||||
],
|
||||
build_by_default: true
|
||||
)
|
||||
|
||||
libapptools_sources = [
|
||||
'pika-tools.c',
|
||||
'pika-tool-options-manager.c',
|
||||
'pikaairbrushtool.c',
|
||||
'pikaalignoptions.c',
|
||||
'pikaaligntool.c',
|
||||
'pikabrightnesscontrasttool.c',
|
||||
'pikabrushtool.c',
|
||||
'pikabucketfilloptions.c',
|
||||
'pikabucketfilltool.c',
|
||||
'pikabycolorselecttool.c',
|
||||
'pikacageoptions.c',
|
||||
'pikacagetool.c',
|
||||
'pikacloneoptions-gui.c',
|
||||
'pikaclonetool.c',
|
||||
'pikacoloroptions.c',
|
||||
'pikacolorpickeroptions.c',
|
||||
'pikacolorpickertool.c',
|
||||
'pikacolortool.c',
|
||||
'pikaconvolvetool.c',
|
||||
'pikacropoptions.c',
|
||||
'pikacroptool.c',
|
||||
'pikacurvestool.c',
|
||||
'pikadodgeburntool.c',
|
||||
'pikadrawtool.c',
|
||||
'pikaeditselectiontool.c',
|
||||
'pikaellipseselecttool.c',
|
||||
'pikaerasertool.c',
|
||||
'pikafilteroptions.c',
|
||||
'pikafiltertool-settings.c',
|
||||
'pikafiltertool-widgets.c',
|
||||
'pikafiltertool.c',
|
||||
'pikaflipoptions.c',
|
||||
'pikafliptool.c',
|
||||
'pikaforegroundselectoptions.c',
|
||||
'pikaforegroundselecttool.c',
|
||||
'pikaforegroundselecttoolundo.c',
|
||||
'pikafreeselecttool.c',
|
||||
'pikafuzzyselecttool.c',
|
||||
'pikagegltool.c',
|
||||
'pikagenerictransformtool.c',
|
||||
'pikagradientoptions.c',
|
||||
'pikagradienttool-editor.c',
|
||||
'pikagradienttool.c',
|
||||
'pikaguidetool.c',
|
||||
'pikahandletransformoptions.c',
|
||||
'pikahandletransformtool.c',
|
||||
'pikahealtool.c',
|
||||
'pikahistogramoptions.c',
|
||||
'pikainkoptions-gui.c',
|
||||
'pikainktool.c',
|
||||
'pikaiscissorsoptions.c',
|
||||
'pikaiscissorstool.c',
|
||||
'pikalevelstool.c',
|
||||
'pikamagnifyoptions.c',
|
||||
'pikamagnifytool.c',
|
||||
'pikameasureoptions.c',
|
||||
'pikameasuretool.c',
|
||||
'pikamoveoptions.c',
|
||||
'pikamovetool.c',
|
||||
'pikamybrushoptions-gui.c',
|
||||
'pikamybrushtool.c',
|
||||
'pikanpointdeformationoptions.c',
|
||||
'pikanpointdeformationtool.c',
|
||||
'pikaoffsettool.c',
|
||||
'pikaoperationtool.c',
|
||||
'pikapaintbrushtool.c',
|
||||
'pikapaintoptions-gui.c',
|
||||
'pikapaintselectoptions.c',
|
||||
'pikapaintselecttool.c',
|
||||
'pikapainttool-paint.c',
|
||||
'pikapainttool.c',
|
||||
'pikapenciltool.c',
|
||||
'pikaperspectiveclonetool.c',
|
||||
'pikaperspectivetool.c',
|
||||
'pikapolygonselecttool.c',
|
||||
'pikarectangleoptions.c',
|
||||
'pikarectangleselectoptions.c',
|
||||
'pikarectangleselecttool.c',
|
||||
'pikaregionselectoptions.c',
|
||||
'pikaregionselecttool.c',
|
||||
'pikarotatetool.c',
|
||||
'pikasamplepointtool.c',
|
||||
'pikascaletool.c',
|
||||
'pikaseamlesscloneoptions.c',
|
||||
'pikaseamlessclonetool.c',
|
||||
'pikaselectionoptions.c',
|
||||
'pikaselectiontool.c',
|
||||
'pikasheartool.c',
|
||||
'pikasmudgetool.c',
|
||||
'pikasourcetool.c',
|
||||
'pikatextoptions.c',
|
||||
'pikatexttool-editor.c',
|
||||
'pikatexttool.c',
|
||||
'pikathresholdtool.c',
|
||||
'pikatilehandleriscissors.c',
|
||||
'pikatool-progress.c',
|
||||
'pikatool.c',
|
||||
'pikatoolcontrol.c',
|
||||
'pikatooloptions-gui.c',
|
||||
'pikatools-utils.c',
|
||||
'pikatransform3doptions.c',
|
||||
'pikatransform3dtool.c',
|
||||
'pikatransformgridoptions.c',
|
||||
'pikatransformgridtool.c',
|
||||
'pikatransformgridtoolundo.c',
|
||||
'pikatransformoptions.c',
|
||||
'pikatransformtool.c',
|
||||
'pikaunifiedtransformtool.c',
|
||||
'pikavectoroptions.c',
|
||||
'pikavectortool.c',
|
||||
'pikawarpoptions.c',
|
||||
'pikawarptool.c',
|
||||
'tool_manager.c',
|
||||
'tools-enums.c',
|
||||
stamp_tools_enums,
|
||||
|
||||
appcoremarshal[1],
|
||||
]
|
||||
|
||||
libapptools = static_library('apptools',
|
||||
libapptools_sources,
|
||||
include_directories: [ rootInclude, rootAppInclude, ],
|
||||
c_args: '-DG_LOG_DOMAIN="Pika-Tools"',
|
||||
dependencies: [
|
||||
gegl, gtk3,
|
||||
],
|
||||
)
|
||||
462
app/tools/pika-tool-options-manager.c
Normal file
462
app/tools/pika-tool-options-manager.c
Normal file
@ -0,0 +1,462 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pika-tool-options-manager.c
|
||||
* Copyright (C) 2018 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikacoreconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "paint/pikapaintoptions.h"
|
||||
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pika-tool-options-manager.h"
|
||||
|
||||
|
||||
typedef struct _PikaToolOptionsManager PikaToolOptionsManager;
|
||||
|
||||
struct _PikaToolOptionsManager
|
||||
{
|
||||
Pika *pika;
|
||||
PikaPaintOptions *global_paint_options;
|
||||
PikaContextPropMask global_props;
|
||||
|
||||
PikaToolInfo *active_tool;
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static PikaContextPropMask
|
||||
tool_options_manager_get_global_props
|
||||
(PikaCoreConfig *config);
|
||||
|
||||
static void tool_options_manager_global_notify (PikaCoreConfig *config,
|
||||
const GParamSpec *pspec,
|
||||
PikaToolOptionsManager *manager);
|
||||
static void tool_options_manager_paint_options_notify
|
||||
(PikaPaintOptions *src,
|
||||
const GParamSpec *pspec,
|
||||
PikaPaintOptions *dest);
|
||||
|
||||
static void tool_options_manager_copy_paint_props
|
||||
(PikaPaintOptions *src,
|
||||
PikaPaintOptions *dest,
|
||||
PikaContextPropMask prop_mask);
|
||||
|
||||
static void tool_options_manager_tool_changed (PikaContext *user_context,
|
||||
PikaToolInfo *tool_info,
|
||||
PikaToolOptionsManager *manager);
|
||||
|
||||
|
||||
static GQuark manager_quark = 0;
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_tool_options_manager_init (Pika *pika)
|
||||
{
|
||||
PikaToolOptionsManager *manager;
|
||||
PikaContext *user_context;
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
g_return_if_fail (manager_quark == 0);
|
||||
|
||||
manager_quark = g_quark_from_static_string ("pika-tool-options-manager");
|
||||
|
||||
manager = g_slice_new0 (PikaToolOptionsManager);
|
||||
|
||||
g_object_set_qdata (G_OBJECT (pika), manager_quark, manager);
|
||||
|
||||
manager->pika = pika;
|
||||
|
||||
manager->global_paint_options =
|
||||
g_object_new (PIKA_TYPE_PAINT_OPTIONS,
|
||||
"pika", pika,
|
||||
"name", "tool-options-manager-global-paint-options",
|
||||
NULL);
|
||||
|
||||
manager->global_props = tool_options_manager_get_global_props (pika->config);
|
||||
|
||||
user_context = pika_get_user_context (pika);
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = list->data;
|
||||
|
||||
/* the global props that are actually used by the tool are
|
||||
* always shared with the user context by undefining them...
|
||||
*/
|
||||
pika_context_define_properties (PIKA_CONTEXT (tool_info->tool_options),
|
||||
manager->global_props &
|
||||
tool_info->context_props,
|
||||
FALSE);
|
||||
|
||||
/* ...and setting the user context as parent
|
||||
*/
|
||||
pika_context_set_parent (PIKA_CONTEXT (tool_info->tool_options),
|
||||
user_context);
|
||||
|
||||
/* make sure paint tools also share their brush, dynamics,
|
||||
* gradient properties if the resp. context properties are
|
||||
* global
|
||||
*/
|
||||
if (PIKA_IS_PAINT_OPTIONS (tool_info->tool_options))
|
||||
{
|
||||
g_signal_connect (tool_info->tool_options, "notify",
|
||||
G_CALLBACK (tool_options_manager_paint_options_notify),
|
||||
manager->global_paint_options);
|
||||
|
||||
g_signal_connect (manager->global_paint_options, "notify",
|
||||
G_CALLBACK (tool_options_manager_paint_options_notify),
|
||||
tool_info->tool_options);
|
||||
|
||||
tool_options_manager_copy_paint_props (manager->global_paint_options,
|
||||
PIKA_PAINT_OPTIONS (tool_info->tool_options),
|
||||
tool_info->context_props &
|
||||
manager->global_props);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_connect (pika->config, "notify::global-brush",
|
||||
G_CALLBACK (tool_options_manager_global_notify),
|
||||
manager);
|
||||
g_signal_connect (pika->config, "notify::global-dynamics",
|
||||
G_CALLBACK (tool_options_manager_global_notify),
|
||||
manager);
|
||||
g_signal_connect (pika->config, "notify::global-pattern",
|
||||
G_CALLBACK (tool_options_manager_global_notify),
|
||||
manager);
|
||||
g_signal_connect (pika->config, "notify::global-palette",
|
||||
G_CALLBACK (tool_options_manager_global_notify),
|
||||
manager);
|
||||
g_signal_connect (pika->config, "notify::global-gradient",
|
||||
G_CALLBACK (tool_options_manager_global_notify),
|
||||
manager);
|
||||
g_signal_connect (pika->config, "notify::global-font",
|
||||
G_CALLBACK (tool_options_manager_global_notify),
|
||||
manager);
|
||||
|
||||
g_signal_connect (user_context, "tool-changed",
|
||||
G_CALLBACK (tool_options_manager_tool_changed),
|
||||
manager);
|
||||
|
||||
tool_options_manager_tool_changed (user_context,
|
||||
pika_context_get_tool (user_context),
|
||||
manager);
|
||||
}
|
||||
|
||||
void
|
||||
pika_tool_options_manager_exit (Pika *pika)
|
||||
{
|
||||
PikaToolOptionsManager *manager;
|
||||
PikaContext *user_context;
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
|
||||
manager = g_object_get_qdata (G_OBJECT (pika), manager_quark);
|
||||
|
||||
g_return_if_fail (manager != NULL);
|
||||
|
||||
user_context = pika_get_user_context (pika);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (user_context,
|
||||
tool_options_manager_tool_changed,
|
||||
manager);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (pika->config,
|
||||
tool_options_manager_global_notify,
|
||||
manager);
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = list->data;
|
||||
|
||||
pika_context_set_parent (PIKA_CONTEXT (tool_info->tool_options), NULL);
|
||||
|
||||
if (PIKA_IS_PAINT_OPTIONS (tool_info->tool_options))
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (tool_info->tool_options,
|
||||
tool_options_manager_paint_options_notify,
|
||||
manager->global_paint_options);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (manager->global_paint_options,
|
||||
tool_options_manager_paint_options_notify,
|
||||
tool_info->tool_options);
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_object (&manager->global_paint_options);
|
||||
|
||||
g_slice_free (PikaToolOptionsManager, manager);
|
||||
|
||||
g_object_set_qdata (G_OBJECT (pika), manager_quark, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static PikaContextPropMask
|
||||
tool_options_manager_get_global_props (PikaCoreConfig *config)
|
||||
{
|
||||
PikaContextPropMask global_props = 0;
|
||||
|
||||
/* FG and BG are always shared between all tools */
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_FOREGROUND;
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_BACKGROUND;
|
||||
|
||||
if (config->global_brush)
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_BRUSH;
|
||||
if (config->global_dynamics)
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_DYNAMICS;
|
||||
if (config->global_pattern)
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_PATTERN;
|
||||
if (config->global_palette)
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_PALETTE;
|
||||
if (config->global_gradient)
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_GRADIENT;
|
||||
if (config->global_font)
|
||||
global_props |= PIKA_CONTEXT_PROP_MASK_FONT;
|
||||
|
||||
return global_props;
|
||||
}
|
||||
|
||||
static void
|
||||
tool_options_manager_global_notify (PikaCoreConfig *config,
|
||||
const GParamSpec *pspec,
|
||||
PikaToolOptionsManager *manager)
|
||||
{
|
||||
PikaContextPropMask global_props;
|
||||
PikaContextPropMask enabled_global_props;
|
||||
PikaContextPropMask disabled_global_props;
|
||||
GList *list;
|
||||
|
||||
global_props = tool_options_manager_get_global_props (config);
|
||||
|
||||
enabled_global_props = global_props & ~manager->global_props;
|
||||
disabled_global_props = manager->global_props & ~global_props;
|
||||
|
||||
/* copy the newly enabled global props to all tool options, and
|
||||
* disconnect the newly disabled ones from the user context
|
||||
*/
|
||||
for (list = pika_get_tool_info_iter (manager->pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = list->data;
|
||||
|
||||
/* don't change the active tool, it is always fully connected
|
||||
* to the user_context anyway because we set its
|
||||
* defined/undefined context props in tool_changed()
|
||||
*/
|
||||
if (tool_info == manager->active_tool)
|
||||
continue;
|
||||
|
||||
/* defining the newly disabled ones disconnects them from the
|
||||
* parent user context
|
||||
*/
|
||||
pika_context_define_properties (PIKA_CONTEXT (tool_info->tool_options),
|
||||
tool_info->context_props &
|
||||
disabled_global_props,
|
||||
TRUE);
|
||||
|
||||
/* undefining the newly enabled ones copies the value from the
|
||||
* parent user context
|
||||
*/
|
||||
pika_context_define_properties (PIKA_CONTEXT (tool_info->tool_options),
|
||||
tool_info->context_props &
|
||||
enabled_global_props,
|
||||
FALSE);
|
||||
|
||||
if (PIKA_IS_PAINT_OPTIONS (tool_info->tool_options))
|
||||
tool_options_manager_copy_paint_props (manager->global_paint_options,
|
||||
PIKA_PAINT_OPTIONS (tool_info->tool_options),
|
||||
tool_info->context_props &
|
||||
enabled_global_props);
|
||||
}
|
||||
|
||||
manager->global_props = global_props;
|
||||
}
|
||||
|
||||
static void
|
||||
tool_options_manager_paint_options_notify (PikaPaintOptions *src,
|
||||
const GParamSpec *pspec,
|
||||
PikaPaintOptions *dest)
|
||||
{
|
||||
Pika *pika = PIKA_CONTEXT (src)->pika;
|
||||
PikaCoreConfig *config = pika->config;
|
||||
PikaToolOptionsManager *manager;
|
||||
PikaToolInfo *tool_info;
|
||||
PikaContextPropMask prop_mask = 0;
|
||||
gboolean active = FALSE;
|
||||
|
||||
manager = g_object_get_qdata (G_OBJECT (pika), manager_quark);
|
||||
|
||||
/* one of the options is the global one, the other is the tool's,
|
||||
* get the tool_info from the tool's options
|
||||
*/
|
||||
if (manager->global_paint_options == src)
|
||||
tool_info = pika_context_get_tool (PIKA_CONTEXT (dest));
|
||||
else
|
||||
tool_info = pika_context_get_tool (PIKA_CONTEXT (src));
|
||||
|
||||
if (tool_info == manager->active_tool)
|
||||
active = TRUE;
|
||||
|
||||
if ((active || config->global_brush) &&
|
||||
tool_info->context_props & PIKA_CONTEXT_PROP_MASK_BRUSH)
|
||||
{
|
||||
prop_mask |= PIKA_CONTEXT_PROP_MASK_BRUSH;
|
||||
}
|
||||
|
||||
if ((active || config->global_dynamics) &&
|
||||
tool_info->context_props & PIKA_CONTEXT_PROP_MASK_DYNAMICS)
|
||||
{
|
||||
prop_mask |= PIKA_CONTEXT_PROP_MASK_DYNAMICS;
|
||||
}
|
||||
|
||||
if ((active || config->global_gradient) &&
|
||||
tool_info->context_props & PIKA_CONTEXT_PROP_MASK_GRADIENT)
|
||||
{
|
||||
prop_mask |= PIKA_CONTEXT_PROP_MASK_GRADIENT;
|
||||
}
|
||||
|
||||
if (pika_paint_options_is_prop (pspec->name, prop_mask))
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&value, pspec->value_type);
|
||||
|
||||
g_object_get_property (G_OBJECT (src), pspec->name, &value);
|
||||
|
||||
g_signal_handlers_block_by_func (dest,
|
||||
tool_options_manager_paint_options_notify,
|
||||
src);
|
||||
|
||||
g_object_set_property (G_OBJECT (dest), pspec->name, &value);
|
||||
|
||||
g_signal_handlers_unblock_by_func (dest,
|
||||
tool_options_manager_paint_options_notify,
|
||||
src);
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tool_options_manager_copy_paint_props (PikaPaintOptions *src,
|
||||
PikaPaintOptions *dest,
|
||||
PikaContextPropMask prop_mask)
|
||||
{
|
||||
g_signal_handlers_block_by_func (dest,
|
||||
tool_options_manager_paint_options_notify,
|
||||
src);
|
||||
|
||||
pika_paint_options_copy_props (src, dest, prop_mask);
|
||||
|
||||
g_signal_handlers_unblock_by_func (dest,
|
||||
tool_options_manager_paint_options_notify,
|
||||
src);
|
||||
}
|
||||
|
||||
static void
|
||||
tool_options_manager_tool_changed (PikaContext *user_context,
|
||||
PikaToolInfo *tool_info,
|
||||
PikaToolOptionsManager *manager)
|
||||
{
|
||||
if (tool_info == manager->active_tool)
|
||||
return;
|
||||
|
||||
/* FIXME: pika_busy HACK
|
||||
* the tool manager will stop the emission, so simply return
|
||||
*/
|
||||
if (manager->pika->busy)
|
||||
return;
|
||||
|
||||
if (manager->active_tool)
|
||||
{
|
||||
PikaToolInfo *active = manager->active_tool;
|
||||
|
||||
/* disconnect the old active tool from all context properties
|
||||
* it uses, but are not currently global
|
||||
*/
|
||||
pika_context_define_properties (PIKA_CONTEXT (active->tool_options),
|
||||
active->context_props &
|
||||
~manager->global_props,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
manager->active_tool = tool_info;
|
||||
|
||||
if (manager->active_tool)
|
||||
{
|
||||
PikaToolInfo *active = manager->active_tool;
|
||||
|
||||
/* make sure the tool options GUI always exists, this call
|
||||
* creates it if needed, so tools always have their option GUI
|
||||
* available even if the tool options dockable is not open, see
|
||||
* for example issue #3435
|
||||
*/
|
||||
pika_tools_get_tool_options_gui (active->tool_options);
|
||||
|
||||
/* copy the new tool's context properties that are not
|
||||
* currently global to the user context, so they get used by
|
||||
* everything
|
||||
*/
|
||||
pika_context_copy_properties (PIKA_CONTEXT (active->tool_options),
|
||||
pika_get_user_context (manager->pika),
|
||||
active->context_props &
|
||||
~manager->global_props);
|
||||
|
||||
if (PIKA_IS_PAINT_OPTIONS (active->tool_options))
|
||||
tool_options_manager_copy_paint_props (PIKA_PAINT_OPTIONS (active->tool_options),
|
||||
manager->global_paint_options,
|
||||
active->context_props &
|
||||
~manager->global_props);
|
||||
|
||||
/* then, undefine these properties so the tool syncs with the
|
||||
* user context automatically
|
||||
*/
|
||||
pika_context_define_properties (PIKA_CONTEXT (active->tool_options),
|
||||
active->context_props &
|
||||
~manager->global_props,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
33
app/tools/pika-tool-options-manager.h
Normal file
33
app/tools/pika-tool-options-manager.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pika-tool-options-manager.h
|
||||
* Copyright (C) 2018 Michael Natterer <mitch@gimp.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_TOOL_OPTIONS_MANAGER_H__
|
||||
#define __PIKA_TOOL_OPTIONS_MANAGER_H__
|
||||
|
||||
|
||||
void pika_tool_options_manager_init (Pika *pika);
|
||||
void pika_tool_options_manager_exit (Pika *pika);
|
||||
|
||||
|
||||
#endif /* __PIKA_TOOL_OPTIONS_MANAGER_H__ */
|
||||
838
app/tools/pika-tools.c
Normal file
838
app/tools/pika-tools.c
Normal file
@ -0,0 +1,838 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pika-contexts.h"
|
||||
#include "core/pika-internal-data.h"
|
||||
#include "core/pikacontext.h"
|
||||
#include "core/pikalist.h"
|
||||
#include "core/pikatoolgroup.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
#include "core/pikatooloptions.h"
|
||||
|
||||
#include "pika-tool-options-manager.h"
|
||||
#include "pika-tools.h"
|
||||
#include "pikatooloptions-gui.h"
|
||||
#include "tool_manager.h"
|
||||
|
||||
#include "pikaairbrushtool.h"
|
||||
#include "pikaaligntool.h"
|
||||
#include "pikabrightnesscontrasttool.h"
|
||||
#include "pikabucketfilltool.h"
|
||||
#include "pikabycolorselecttool.h"
|
||||
#include "pikacagetool.h"
|
||||
#include "pikaclonetool.h"
|
||||
#include "pikacolorpickertool.h"
|
||||
#include "pikaconvolvetool.h"
|
||||
#include "pikacroptool.h"
|
||||
#include "pikacurvestool.h"
|
||||
#include "pikadodgeburntool.h"
|
||||
#include "pikaellipseselecttool.h"
|
||||
#include "pikaerasertool.h"
|
||||
#include "pikafliptool.h"
|
||||
#include "pikafreeselecttool.h"
|
||||
#include "pikaforegroundselecttool.h"
|
||||
#include "pikafuzzyselecttool.h"
|
||||
#include "pikagegltool.h"
|
||||
#include "pikagradienttool.h"
|
||||
#include "pikahandletransformtool.h"
|
||||
#include "pikahealtool.h"
|
||||
#include "pikainktool.h"
|
||||
#include "pikaiscissorstool.h"
|
||||
#include "pikalevelstool.h"
|
||||
#include "pikaoperationtool.h"
|
||||
#include "pikamagnifytool.h"
|
||||
#include "pikameasuretool.h"
|
||||
#include "pikamovetool.h"
|
||||
#include "pikamybrushtool.h"
|
||||
#include "pikanpointdeformationtool.h"
|
||||
#include "pikaoffsettool.h"
|
||||
#include "pikapaintbrushtool.h"
|
||||
#include "pikapaintselecttool.h"
|
||||
#include "pikapenciltool.h"
|
||||
#include "pikaperspectiveclonetool.h"
|
||||
#include "pikaperspectivetool.h"
|
||||
#include "pikathresholdtool.h"
|
||||
#include "pikarectangleselecttool.h"
|
||||
#include "pikarotatetool.h"
|
||||
#include "pikaseamlessclonetool.h"
|
||||
#include "pikascaletool.h"
|
||||
#include "pikasheartool.h"
|
||||
#include "pikasmudgetool.h"
|
||||
#include "pikatexttool.h"
|
||||
#include "pikatransform3dtool.h"
|
||||
#include "pikaunifiedtransformtool.h"
|
||||
#include "pikavectortool.h"
|
||||
#include "pikawarptool.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
#define TOOL_RC_FILE_VERSION 1
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_tools_register (GType tool_type,
|
||||
GType tool_options_type,
|
||||
PikaToolOptionsGUIFunc options_gui_func,
|
||||
PikaContextPropMask context_props,
|
||||
const gchar *identifier,
|
||||
const gchar *label,
|
||||
const gchar *tooltip,
|
||||
const gchar *menu_label,
|
||||
const gchar *menu_accel,
|
||||
const gchar *help_domain,
|
||||
const gchar *help_data,
|
||||
const gchar *icon_name,
|
||||
gpointer data);
|
||||
|
||||
static void pika_tools_copy_structure (Pika *pika,
|
||||
PikaContainer *src_container,
|
||||
PikaContainer *dest_container,
|
||||
GHashTable *tools);
|
||||
|
||||
/* private variables */
|
||||
|
||||
static GBinding *toolbox_groups_binding = NULL;
|
||||
static gboolean tool_options_deleted = FALSE;
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_tools_init (Pika *pika)
|
||||
{
|
||||
PikaToolRegisterFunc register_funcs[] =
|
||||
{
|
||||
/* selection tools */
|
||||
|
||||
pika_rectangle_select_tool_register,
|
||||
pika_ellipse_select_tool_register,
|
||||
pika_free_select_tool_register,
|
||||
pika_fuzzy_select_tool_register,
|
||||
pika_by_color_select_tool_register,
|
||||
pika_iscissors_tool_register,
|
||||
pika_foreground_select_tool_register,
|
||||
pika_paint_select_tool_register,
|
||||
|
||||
/* path tool */
|
||||
|
||||
pika_vector_tool_register,
|
||||
|
||||
/* non-modifying tools */
|
||||
|
||||
pika_color_picker_tool_register,
|
||||
pika_magnify_tool_register,
|
||||
pika_measure_tool_register,
|
||||
|
||||
/* transform tools */
|
||||
|
||||
pika_move_tool_register,
|
||||
pika_align_tool_register,
|
||||
pika_crop_tool_register,
|
||||
pika_unified_transform_tool_register,
|
||||
pika_rotate_tool_register,
|
||||
pika_scale_tool_register,
|
||||
pika_shear_tool_register,
|
||||
pika_handle_transform_tool_register,
|
||||
pika_perspective_tool_register,
|
||||
pika_transform_3d_tool_register,
|
||||
pika_flip_tool_register,
|
||||
pika_cage_tool_register,
|
||||
pika_warp_tool_register,
|
||||
pika_n_point_deformation_tool_register,
|
||||
|
||||
/* paint tools */
|
||||
|
||||
pika_seamless_clone_tool_register,
|
||||
pika_text_tool_register,
|
||||
pika_bucket_fill_tool_register,
|
||||
pika_gradient_tool_register,
|
||||
pika_pencil_tool_register,
|
||||
pika_paintbrush_tool_register,
|
||||
pika_eraser_tool_register,
|
||||
pika_airbrush_tool_register,
|
||||
pika_ink_tool_register,
|
||||
pika_mybrush_tool_register,
|
||||
pika_clone_tool_register,
|
||||
pika_heal_tool_register,
|
||||
pika_perspective_clone_tool_register,
|
||||
pika_convolve_tool_register,
|
||||
pika_smudge_tool_register,
|
||||
pika_dodge_burn_tool_register,
|
||||
|
||||
/* filter tools */
|
||||
|
||||
pika_brightness_contrast_tool_register,
|
||||
pika_threshold_tool_register,
|
||||
pika_levels_tool_register,
|
||||
pika_curves_tool_register,
|
||||
pika_offset_tool_register,
|
||||
pika_gegl_tool_register,
|
||||
pika_operation_tool_register
|
||||
};
|
||||
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
|
||||
pika_tool_options_create_folder ();
|
||||
|
||||
pika_container_freeze (pika->tool_info_list);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (register_funcs); i++)
|
||||
{
|
||||
register_funcs[i] (pika_tools_register, pika);
|
||||
}
|
||||
|
||||
pika_container_thaw (pika->tool_info_list);
|
||||
|
||||
pika_tool_options_manager_init (pika);
|
||||
|
||||
tool_manager_init (pika);
|
||||
|
||||
toolbox_groups_binding = g_object_bind_property (
|
||||
pika->config, "toolbox-groups",
|
||||
pika->tool_item_ui_list, "flat",
|
||||
G_BINDING_INVERT_BOOLEAN |
|
||||
G_BINDING_SYNC_CREATE);
|
||||
}
|
||||
|
||||
void
|
||||
pika_tools_exit (Pika *pika)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
|
||||
g_clear_object (&toolbox_groups_binding);
|
||||
|
||||
tool_manager_exit (pika);
|
||||
|
||||
pika_tool_options_manager_exit (pika);
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = list->data;
|
||||
|
||||
pika_tools_set_tool_options_gui (tool_info->tool_options, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_tools_restore (Pika *pika)
|
||||
{
|
||||
PikaObject *object;
|
||||
GList *list;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
|
||||
/* restore tool order */
|
||||
pika_tools_reset (pika, pika->tool_item_list, TRUE);
|
||||
|
||||
/* make the generic operation tool invisible by default */
|
||||
object = pika_container_get_child_by_name (pika->tool_info_list,
|
||||
"pika-operation-tool");
|
||||
if (object)
|
||||
g_object_set (object, "visible", FALSE, NULL);
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = PIKA_TOOL_INFO (list->data);
|
||||
|
||||
/* get default values from prefs (see bug #120832) */
|
||||
pika_config_reset (PIKA_CONFIG (tool_info->tool_options));
|
||||
}
|
||||
|
||||
if (! pika_contexts_load (pika, &error))
|
||||
{
|
||||
pika_message_literal (pika, NULL, PIKA_MESSAGE_WARNING, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
if (! pika_internal_data_load (pika, &error))
|
||||
{
|
||||
pika_message_literal (pika, NULL, PIKA_MESSAGE_WARNING, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
/* make sure there is always a tool active, so broken config files
|
||||
* can't leave us with no initial tool
|
||||
*/
|
||||
if (! pika_context_get_tool (pika_get_user_context (pika)))
|
||||
{
|
||||
pika_context_set_tool (pika_get_user_context (pika),
|
||||
pika_get_tool_info_iter (pika)->data);
|
||||
}
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = PIKA_TOOL_INFO (list->data);
|
||||
PikaToolOptionsGUIFunc options_gui_func;
|
||||
|
||||
/* copy all context properties except those the tool actually
|
||||
* uses, because the subsequent deserialize() on the tool
|
||||
* options will only set the properties that were set to
|
||||
* non-default values at the time of saving, and we want to
|
||||
* keep these default values as if they have been saved.
|
||||
* (see bug #541586).
|
||||
*/
|
||||
pika_context_copy_properties (pika_get_user_context (pika),
|
||||
PIKA_CONTEXT (tool_info->tool_options),
|
||||
PIKA_CONTEXT_PROP_MASK_ALL &~
|
||||
(tool_info->context_props |
|
||||
PIKA_CONTEXT_PROP_MASK_TOOL |
|
||||
PIKA_CONTEXT_PROP_MASK_PAINT_INFO));
|
||||
|
||||
pika_tool_options_deserialize (tool_info->tool_options, NULL);
|
||||
|
||||
options_gui_func = g_object_get_data (G_OBJECT (tool_info),
|
||||
"pika-tool-options-gui-func");
|
||||
|
||||
if (! options_gui_func)
|
||||
options_gui_func = pika_tool_options_empty_gui;
|
||||
|
||||
pika_tools_set_tool_options_gui_func (tool_info->tool_options,
|
||||
options_gui_func);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pika_tools_save (Pika *pika,
|
||||
gboolean save_tool_options,
|
||||
gboolean always_save)
|
||||
{
|
||||
PikaConfigWriter *writer;
|
||||
GFile *file;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
|
||||
if (save_tool_options && (! tool_options_deleted || always_save))
|
||||
{
|
||||
GList *list;
|
||||
GError *error = NULL;
|
||||
|
||||
if (! pika_contexts_save (pika, &error))
|
||||
{
|
||||
pika_message_literal (pika, NULL, PIKA_MESSAGE_WARNING,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
if (! pika_internal_data_save (pika, &error))
|
||||
{
|
||||
pika_message_literal (pika, NULL, PIKA_MESSAGE_WARNING,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
pika_tool_options_create_folder ();
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = PIKA_TOOL_INFO (list->data);
|
||||
|
||||
pika_tool_options_serialize (tool_info->tool_options, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
file = pika_directory_file ("toolrc", NULL);
|
||||
|
||||
if (pika->be_verbose)
|
||||
g_print ("Writing '%s'\n", pika_file_get_utf8_name (file));
|
||||
|
||||
writer = pika_config_writer_new_from_file (file, TRUE, "PIKA toolrc", NULL);
|
||||
|
||||
if (writer)
|
||||
{
|
||||
pika_tools_serialize (pika, pika->tool_item_list, writer);
|
||||
|
||||
pika_config_writer_finish (writer, "end of toolrc", NULL);
|
||||
}
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_tools_clear (Pika *pika,
|
||||
GError **error)
|
||||
{
|
||||
GList *list;
|
||||
gboolean success = TRUE;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list && success;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = PIKA_TOOL_INFO (list->data);
|
||||
|
||||
success = pika_tool_options_delete (tool_info->tool_options, NULL);
|
||||
}
|
||||
|
||||
if (success)
|
||||
success = pika_contexts_clear (pika, error);
|
||||
|
||||
if (success)
|
||||
success = pika_internal_data_clear (pika, error);
|
||||
|
||||
if (success)
|
||||
tool_options_deleted = TRUE;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_tools_serialize (Pika *pika,
|
||||
PikaContainer *container,
|
||||
PikaConfigWriter *writer)
|
||||
{
|
||||
g_return_val_if_fail (PIKA_IS_PIKA (pika), FALSE);
|
||||
g_return_val_if_fail (PIKA_IS_CONTAINER (container), FALSE);
|
||||
|
||||
pika_config_writer_open (writer, "file-version");
|
||||
pika_config_writer_printf (writer, "%d", TOOL_RC_FILE_VERSION);
|
||||
pika_config_writer_close (writer);
|
||||
|
||||
pika_config_writer_linefeed (writer);
|
||||
|
||||
return pika_config_serialize (PIKA_CONFIG (container), writer, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_tools_deserialize (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GScanner *scanner)
|
||||
{
|
||||
enum
|
||||
{
|
||||
FILE_VERSION = 1
|
||||
};
|
||||
|
||||
PikaContainer *src_container;
|
||||
GTokenType token;
|
||||
guint scope_id;
|
||||
guint old_scope_id;
|
||||
gint file_version = 0;
|
||||
gboolean result = FALSE;
|
||||
|
||||
scope_id = g_type_qname (PIKA_TYPE_TOOL_GROUP);
|
||||
old_scope_id = g_scanner_set_scope (scanner, scope_id);
|
||||
|
||||
g_scanner_scope_add_symbol (scanner, scope_id,
|
||||
"file-version",
|
||||
GINT_TO_POINTER (FILE_VERSION));
|
||||
|
||||
token = G_TOKEN_LEFT_PAREN;
|
||||
|
||||
while (g_scanner_peek_next_token (scanner) == token &&
|
||||
(token != G_TOKEN_LEFT_PAREN ||
|
||||
! file_version))
|
||||
{
|
||||
token = g_scanner_get_next_token (scanner);
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case G_TOKEN_LEFT_PAREN:
|
||||
token = G_TOKEN_SYMBOL;
|
||||
break;
|
||||
|
||||
case G_TOKEN_SYMBOL:
|
||||
switch (GPOINTER_TO_INT (scanner->value.v_symbol))
|
||||
{
|
||||
case FILE_VERSION:
|
||||
token = G_TOKEN_INT;
|
||||
if (pika_scanner_parse_int (scanner, &file_version))
|
||||
token = G_TOKEN_RIGHT_PAREN;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case G_TOKEN_RIGHT_PAREN:
|
||||
token = G_TOKEN_LEFT_PAREN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_scanner_set_scope (scanner, old_scope_id);
|
||||
|
||||
if (token != G_TOKEN_LEFT_PAREN)
|
||||
{
|
||||
g_scanner_get_next_token (scanner);
|
||||
g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
|
||||
_("fatal parse error"), TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else if (file_version != TOOL_RC_FILE_VERSION)
|
||||
{
|
||||
g_scanner_error (scanner, "wrong toolrc file format version");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pika_container_freeze (container);
|
||||
|
||||
/* make sure the various PikaToolItem types are registered */
|
||||
g_type_class_unref (g_type_class_ref (PIKA_TYPE_TOOL_GROUP));
|
||||
g_type_class_unref (g_type_class_ref (PIKA_TYPE_TOOL_INFO));
|
||||
|
||||
pika_container_clear (container);
|
||||
|
||||
src_container = g_object_new (PIKA_TYPE_LIST,
|
||||
"children-type", PIKA_TYPE_TOOL_ITEM,
|
||||
"append", TRUE,
|
||||
NULL);
|
||||
|
||||
if (pika_config_deserialize (PIKA_CONFIG (src_container),
|
||||
scanner, 0, NULL))
|
||||
{
|
||||
GHashTable *tools;
|
||||
GList *list;
|
||||
|
||||
result = TRUE;
|
||||
|
||||
tools = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
pika_tools_copy_structure (pika, src_container, container, tools);
|
||||
|
||||
for (list = pika_get_tool_info_iter (pika);
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolInfo *tool_info = list->data;
|
||||
|
||||
if (! tool_info->hidden && ! g_hash_table_contains (tools, tool_info))
|
||||
{
|
||||
if (tool_info->experimental)
|
||||
{
|
||||
/* if an experimental tool is not in the file, just add it to
|
||||
* the tool-item list.
|
||||
*/
|
||||
pika_container_add (container, PIKA_OBJECT (tool_info));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, it means we added a new stable tool. this must
|
||||
* be the user toolrc file; rejct it, so that we fall back to
|
||||
* the default toolrc file, which should contain the missing
|
||||
* tool.
|
||||
*/
|
||||
g_scanner_error (scanner, "missing tools in toolrc file");
|
||||
|
||||
result = FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_unref (tools);
|
||||
}
|
||||
|
||||
g_object_unref (src_container);
|
||||
|
||||
pika_container_thaw (container);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
pika_tools_reset (Pika *pika,
|
||||
PikaContainer *container,
|
||||
gboolean user_toolrc)
|
||||
{
|
||||
GList *files = NULL;
|
||||
GList *list;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
g_return_if_fail (PIKA_IS_CONTAINER (container));
|
||||
|
||||
if (user_toolrc)
|
||||
files = g_list_prepend (files, pika_directory_file ("toolrc", NULL));
|
||||
files = g_list_prepend (files, pika_sysconf_directory_file ("toolrc", NULL));
|
||||
|
||||
files = g_list_reverse (files);
|
||||
|
||||
pika_container_freeze (container);
|
||||
|
||||
pika_container_clear (container);
|
||||
|
||||
for (list = files; list; list = g_list_next (list))
|
||||
{
|
||||
GScanner *scanner;
|
||||
GFile *file = list->data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (pika->be_verbose)
|
||||
g_print ("Parsing '%s'\n", pika_file_get_utf8_name (file));
|
||||
|
||||
scanner = pika_scanner_new_file (file, &error);
|
||||
|
||||
if (scanner && pika_tools_deserialize (pika, container, scanner))
|
||||
{
|
||||
pika_scanner_unref (scanner);
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error->code != G_IO_ERROR_NOT_FOUND)
|
||||
{
|
||||
pika_message_literal (pika, NULL,
|
||||
PIKA_MESSAGE_WARNING, error->message);
|
||||
}
|
||||
|
||||
g_clear_error (&error);
|
||||
|
||||
pika_container_clear (container);
|
||||
}
|
||||
|
||||
g_clear_pointer (&scanner, pika_scanner_unref);
|
||||
}
|
||||
|
||||
g_list_free_full (files, g_object_unref);
|
||||
|
||||
if (pika_container_is_empty (container))
|
||||
{
|
||||
if (pika->be_verbose)
|
||||
g_print ("Using default tool order\n");
|
||||
|
||||
pika_tools_copy_structure (pika, pika->tool_info_list, container, NULL);
|
||||
}
|
||||
|
||||
pika_container_thaw (container);
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static void
|
||||
pika_tools_register (GType tool_type,
|
||||
GType tool_options_type,
|
||||
PikaToolOptionsGUIFunc options_gui_func,
|
||||
PikaContextPropMask context_props,
|
||||
const gchar *identifier,
|
||||
const gchar *label,
|
||||
const gchar *tooltip,
|
||||
const gchar *menu_label,
|
||||
const gchar *menu_accel,
|
||||
const gchar *help_domain,
|
||||
const gchar *help_data,
|
||||
const gchar *icon_name,
|
||||
gpointer data)
|
||||
{
|
||||
Pika *pika = (Pika *) data;
|
||||
PikaToolInfo *tool_info;
|
||||
const gchar *paint_core_name;
|
||||
gboolean visible;
|
||||
|
||||
g_return_if_fail (PIKA_IS_PIKA (pika));
|
||||
g_return_if_fail (g_type_is_a (tool_type, PIKA_TYPE_TOOL));
|
||||
g_return_if_fail (tool_options_type == G_TYPE_NONE ||
|
||||
g_type_is_a (tool_options_type, PIKA_TYPE_TOOL_OPTIONS));
|
||||
|
||||
if (tool_options_type == G_TYPE_NONE)
|
||||
tool_options_type = PIKA_TYPE_TOOL_OPTIONS;
|
||||
|
||||
if (tool_type == PIKA_TYPE_PENCIL_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-pencil";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_PAINTBRUSH_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-paintbrush";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_ERASER_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-eraser";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_AIRBRUSH_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-airbrush";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_CLONE_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-clone";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_HEAL_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-heal";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_PERSPECTIVE_CLONE_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-perspective-clone";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_CONVOLVE_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-convolve";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_SMUDGE_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-smudge";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_DODGE_BURN_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-dodge-burn";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_INK_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-ink";
|
||||
}
|
||||
else if (tool_type == PIKA_TYPE_MYBRUSH_TOOL)
|
||||
{
|
||||
paint_core_name = "pika-mybrush";
|
||||
}
|
||||
else
|
||||
{
|
||||
paint_core_name = "pika-paintbrush";
|
||||
}
|
||||
|
||||
tool_info = pika_tool_info_new (pika,
|
||||
tool_type,
|
||||
tool_options_type,
|
||||
context_props,
|
||||
identifier,
|
||||
label,
|
||||
tooltip,
|
||||
menu_label,
|
||||
menu_accel,
|
||||
help_domain,
|
||||
help_data,
|
||||
paint_core_name,
|
||||
icon_name);
|
||||
|
||||
visible = (! g_type_is_a (tool_type, PIKA_TYPE_FILTER_TOOL));
|
||||
|
||||
pika_tool_item_set_visible (PIKA_TOOL_ITEM (tool_info), visible);
|
||||
|
||||
/* hack to hide the operation tool entirely */
|
||||
if (tool_type == PIKA_TYPE_OPERATION_TOOL)
|
||||
tool_info->hidden = TRUE;
|
||||
|
||||
/* hack to not require experimental tools to be present in toolrc */
|
||||
if (tool_type == PIKA_TYPE_N_POINT_DEFORMATION_TOOL ||
|
||||
tool_type == PIKA_TYPE_SEAMLESS_CLONE_TOOL ||
|
||||
tool_type == PIKA_TYPE_PAINT_SELECT_TOOL)
|
||||
{
|
||||
tool_info->experimental = TRUE;
|
||||
}
|
||||
|
||||
g_object_set_data (G_OBJECT (tool_info), "pika-tool-options-gui-func",
|
||||
options_gui_func);
|
||||
|
||||
pika_container_add (pika->tool_info_list, PIKA_OBJECT (tool_info));
|
||||
g_object_unref (tool_info);
|
||||
|
||||
if (tool_type == PIKA_TYPE_PAINTBRUSH_TOOL)
|
||||
pika_tool_info_set_standard (pika, tool_info);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_tools_copy_structure (Pika *pika,
|
||||
PikaContainer *src_container,
|
||||
PikaContainer *dest_container,
|
||||
GHashTable *tools)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = PIKA_LIST (src_container)->queue->head;
|
||||
list;
|
||||
list = g_list_next (list))
|
||||
{
|
||||
PikaToolItem *src_tool_item = list->data;
|
||||
PikaToolItem *dest_tool_item = NULL;
|
||||
|
||||
if (PIKA_IS_TOOL_GROUP (src_tool_item))
|
||||
{
|
||||
dest_tool_item = PIKA_TOOL_ITEM (pika_tool_group_new ());
|
||||
|
||||
pika_tools_copy_structure (
|
||||
pika,
|
||||
pika_viewable_get_children (PIKA_VIEWABLE (src_tool_item)),
|
||||
pika_viewable_get_children (PIKA_VIEWABLE (dest_tool_item)),
|
||||
tools);
|
||||
|
||||
pika_tool_group_set_active_tool (
|
||||
PIKA_TOOL_GROUP (dest_tool_item),
|
||||
pika_tool_group_get_active_tool (PIKA_TOOL_GROUP (src_tool_item)));
|
||||
}
|
||||
else
|
||||
{
|
||||
dest_tool_item = PIKA_TOOL_ITEM (
|
||||
pika_get_tool_info (pika, pika_object_get_name (src_tool_item)));
|
||||
|
||||
if (dest_tool_item)
|
||||
{
|
||||
if (! PIKA_TOOL_INFO (dest_tool_item)->hidden)
|
||||
{
|
||||
g_object_ref (dest_tool_item);
|
||||
|
||||
if (tools)
|
||||
g_hash_table_add (tools, dest_tool_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
dest_tool_item = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dest_tool_item)
|
||||
{
|
||||
pika_tool_item_set_visible (
|
||||
dest_tool_item,
|
||||
pika_tool_item_get_visible (src_tool_item));
|
||||
|
||||
pika_container_add (dest_container,
|
||||
PIKA_OBJECT (dest_tool_item));
|
||||
|
||||
g_object_unref (dest_tool_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
app/tools/pika-tools.h
Normal file
49
app/tools/pika-tools.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_TOOLS_H__
|
||||
#define __PIKA_TOOLS_H__
|
||||
|
||||
|
||||
void pika_tools_init (Pika *pika);
|
||||
void pika_tools_exit (Pika *pika);
|
||||
|
||||
void pika_tools_restore (Pika *pika);
|
||||
void pika_tools_save (Pika *pika,
|
||||
gboolean save_tool_options,
|
||||
gboolean always_save);
|
||||
|
||||
gboolean pika_tools_clear (Pika *pika,
|
||||
GError **error);
|
||||
|
||||
gboolean pika_tools_serialize (Pika *pika,
|
||||
PikaContainer *container,
|
||||
PikaConfigWriter *writer);
|
||||
gboolean pika_tools_deserialize (Pika *pika,
|
||||
PikaContainer *container,
|
||||
GScanner *scanner);
|
||||
|
||||
void pika_tools_reset (Pika *pika,
|
||||
PikaContainer *container,
|
||||
gboolean user_toolrc);
|
||||
|
||||
|
||||
#endif /* __PIKA_TOOLS_H__ */
|
||||
151
app/tools/pikaairbrushtool.c
Normal file
151
app/tools/pikaairbrushtool.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "paint/pikaairbrush.h"
|
||||
#include "paint/pikaairbrushoptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
|
||||
#include "pikaairbrushtool.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
#include "pikapainttool-paint.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_airbrush_tool_constructed (GObject *object);
|
||||
|
||||
static void pika_airbrush_tool_airbrush_stamp (PikaAirbrush *airbrush,
|
||||
PikaAirbrushTool *airbrush_tool);
|
||||
|
||||
static void pika_airbrush_tool_stamp (PikaAirbrushTool *airbrush_tool,
|
||||
gpointer data);
|
||||
|
||||
static GtkWidget * pika_airbrush_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaAirbrushTool, pika_airbrush_tool, PIKA_TYPE_PAINTBRUSH_TOOL)
|
||||
|
||||
#define parent_class pika_airbrush_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_airbrush_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_AIRBRUSH_TOOL,
|
||||
PIKA_TYPE_AIRBRUSH_OPTIONS,
|
||||
pika_airbrush_options_gui,
|
||||
PIKA_PAINT_OPTIONS_CONTEXT_MASK |
|
||||
PIKA_CONTEXT_PROP_MASK_GRADIENT,
|
||||
"pika-airbrush-tool",
|
||||
_("Airbrush"),
|
||||
_("Airbrush Tool: Paint using a brush, with variable pressure"),
|
||||
N_("_Airbrush"), "A",
|
||||
NULL, PIKA_HELP_TOOL_AIRBRUSH,
|
||||
PIKA_ICON_TOOL_AIRBRUSH,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_airbrush_tool_class_init (PikaAirbrushToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = pika_airbrush_tool_constructed;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_airbrush_tool_init (PikaAirbrushTool *airbrush)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (airbrush);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_AIRBRUSH);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_airbrush_tool_constructed (GObject *object)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
g_signal_connect_object (paint_tool->core, "stamp",
|
||||
G_CALLBACK (pika_airbrush_tool_airbrush_stamp),
|
||||
object, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_airbrush_tool_airbrush_stamp (PikaAirbrush *airbrush,
|
||||
PikaAirbrushTool *airbrush_tool)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (airbrush_tool);
|
||||
|
||||
pika_paint_tool_paint_push (
|
||||
paint_tool,
|
||||
(PikaPaintToolPaintFunc) pika_airbrush_tool_stamp,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_airbrush_tool_stamp (PikaAirbrushTool *airbrush_tool,
|
||||
gpointer data)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (airbrush_tool);
|
||||
|
||||
pika_airbrush_stamp (PIKA_AIRBRUSH (paint_tool->core));
|
||||
}
|
||||
|
||||
|
||||
/* tool options stuff */
|
||||
|
||||
static GtkWidget *
|
||||
pika_airbrush_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *button;
|
||||
GtkWidget *scale;
|
||||
|
||||
button = pika_prop_check_button_new (config, "motion-only", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
scale = pika_prop_spin_scale_new (config, "rate",
|
||||
1.0, 10.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
scale = pika_prop_spin_scale_new (config, "flow",
|
||||
1.0, 10.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
57
app/tools/pikaairbrushtool.h
Normal file
57
app/tools/pikaairbrushtool.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_AIRBRUSH_TOOL_H__
|
||||
#define __PIKA_AIRBRUSH_TOOL_H__
|
||||
|
||||
|
||||
#include "pikapaintbrushtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_AIRBRUSH_TOOL (pika_airbrush_tool_get_type ())
|
||||
#define PIKA_AIRBRUSH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_AIRBRUSH_TOOL, PikaAirbrushTool))
|
||||
#define PIKA_AIRBRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_AIRBRUSH_TOOL, PikaAirbrushToolClass))
|
||||
#define PIKA_IS_AIRBRUSH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_AIRBRUSH_TOOL))
|
||||
#define PIKA_IS_AIRBRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_AIRBRUSH_TOOL))
|
||||
#define PIKA_AIRBRUSH_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_AIRBRUSH_TOOL, PikaAirbrushToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaAirbrushTool PikaAirbrushTool;
|
||||
typedef struct _PikaAirbrushToolClass PikaAirbrushToolClass;
|
||||
|
||||
struct _PikaAirbrushTool
|
||||
{
|
||||
PikaPaintbrushTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaAirbrushToolClass
|
||||
{
|
||||
PikaPaintbrushToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_airbrush_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_airbrush_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_AIRBRUSH_TOOL_H__ */
|
||||
888
app/tools/pikaalignoptions.c
Normal file
888
app/tools/pikaalignoptions.c
Normal file
@ -0,0 +1,888 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikaguide.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikalayer.h"
|
||||
#include "core/pikachannel.h"
|
||||
|
||||
#include "vectors/pikavectors.h"
|
||||
|
||||
#include "widgets/pikapivotselector.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikaalignoptions.h"
|
||||
#include "pikatooloptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
#define ALIGN_VER_N_BUTTONS 3
|
||||
#define ALIGN_HOR_N_BUTTONS 3
|
||||
#define DISTR_VER_N_BUTTONS 2
|
||||
#define DISTR_HOR_N_BUTTONS 2
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
ALIGN_BUTTON_CLICKED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ALIGN_REFERENCE,
|
||||
PROP_ALIGN_LAYERS,
|
||||
PROP_ALIGN_VECTORS,
|
||||
PROP_ALIGN_CONTENTS,
|
||||
PROP_PIVOT_X,
|
||||
PROP_PIVOT_Y,
|
||||
};
|
||||
|
||||
struct _PikaAlignOptionsPrivate
|
||||
{
|
||||
gboolean align_layers;
|
||||
gboolean align_vectors;
|
||||
gboolean align_contents;
|
||||
gdouble pivot_x;
|
||||
gdouble pivot_y;
|
||||
|
||||
GList *selected_guides;
|
||||
GObject *reference;
|
||||
|
||||
GtkWidget *selected_guides_label;
|
||||
GtkWidget *reference_combo;
|
||||
GtkWidget *reference_box;
|
||||
GtkWidget *reference_label;
|
||||
GtkWidget *pivot_selector;
|
||||
|
||||
GtkWidget *align_ver_button[ALIGN_VER_N_BUTTONS];
|
||||
GtkWidget *align_hor_button[ALIGN_HOR_N_BUTTONS];
|
||||
GtkWidget *distr_ver_button[DISTR_VER_N_BUTTONS];
|
||||
GtkWidget *distr_hor_button[DISTR_HOR_N_BUTTONS];
|
||||
};
|
||||
|
||||
|
||||
static void pika_align_options_finalize (GObject *object);
|
||||
static void pika_align_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_align_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void pika_align_options_image_changed (PikaContext *context,
|
||||
PikaImage *image,
|
||||
PikaAlignOptions *options);
|
||||
|
||||
static void pika_align_options_update_area (PikaAlignOptions *options);
|
||||
static void pika_align_options_guide_removed (PikaImage *image,
|
||||
PikaGuide *guide,
|
||||
PikaAlignOptions *options);
|
||||
static void pika_align_options_reference_removed (GObject *object,
|
||||
PikaAlignOptions *options);
|
||||
static void pika_align_options_pivot_changed (PikaPivotSelector *selector,
|
||||
PikaAlignOptions *options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaAlignOptions, pika_align_options, PIKA_TYPE_TOOL_OPTIONS)
|
||||
|
||||
#define parent_class pika_selection_options_parent_class
|
||||
|
||||
static guint align_options_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
static void
|
||||
pika_align_options_class_init (PikaAlignOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_align_options_finalize;
|
||||
object_class->set_property = pika_align_options_set_property;
|
||||
object_class->get_property = pika_align_options_get_property;
|
||||
|
||||
klass->align_button_clicked = NULL;
|
||||
|
||||
align_options_signals[ALIGN_BUTTON_CLICKED] =
|
||||
g_signal_new ("align-button-clicked",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaAlignOptionsClass,
|
||||
align_button_clicked),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
PIKA_TYPE_ALIGNMENT_TYPE);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_ALIGN_REFERENCE,
|
||||
"align-reference",
|
||||
_("Relative to"),
|
||||
_("Reference object targets will be aligned on"),
|
||||
PIKA_TYPE_ALIGN_REFERENCE_TYPE,
|
||||
PIKA_ALIGN_REFERENCE_IMAGE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_LAYERS,
|
||||
"align-layers",
|
||||
_("Selected layers"),
|
||||
_("Selected layers will be aligned or distributed by the tool"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_VECTORS,
|
||||
"align-vectors",
|
||||
_("Selected paths"),
|
||||
_("Selected paths will be aligned or distributed by the tool"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_ALIGN_CONTENTS,
|
||||
"align-contents",
|
||||
_("Use extents of layer contents"),
|
||||
_("Instead of aligning or distributing on layer borders, use its content bounding box"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_PIVOT_X,
|
||||
"pivot-x",
|
||||
"X position of the point to align in objects",
|
||||
NULL,
|
||||
0.0, 1.0, 0.5,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_PIVOT_Y,
|
||||
"pivot-y",
|
||||
"Y position of the point to align in objects",
|
||||
NULL,
|
||||
0.0, 1.0, 0.5,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_init (PikaAlignOptions *options)
|
||||
{
|
||||
options->priv = pika_align_options_get_instance_private (options);
|
||||
|
||||
options->priv->selected_guides = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_finalize (GObject *object)
|
||||
{
|
||||
PikaAlignOptions *options = PIKA_ALIGN_OPTIONS (object);
|
||||
|
||||
if (PIKA_CONTEXT (options)->pika)
|
||||
pika_align_options_image_changed (pika_get_user_context (PIKA_CONTEXT (options)->pika),
|
||||
NULL, options);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaAlignOptions *options = PIKA_ALIGN_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ALIGN_REFERENCE:
|
||||
options->align_reference = g_value_get_enum (value);
|
||||
pika_align_options_update_area (options);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_LAYERS:
|
||||
options->priv->align_layers = g_value_get_boolean (value);
|
||||
pika_align_options_update_area (options);
|
||||
break;
|
||||
case PROP_ALIGN_VECTORS:
|
||||
options->priv->align_vectors = g_value_get_boolean (value);
|
||||
pika_align_options_update_area (options);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_CONTENTS:
|
||||
options->priv->align_contents = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_PIVOT_X:
|
||||
options->priv->pivot_x = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_PIVOT_Y:
|
||||
options->priv->pivot_y = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaAlignOptions *options = PIKA_ALIGN_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ALIGN_REFERENCE:
|
||||
g_value_set_enum (value, options->align_reference);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_LAYERS:
|
||||
g_value_set_boolean (value, options->priv->align_layers);
|
||||
break;
|
||||
case PROP_ALIGN_VECTORS:
|
||||
g_value_set_boolean (value, options->priv->align_vectors);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_CONTENTS:
|
||||
g_value_set_boolean (value, options->priv->align_contents);
|
||||
break;
|
||||
|
||||
case PROP_PIVOT_X:
|
||||
g_value_set_double (value, options->priv->pivot_x);
|
||||
break;
|
||||
case PROP_PIVOT_Y:
|
||||
g_value_set_double (value, options->priv->pivot_y);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_button_clicked (GtkButton *button,
|
||||
PikaAlignOptions *options)
|
||||
{
|
||||
PikaAlignmentType action;
|
||||
|
||||
action = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
|
||||
"align-action"));
|
||||
|
||||
g_signal_emit (options, align_options_signals[ALIGN_BUTTON_CLICKED], 0,
|
||||
action);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
pika_align_options_button_new (PikaAlignOptions *options,
|
||||
PikaAlignmentType action,
|
||||
GtkWidget *parent,
|
||||
const gchar *tooltip)
|
||||
{
|
||||
GtkWidget *button;
|
||||
GtkWidget *image;
|
||||
const gchar *icon_name = NULL;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PIKA_ALIGN_LEFT:
|
||||
icon_name = PIKA_ICON_GRAVITY_WEST;
|
||||
break;
|
||||
case PIKA_ALIGN_HCENTER:
|
||||
icon_name = PIKA_ICON_CENTER_HORIZONTAL;
|
||||
break;
|
||||
case PIKA_ALIGN_RIGHT:
|
||||
icon_name = PIKA_ICON_GRAVITY_EAST;
|
||||
break;
|
||||
case PIKA_ALIGN_TOP:
|
||||
icon_name = PIKA_ICON_GRAVITY_NORTH;
|
||||
break;
|
||||
case PIKA_ALIGN_VCENTER:
|
||||
icon_name = PIKA_ICON_CENTER_VERTICAL;
|
||||
break;
|
||||
case PIKA_ALIGN_BOTTOM:
|
||||
icon_name = PIKA_ICON_GRAVITY_SOUTH;
|
||||
break;
|
||||
case PIKA_ARRANGE_HFILL:
|
||||
icon_name = PIKA_ICON_FILL_HORIZONTAL;
|
||||
break;
|
||||
case PIKA_ARRANGE_VFILL:
|
||||
icon_name = PIKA_ICON_FILL_VERTICAL;
|
||||
break;
|
||||
case PIKA_DISTRIBUTE_EVEN_HORIZONTAL_GAP:
|
||||
icon_name = PIKA_ICON_EVEN_HORIZONTAL_GAP;
|
||||
break;
|
||||
case PIKA_DISTRIBUTE_EVEN_VERTICAL_GAP:
|
||||
icon_name = PIKA_ICON_EVEN_VERTICAL_GAP;
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
gtk_widget_show (button);
|
||||
|
||||
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
gtk_widget_show (image);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (parent), button, FALSE, FALSE, 0);
|
||||
gtk_widget_show (button);
|
||||
|
||||
pika_help_set_help_data (button, tooltip, NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (button), "align-action",
|
||||
GINT_TO_POINTER (action));
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (pika_align_options_button_clicked),
|
||||
options);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_align_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
PikaAlignOptions *options = PIKA_ALIGN_OPTIONS (tool_options);
|
||||
GtkWidget *vbox = pika_tool_options_gui (tool_options);
|
||||
GtkWidget *widget;
|
||||
GtkWidget *section_vbox;
|
||||
GtkWidget *items_grid;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *combo;
|
||||
gchar *text;
|
||||
gint n = 0;
|
||||
|
||||
/* Selected objects */
|
||||
frame = pika_frame_new (_("Targets"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
section_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), section_vbox);
|
||||
gtk_widget_show (section_vbox);
|
||||
|
||||
items_grid = gtk_grid_new ();
|
||||
gtk_container_add (GTK_CONTAINER (section_vbox), items_grid);
|
||||
gtk_widget_show (items_grid);
|
||||
|
||||
widget = pika_prop_check_button_new (config, "align-contents", NULL);
|
||||
widget = pika_prop_expanding_frame_new (config, "align-layers",
|
||||
NULL, widget, NULL);
|
||||
gtk_grid_attach (GTK_GRID (items_grid), widget, 0, 0, 1, 1);
|
||||
|
||||
widget = pika_prop_check_button_new (config, "align-vectors", NULL);
|
||||
gtk_grid_attach (GTK_GRID (items_grid), widget, 0, 1, 1, 1);
|
||||
|
||||
options->priv->pivot_selector = pika_pivot_selector_new (0.0, 0.0, 1.0, 1.0);
|
||||
gtk_widget_set_tooltip_text (options->priv->pivot_selector,
|
||||
_("Set anchor point of targets"));
|
||||
pika_pivot_selector_set_position (PIKA_PIVOT_SELECTOR (options->priv->pivot_selector),
|
||||
options->priv->pivot_x, options->priv->pivot_y);
|
||||
gtk_grid_attach (GTK_GRID (items_grid), options->priv->pivot_selector, 1, 0, 1, 2);
|
||||
gtk_widget_show (options->priv->pivot_selector);
|
||||
|
||||
g_signal_connect (options->priv->pivot_selector, "changed",
|
||||
G_CALLBACK (pika_align_options_pivot_changed),
|
||||
options);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
widget = gtk_image_new_from_icon_name (PIKA_ICON_CURSOR, GTK_ICON_SIZE_BUTTON);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
/* TRANSLATORS: the %s strings are modifiers such as Shift, Alt or Cmd. */
|
||||
text = g_strdup_printf (_("%s-pick target guides (%s-%s to add more)"),
|
||||
pika_get_mod_string (GDK_MOD1_MASK),
|
||||
pika_get_mod_string (pika_get_extend_selection_mask ()),
|
||||
pika_get_mod_string (GDK_MOD1_MASK));
|
||||
widget = gtk_label_new (text);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
|
||||
gtk_label_set_line_wrap_mode (GTK_LABEL (widget), PANGO_WRAP_WORD);
|
||||
g_free (text);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
widget = gtk_label_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
options->priv->selected_guides_label = widget;
|
||||
|
||||
/* Align frame */
|
||||
frame = pika_frame_new (_("Align"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
section_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), section_vbox);
|
||||
gtk_widget_show (section_vbox);
|
||||
|
||||
/* Align frame: reference */
|
||||
combo = pika_prop_enum_combo_box_new (config, "align-reference", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Relative to"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), combo, FALSE, FALSE, 0);
|
||||
options->priv->reference_combo = combo;
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
options->priv->reference_box = hbox;
|
||||
|
||||
widget = gtk_image_new_from_icon_name (PIKA_ICON_CURSOR, GTK_ICON_SIZE_BUTTON);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
widget = gtk_label_new (_("Select the reference object"));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
widget = gtk_label_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
options->priv->reference_label = widget;
|
||||
|
||||
/* Align frame: buttons */
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
n = 0;
|
||||
options->priv->align_ver_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ALIGN_LEFT, hbox,
|
||||
_("Align anchor points of targets on left edge of reference"));
|
||||
|
||||
options->priv->align_ver_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ALIGN_HCENTER, hbox,
|
||||
_("Align anchor points of targets on vertical middle of reference"));
|
||||
|
||||
options->priv->align_ver_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ALIGN_RIGHT, hbox,
|
||||
_("Align anchor points of targets on right edge of reference"));
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
n = 0;
|
||||
options->priv->align_hor_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ALIGN_TOP, hbox,
|
||||
_("Align anchor points of targets on top edge of reference"));
|
||||
|
||||
options->priv->align_hor_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ALIGN_VCENTER, hbox,
|
||||
_("Align anchor points of targets on horizontal middle of reference"));
|
||||
|
||||
options->priv->align_hor_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ALIGN_BOTTOM, hbox,
|
||||
_("Align anchor points of targets on bottom of reference"));
|
||||
|
||||
/* Distribute frame */
|
||||
frame = pika_frame_new (_("Distribute"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
section_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
gtk_container_add (GTK_CONTAINER (frame), section_vbox);
|
||||
gtk_widget_show (section_vbox);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
n = 0;
|
||||
options->priv->distr_ver_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ARRANGE_HFILL, hbox,
|
||||
_("Distribute anchor points of targets evenly in the horizontal"));
|
||||
options->priv->distr_ver_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_DISTRIBUTE_EVEN_HORIZONTAL_GAP, hbox,
|
||||
_("Distribute horizontally with even horizontal gaps"));
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (section_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
n = 0;
|
||||
options->priv->distr_hor_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_ARRANGE_VFILL, hbox,
|
||||
_("Distribute anchor points of targets evenly in the vertical"));
|
||||
options->priv->distr_hor_button[n++] =
|
||||
pika_align_options_button_new (options, PIKA_DISTRIBUTE_EVEN_VERTICAL_GAP, hbox,
|
||||
_("Distribute vertically with even vertical gaps"));
|
||||
|
||||
g_signal_connect (pika_get_user_context (PIKA_CONTEXT (options)->pika),
|
||||
"image-changed",
|
||||
G_CALLBACK (pika_align_options_image_changed),
|
||||
tool_options);
|
||||
pika_align_options_image_changed (pika_get_user_context (PIKA_CONTEXT (options)->pika),
|
||||
pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika)),
|
||||
options);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
||||
GList *
|
||||
pika_align_options_get_objects (PikaAlignOptions *options)
|
||||
{
|
||||
PikaImage *image;
|
||||
GList *objects = NULL;
|
||||
|
||||
image = pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika));
|
||||
|
||||
if (image)
|
||||
{
|
||||
if (options->priv->align_layers)
|
||||
{
|
||||
GList *layers;
|
||||
|
||||
layers = pika_image_get_selected_layers (image);
|
||||
layers = g_list_copy (layers);
|
||||
objects = g_list_concat (objects, layers);
|
||||
}
|
||||
if (options->priv->align_vectors)
|
||||
{
|
||||
GList *vectors;
|
||||
|
||||
vectors = pika_image_get_selected_vectors (image);
|
||||
vectors = g_list_copy (vectors);
|
||||
objects = g_list_concat (objects, vectors);
|
||||
}
|
||||
|
||||
if (options->priv->selected_guides)
|
||||
{
|
||||
GList *guides;
|
||||
|
||||
guides = g_list_copy (options->priv->selected_guides);
|
||||
objects = g_list_concat (objects, guides);
|
||||
}
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
void
|
||||
pika_align_options_get_pivot (PikaAlignOptions *options,
|
||||
gdouble *x,
|
||||
gdouble *y)
|
||||
{
|
||||
pika_pivot_selector_get_position (PIKA_PIVOT_SELECTOR (options->priv->pivot_selector),
|
||||
x, y);
|
||||
}
|
||||
|
||||
void
|
||||
pika_align_options_pick_reference (PikaAlignOptions *options,
|
||||
GObject *object)
|
||||
{
|
||||
if (options->priv->reference)
|
||||
g_signal_handlers_disconnect_by_func (options->priv->reference,
|
||||
G_CALLBACK (pika_align_options_reference_removed),
|
||||
options);
|
||||
|
||||
g_clear_object (&options->priv->reference);
|
||||
|
||||
if (object)
|
||||
{
|
||||
options->priv->reference = g_object_ref (object);
|
||||
|
||||
/* Both PikaItem and PikaGuide/PikaAuxItem have a "removed" signal with
|
||||
* similar signature. */
|
||||
g_signal_connect_object (options->priv->reference,
|
||||
"removed",
|
||||
G_CALLBACK (pika_align_options_reference_removed),
|
||||
options, 0);
|
||||
}
|
||||
|
||||
pika_align_options_update_area (options);
|
||||
}
|
||||
|
||||
GObject *
|
||||
pika_align_options_get_reference (PikaAlignOptions *options,
|
||||
gboolean blink_if_none)
|
||||
{
|
||||
GObject *reference = NULL;
|
||||
PikaImage *image;
|
||||
|
||||
image = pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika));
|
||||
|
||||
if (image)
|
||||
{
|
||||
switch (options->align_reference)
|
||||
{
|
||||
case PIKA_ALIGN_REFERENCE_IMAGE:
|
||||
reference = G_OBJECT (image);
|
||||
break;
|
||||
case PIKA_ALIGN_REFERENCE_SELECTION:
|
||||
reference = G_OBJECT (pika_image_get_mask (image));
|
||||
break;
|
||||
case PIKA_ALIGN_REFERENCE_PICK:
|
||||
reference = G_OBJECT (options->priv->reference);
|
||||
break;
|
||||
}
|
||||
|
||||
if (reference == NULL && blink_if_none)
|
||||
{
|
||||
if (options->align_reference == PIKA_ALIGN_REFERENCE_PICK)
|
||||
pika_widget_blink (options->priv->reference_box);
|
||||
else
|
||||
pika_widget_blink (options->priv->reference_combo);
|
||||
}
|
||||
}
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_align_options_align_contents (PikaAlignOptions *options)
|
||||
{
|
||||
return options->priv->align_contents;
|
||||
}
|
||||
|
||||
void
|
||||
pika_align_options_pick_guide (PikaAlignOptions *options,
|
||||
PikaGuide *guide,
|
||||
gboolean extend)
|
||||
{
|
||||
if (! extend)
|
||||
g_clear_pointer (&options->priv->selected_guides, g_list_free);
|
||||
|
||||
if (guide)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
if ((list = g_list_find (options->priv->selected_guides, guide)))
|
||||
options->priv->selected_guides = g_list_delete_link (options->priv->selected_guides, list);
|
||||
else
|
||||
options->priv->selected_guides = g_list_prepend (options->priv->selected_guides, guide);
|
||||
}
|
||||
|
||||
pika_align_options_update_area (options);
|
||||
}
|
||||
|
||||
|
||||
/* Private functions */
|
||||
|
||||
static void
|
||||
pika_align_options_image_changed (PikaContext *context,
|
||||
PikaImage *image,
|
||||
PikaAlignOptions *options)
|
||||
{
|
||||
PikaImage *prev_image;
|
||||
|
||||
prev_image = g_object_get_data (G_OBJECT (options), "pika-align-options-image");
|
||||
|
||||
if (image != prev_image)
|
||||
{
|
||||
/* We cannot keep track of selected guides across image changes. */
|
||||
g_clear_pointer (&options->priv->selected_guides, g_list_free);
|
||||
pika_align_options_pick_reference (options, NULL);
|
||||
|
||||
if (prev_image)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (prev_image,
|
||||
G_CALLBACK (pika_align_options_update_area),
|
||||
options);
|
||||
g_signal_handlers_disconnect_by_func (prev_image,
|
||||
G_CALLBACK (pika_align_options_guide_removed),
|
||||
options);
|
||||
}
|
||||
if (image)
|
||||
{
|
||||
g_signal_connect_object (image, "selected-channels-changed",
|
||||
G_CALLBACK (pika_align_options_update_area),
|
||||
options, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (image, "selected-layers-changed",
|
||||
G_CALLBACK (pika_align_options_update_area),
|
||||
options, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (image, "guide-removed",
|
||||
G_CALLBACK (pika_align_options_guide_removed),
|
||||
options, 0);
|
||||
}
|
||||
|
||||
g_object_set_data (G_OBJECT (options), "pika-align-options-image", image);
|
||||
pika_align_options_update_area (options);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_update_area (PikaAlignOptions *options)
|
||||
{
|
||||
PikaImage *image;
|
||||
GList *layers = NULL;
|
||||
GList *vectors = NULL;
|
||||
gboolean enable_ver_align = FALSE;
|
||||
gboolean enable_hor_align = FALSE;
|
||||
gboolean enable_ver_distr = FALSE;
|
||||
gboolean enable_hor_distr = FALSE;
|
||||
gint n_items = 0;
|
||||
gchar *text;
|
||||
|
||||
image = pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika));
|
||||
|
||||
/* GUI not created yet. */
|
||||
if (! options->priv->reference_combo)
|
||||
return;
|
||||
|
||||
if (image)
|
||||
{
|
||||
layers = pika_image_get_selected_layers (image);
|
||||
vectors = pika_image_get_selected_vectors (image);
|
||||
|
||||
if (options->priv->align_layers)
|
||||
n_items += g_list_length (layers);
|
||||
if (options->priv->align_vectors)
|
||||
n_items += g_list_length (vectors);
|
||||
|
||||
n_items += g_list_length (options->priv->selected_guides);
|
||||
}
|
||||
|
||||
if (n_items > 0)
|
||||
{
|
||||
GObject *reference;
|
||||
|
||||
reference = pika_align_options_get_reference (options, FALSE);
|
||||
|
||||
enable_ver_align = (reference != NULL &&
|
||||
(! PIKA_IS_GUIDE (reference) ||
|
||||
pika_guide_get_orientation (PIKA_GUIDE (reference)) == PIKA_ORIENTATION_VERTICAL));
|
||||
enable_hor_align = (reference != NULL &&
|
||||
(! PIKA_IS_GUIDE (reference) ||
|
||||
pika_guide_get_orientation (PIKA_GUIDE (reference)) == PIKA_ORIENTATION_HORIZONTAL));
|
||||
enable_ver_distr = enable_hor_distr = (n_items > 2);
|
||||
}
|
||||
for (gint i = 0; i < ALIGN_VER_N_BUTTONS; i++)
|
||||
gtk_widget_set_sensitive (options->priv->align_ver_button[i], enable_ver_align);
|
||||
for (gint i = 0; i < ALIGN_HOR_N_BUTTONS; i++)
|
||||
gtk_widget_set_sensitive (options->priv->align_hor_button[i], enable_hor_align);
|
||||
for (gint i = 0; i < DISTR_VER_N_BUTTONS; i++)
|
||||
gtk_widget_set_sensitive (options->priv->distr_ver_button[i], enable_ver_distr);
|
||||
for (gint i = 0; i < DISTR_HOR_N_BUTTONS; i++)
|
||||
gtk_widget_set_sensitive (options->priv->distr_hor_button[i], enable_hor_distr);
|
||||
|
||||
/* Update the guide picking widgets. */
|
||||
if (options->priv->selected_guides)
|
||||
{
|
||||
gchar *tmp_txt;
|
||||
|
||||
tmp_txt = g_strdup_printf (ngettext ("1 guide will be aligned or distributed",
|
||||
"%d guides will be aligned or distributed",
|
||||
g_list_length (options->priv->selected_guides)),
|
||||
g_list_length (options->priv->selected_guides));
|
||||
text = g_strdup_printf ("<i>%s</i>", tmp_txt);
|
||||
g_free (tmp_txt);
|
||||
gtk_widget_show (options->priv->selected_guides_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = NULL;
|
||||
gtk_widget_hide (options->priv->selected_guides_label);
|
||||
}
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (options->priv->selected_guides_label), text);
|
||||
g_free (text);
|
||||
|
||||
/* Update the reference widgets. */
|
||||
text = NULL;
|
||||
if (options->align_reference == PIKA_ALIGN_REFERENCE_PICK)
|
||||
{
|
||||
if (options->priv->reference)
|
||||
{
|
||||
gchar *tmp_txt;
|
||||
|
||||
if (PIKA_IS_LAYER (options->priv->reference))
|
||||
tmp_txt = g_strdup_printf (_("Reference layer: %s"),
|
||||
pika_object_get_name (options->priv->reference));
|
||||
else if (PIKA_IS_CHANNEL (options->priv->reference))
|
||||
tmp_txt = g_strdup_printf (_("Reference channel: %s"),
|
||||
pika_object_get_name (options->priv->reference));
|
||||
else if (PIKA_IS_VECTORS (options->priv->reference))
|
||||
tmp_txt = g_strdup_printf (_("Reference path: %s"),
|
||||
pika_object_get_name (options->priv->reference));
|
||||
else if (PIKA_IS_GUIDE (options->priv->reference))
|
||||
tmp_txt = g_strdup (_("Reference guide"));
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
text = g_strdup_printf ("<i>%s</i>", tmp_txt);
|
||||
g_free (tmp_txt);
|
||||
}
|
||||
gtk_widget_show (options->priv->reference_box);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (options->priv->reference_box);
|
||||
}
|
||||
gtk_label_set_markup (GTK_LABEL (options->priv->reference_label), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_guide_removed (PikaImage *image,
|
||||
PikaGuide *guide,
|
||||
PikaAlignOptions *options)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
if ((list = g_list_find (options->priv->selected_guides, guide)))
|
||||
options->priv->selected_guides = g_list_delete_link (options->priv->selected_guides, list);
|
||||
|
||||
if (G_OBJECT (guide) == options->priv->reference)
|
||||
pika_align_options_pick_reference (options, NULL);
|
||||
|
||||
pika_align_options_update_area (options);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_reference_removed (GObject *object,
|
||||
PikaAlignOptions *options)
|
||||
{
|
||||
if (G_OBJECT (object) == options->priv->reference)
|
||||
pika_align_options_pick_reference (options, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_options_pivot_changed (PikaPivotSelector *selector,
|
||||
PikaAlignOptions *options)
|
||||
{
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
|
||||
pika_pivot_selector_get_position (selector, &x, &y);
|
||||
g_object_set (options,
|
||||
"pivot-x", x,
|
||||
"pivot-y", y,
|
||||
NULL);
|
||||
}
|
||||
79
app/tools/pikaalignoptions.h
Normal file
79
app/tools/pikaalignoptions.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_ALIGN_OPTIONS_H__
|
||||
#define __PIKA_ALIGN_OPTIONS_H__
|
||||
|
||||
|
||||
#include "core/pikatooloptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_ALIGN_OPTIONS (pika_align_options_get_type ())
|
||||
#define PIKA_ALIGN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_ALIGN_OPTIONS, PikaAlignOptions))
|
||||
#define PIKA_ALIGN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_ALIGN_OPTIONS, PikaAlignOptionsClass))
|
||||
#define PIKA_IS_ALIGN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_ALIGN_OPTIONS))
|
||||
#define PIKA_IS_ALIGN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_ALIGN_OPTIONS))
|
||||
#define PIKA_ALIGN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_ALIGN_OPTIONS, PikaAlignOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaAlignOptions PikaAlignOptions;
|
||||
typedef struct _PikaAlignOptionsPrivate PikaAlignOptionsPrivate;
|
||||
typedef struct _PikaAlignOptionsClass PikaAlignOptionsClass;
|
||||
|
||||
struct _PikaAlignOptions
|
||||
{
|
||||
PikaToolOptions parent_instance;
|
||||
|
||||
PikaAlignReferenceType align_reference;
|
||||
|
||||
PikaAlignOptionsPrivate *priv;
|
||||
};
|
||||
|
||||
struct _PikaAlignOptionsClass
|
||||
{
|
||||
PikaToolOptionsClass parent_class;
|
||||
|
||||
void (* align_button_clicked) (PikaAlignOptions *options,
|
||||
PikaAlignmentType align_type);
|
||||
};
|
||||
|
||||
|
||||
GType pika_align_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_align_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
GList * pika_align_options_get_objects (PikaAlignOptions *options);
|
||||
void pika_align_options_get_pivot (PikaAlignOptions *options,
|
||||
gdouble *x,
|
||||
gdouble *y);
|
||||
|
||||
void pika_align_options_pick_reference (PikaAlignOptions *options,
|
||||
GObject *object);
|
||||
GObject * pika_align_options_get_reference (PikaAlignOptions *options,
|
||||
gboolean blink_if_none);
|
||||
gboolean pika_align_options_align_contents (PikaAlignOptions *options);
|
||||
|
||||
void pika_align_options_pick_guide (PikaAlignOptions *options,
|
||||
PikaGuide *guide,
|
||||
gboolean extend);
|
||||
|
||||
|
||||
#endif /* __PIKA_ALIGN_OPTIONS_H__ */
|
||||
859
app/tools/pikaaligntool.c
Normal file
859
app/tools/pikaaligntool.c
Normal file
@ -0,0 +1,859 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikadisplayconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikaguide.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-arrange.h"
|
||||
#include "core/pikaimage-pick-item.h"
|
||||
#include "core/pikaimage-undo.h"
|
||||
#include "core/pikalayer.h"
|
||||
#include "core/pikapickable.h"
|
||||
#include "core/pikapickable-auto-shrink.h"
|
||||
|
||||
#include "vectors/pikavectors.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "display/pikacanvasitem.h"
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikadisplayshell.h"
|
||||
#include "display/pikadisplayshell-appearance.h"
|
||||
|
||||
#include "pikaalignoptions.h"
|
||||
#include "pikaaligntool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
#define EPSILON 3 /* move distance after which we do a box-select */
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_align_tool_constructed (GObject *object);
|
||||
|
||||
static void pika_align_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display);
|
||||
static void pika_align_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_align_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_align_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static gboolean pika_align_tool_key_press (PikaTool *tool,
|
||||
GdkEventKey *kevent,
|
||||
PikaDisplay *display);
|
||||
static void pika_align_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
static void pika_align_tool_status_update (PikaTool *tool,
|
||||
PikaDisplay *display,
|
||||
GdkModifierType state,
|
||||
gboolean proximity);
|
||||
static void pika_align_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
const gchar * pika_align_tool_can_undo (PikaTool *tool,
|
||||
PikaDisplay *display);
|
||||
static gboolean pika_align_tool_undo (PikaTool *tool,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_align_tool_draw (PikaDrawTool *draw_tool);
|
||||
static void pika_align_tool_redraw (PikaAlignTool *align_tool);
|
||||
|
||||
static void pika_align_tool_align (PikaAlignTool *align_tool,
|
||||
PikaAlignmentType align_type);
|
||||
|
||||
static gint pika_align_tool_undo_idle (gpointer data);
|
||||
static void pika_align_tool_display_changed (PikaContext *context,
|
||||
PikaDisplay *display,
|
||||
PikaAlignTool *align_tool);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaAlignTool, pika_align_tool, PIKA_TYPE_DRAW_TOOL)
|
||||
|
||||
#define parent_class pika_align_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_align_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_ALIGN_TOOL,
|
||||
PIKA_TYPE_ALIGN_OPTIONS,
|
||||
pika_align_options_gui,
|
||||
0,
|
||||
"pika-align-tool",
|
||||
_("Align and Distribute"),
|
||||
_("Alignment Tool: Align or arrange layers and other objects"),
|
||||
N_("_Align and Distribute"), "Q",
|
||||
NULL, PIKA_HELP_TOOL_ALIGN,
|
||||
PIKA_ICON_TOOL_ALIGN,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_class_init (PikaAlignToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaDrawToolClass *draw_tool_class = PIKA_DRAW_TOOL_CLASS (klass);
|
||||
|
||||
object_class->constructed = pika_align_tool_constructed;
|
||||
|
||||
tool_class->control = pika_align_tool_control;
|
||||
tool_class->button_press = pika_align_tool_button_press;
|
||||
tool_class->button_release = pika_align_tool_button_release;
|
||||
tool_class->motion = pika_align_tool_motion;
|
||||
tool_class->key_press = pika_align_tool_key_press;
|
||||
tool_class->oper_update = pika_align_tool_oper_update;
|
||||
tool_class->cursor_update = pika_align_tool_cursor_update;
|
||||
tool_class->can_undo = pika_align_tool_can_undo;
|
||||
tool_class->undo = pika_align_tool_undo;
|
||||
|
||||
draw_tool_class->draw = pika_align_tool_draw;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_init (PikaAlignTool *align_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (align_tool);
|
||||
|
||||
pika_tool_control_set_snap_to (tool->control, FALSE);
|
||||
pika_tool_control_set_precision (tool->control,
|
||||
PIKA_CURSOR_PRECISION_PIXEL_BORDER);
|
||||
pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_MOVE);
|
||||
|
||||
align_tool->function = ALIGN_TOOL_REF_IDLE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_constructed (GObject *object)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (object);
|
||||
PikaAlignOptions *options;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
options = PIKA_ALIGN_TOOL_GET_OPTIONS (align_tool);
|
||||
|
||||
g_signal_connect_object (options, "align-button-clicked",
|
||||
G_CALLBACK (pika_align_tool_align),
|
||||
align_tool, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (options, "notify::align-reference",
|
||||
G_CALLBACK (pika_align_tool_redraw),
|
||||
align_tool, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (options, "notify::align-contents",
|
||||
G_CALLBACK (pika_align_tool_redraw),
|
||||
align_tool, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (pika_get_user_context (PIKA_CONTEXT (options)->pika),
|
||||
"display-changed",
|
||||
G_CALLBACK (pika_align_tool_display_changed),
|
||||
align_tool, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case PIKA_TOOL_ACTION_PAUSE:
|
||||
case PIKA_TOOL_ACTION_RESUME:
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_HALT:
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_COMMIT:
|
||||
break;
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->control (tool, action, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (tool);
|
||||
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
/* If the tool was being used in another image... reset it */
|
||||
if (display != tool->display)
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, display);
|
||||
|
||||
tool->display = display;
|
||||
|
||||
pika_tool_control_activate (tool->control);
|
||||
|
||||
align_tool->x2 = align_tool->x1 = coords->x;
|
||||
align_tool->y2 = align_tool->y1 = coords->y;
|
||||
|
||||
if (! pika_draw_tool_is_active (PIKA_DRAW_TOOL (tool)))
|
||||
pika_draw_tool_start (PIKA_DRAW_TOOL (tool), display);
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
}
|
||||
|
||||
/* some rather complex logic here. If the user clicks without modifiers,
|
||||
* then we start a new list, and use the first object in it as reference.
|
||||
* If the user clicks using Shift, or draws a rubber-band box, then
|
||||
* we add objects to the list, but do not specify which one should
|
||||
* be used as reference.
|
||||
*/
|
||||
static void
|
||||
pika_align_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (tool);
|
||||
PikaAlignOptions *options = PIKA_ALIGN_TOOL_GET_OPTIONS (tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
GdkModifierType extend_mask;
|
||||
|
||||
extend_mask = pika_get_extend_selection_mask ();
|
||||
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
pika_tool_control_halt (tool->control);
|
||||
|
||||
if (release_type == PIKA_BUTTON_RELEASE_CANCEL)
|
||||
{
|
||||
align_tool->x2 = align_tool->x1;
|
||||
align_tool->y2 = align_tool->y1;
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
return;
|
||||
}
|
||||
|
||||
if (state & GDK_MOD1_MASK)
|
||||
{
|
||||
PikaGuide *guide = NULL;
|
||||
|
||||
if (pika_display_shell_get_show_guides (shell))
|
||||
{
|
||||
gint snap_distance = display->config->snap_distance;
|
||||
|
||||
guide = pika_image_pick_guide (image,
|
||||
coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance));
|
||||
}
|
||||
|
||||
pika_align_options_pick_guide (options, guide, (gboolean) state & extend_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
GObject *object = NULL;
|
||||
|
||||
/* Check if a layer is fully included in the rubber-band rectangle.
|
||||
* Don't verify for too small rectangles.
|
||||
*/
|
||||
/* FIXME: look for vectors too */
|
||||
if (hypot (coords->x - align_tool->x1,
|
||||
coords->y - align_tool->y1) > EPSILON)
|
||||
{
|
||||
gint X0 = MIN (coords->x, align_tool->x1);
|
||||
gint X1 = MAX (coords->x, align_tool->x1);
|
||||
gint Y0 = MIN (coords->y, align_tool->y1);
|
||||
gint Y1 = MAX (coords->y, align_tool->y1);
|
||||
GList *all_layers;
|
||||
GList *list;
|
||||
|
||||
all_layers = pika_image_get_layer_list (image);
|
||||
|
||||
for (list = all_layers; list; list = g_list_next (list))
|
||||
{
|
||||
PikaLayer *layer = list->data;
|
||||
gint x0, y0, x1, y1;
|
||||
|
||||
if (! pika_item_get_visible (PIKA_ITEM (layer)))
|
||||
continue;
|
||||
|
||||
pika_item_get_offset (PIKA_ITEM (layer), &x0, &y0);
|
||||
x1 = x0 + pika_item_get_width (PIKA_ITEM (layer));
|
||||
y1 = y0 + pika_item_get_height (PIKA_ITEM (layer));
|
||||
|
||||
if (x0 < X0 || y0 < Y0 || x1 > X1 || y1 > Y1)
|
||||
continue;
|
||||
|
||||
object = G_OBJECT (layer);
|
||||
break;
|
||||
}
|
||||
|
||||
g_list_free (all_layers);
|
||||
}
|
||||
|
||||
if (object == NULL)
|
||||
{
|
||||
PikaVectors *vectors;
|
||||
PikaGuide *guide;
|
||||
PikaLayer *layer;
|
||||
GObject *previously_picked;
|
||||
gint snap_distance = display->config->snap_distance;
|
||||
|
||||
previously_picked = pika_align_options_get_reference (options, FALSE);
|
||||
|
||||
|
||||
if ((vectors = pika_image_pick_vectors (image,
|
||||
coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance))))
|
||||
{
|
||||
object = G_OBJECT (vectors);
|
||||
}
|
||||
else if (pika_display_shell_get_show_guides (shell) &&
|
||||
(guide = pika_image_pick_guide (image,
|
||||
coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance))))
|
||||
{
|
||||
object = G_OBJECT (guide);
|
||||
}
|
||||
else if ((layer = pika_image_pick_layer (image, coords->x, coords->y,
|
||||
previously_picked && PIKA_IS_LAYER (previously_picked)? PIKA_LAYER (previously_picked) : NULL)))
|
||||
{
|
||||
object = G_OBJECT (layer);
|
||||
}
|
||||
}
|
||||
|
||||
if (object)
|
||||
pika_align_options_pick_reference (options, object);
|
||||
}
|
||||
|
||||
align_tool->x2 = align_tool->x1;
|
||||
align_tool->y2 = align_tool->y1;
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (tool);
|
||||
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
align_tool->x2 = coords->x;
|
||||
align_tool->y2 = coords->y;
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_align_tool_key_press (PikaTool *tool,
|
||||
GdkEventKey *kevent,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
if (display == tool->display)
|
||||
{
|
||||
switch (kevent->keyval)
|
||||
{
|
||||
case GDK_KEY_Escape:
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, display);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (tool);
|
||||
PikaAlignOptions *options = PIKA_ALIGN_TOOL_GET_OPTIONS (align_tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
gint snap_distance = display->config->snap_distance;
|
||||
|
||||
state &= pika_get_all_modifiers_mask ();
|
||||
|
||||
align_tool->function = ALIGN_TOOL_NO_ACTION;
|
||||
|
||||
if (pika_image_pick_vectors (image,
|
||||
coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance)))
|
||||
{
|
||||
if (options->align_reference == PIKA_ALIGN_REFERENCE_PICK)
|
||||
align_tool->function = ALIGN_TOOL_REF_PICK_PATH;
|
||||
}
|
||||
else if (pika_display_shell_get_show_guides (shell) &&
|
||||
pika_image_pick_guide (image,
|
||||
coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance)))
|
||||
{
|
||||
if (state == (pika_get_extend_selection_mask () | GDK_MOD1_MASK))
|
||||
align_tool->function = ALIGN_TOOL_ALIGN_ADD_GUIDE;
|
||||
else if (state == GDK_MOD1_MASK)
|
||||
align_tool->function = ALIGN_TOOL_ALIGN_PICK_GUIDE;
|
||||
else if (options->align_reference == PIKA_ALIGN_REFERENCE_PICK)
|
||||
align_tool->function = ALIGN_TOOL_REF_PICK_GUIDE;
|
||||
}
|
||||
else if (pika_image_pick_layer_by_bounds (image, coords->x, coords->y))
|
||||
{
|
||||
if (options->align_reference == PIKA_ALIGN_REFERENCE_PICK)
|
||||
align_tool->function = ALIGN_TOOL_REF_PICK_LAYER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state & GDK_MOD1_MASK)
|
||||
align_tool->function = ALIGN_TOOL_ALIGN_IDLE;
|
||||
else if (options->align_reference == PIKA_ALIGN_REFERENCE_PICK)
|
||||
align_tool->function = ALIGN_TOOL_REF_IDLE;
|
||||
}
|
||||
|
||||
pika_align_tool_status_update (tool, display, state, proximity);
|
||||
|
||||
if (! pika_draw_tool_is_active (PIKA_DRAW_TOOL (tool)))
|
||||
pika_draw_tool_start (PIKA_DRAW_TOOL (tool), display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (tool);
|
||||
PikaToolCursorType tool_cursor = PIKA_TOOL_CURSOR_NONE;
|
||||
PikaCursorModifier modifier = PIKA_CURSOR_MODIFIER_NONE;
|
||||
|
||||
switch (align_tool->function)
|
||||
{
|
||||
case ALIGN_TOOL_REF_IDLE:
|
||||
case ALIGN_TOOL_ALIGN_IDLE:
|
||||
tool_cursor = PIKA_TOOL_CURSOR_RECT_SELECT;
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_REF_PICK_LAYER:
|
||||
tool_cursor = PIKA_TOOL_CURSOR_HAND;
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_ALIGN_ADD_GUIDE:
|
||||
modifier = PIKA_CURSOR_MODIFIER_PLUS;
|
||||
case ALIGN_TOOL_REF_PICK_GUIDE:
|
||||
case ALIGN_TOOL_ALIGN_PICK_GUIDE:
|
||||
tool_cursor = PIKA_TOOL_CURSOR_MOVE;
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_REF_PICK_PATH:
|
||||
tool_cursor = PIKA_TOOL_CURSOR_PATHS;
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_REF_DRAG_BOX:
|
||||
case ALIGN_TOOL_NO_ACTION:
|
||||
break;
|
||||
}
|
||||
|
||||
pika_tool_control_set_cursor (tool->control, PIKA_CURSOR_MOUSE);
|
||||
pika_tool_control_set_tool_cursor (tool->control, tool_cursor);
|
||||
pika_tool_control_set_cursor_modifier (tool->control, modifier);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pika_align_tool_can_undo (PikaTool *tool,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
return _("Arrange Objects");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_align_tool_undo (PikaTool *tool,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
g_idle_add ((GSourceFunc) pika_align_tool_undo_idle, (gpointer) tool);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_status_update (PikaTool *tool,
|
||||
PikaDisplay *display,
|
||||
GdkModifierType state,
|
||||
gboolean proximity)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (tool);
|
||||
gchar *status = NULL;
|
||||
GdkModifierType extend_mask;
|
||||
|
||||
extend_mask = pika_get_extend_selection_mask ();
|
||||
|
||||
pika_tool_pop_status (tool, display);
|
||||
|
||||
if (proximity)
|
||||
{
|
||||
switch (align_tool->function)
|
||||
{
|
||||
case ALIGN_TOOL_REF_IDLE:
|
||||
status = g_strdup (_("Click on a layer, path or guide, "
|
||||
"or Click-Drag to pick a reference"));
|
||||
break;
|
||||
case ALIGN_TOOL_REF_PICK_LAYER:
|
||||
status = g_strdup (_("Click to pick this layer as reference"));
|
||||
break;
|
||||
case ALIGN_TOOL_REF_PICK_GUIDE:
|
||||
status = pika_suggest_modifiers (_("Click to pick this guide as reference"),
|
||||
GDK_MOD1_MASK & ~state,
|
||||
NULL, NULL, NULL);
|
||||
break;
|
||||
case ALIGN_TOOL_REF_PICK_PATH:
|
||||
status = g_strdup (_("Click to pick this path as reference"));
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_REF_DRAG_BOX:
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_ALIGN_IDLE:
|
||||
status = g_strdup (_("Click on a guide to add it to objects to align, "
|
||||
"click anywhere else to unselect all guides"));
|
||||
break;
|
||||
case ALIGN_TOOL_ALIGN_PICK_GUIDE:
|
||||
status = pika_suggest_modifiers (_("Click to select this guide for alignment"),
|
||||
extend_mask & ~state,
|
||||
NULL, NULL, NULL);
|
||||
break;
|
||||
case ALIGN_TOOL_ALIGN_ADD_GUIDE:
|
||||
status = g_strdup (_("Click to add this guide to the list of objects to align"));
|
||||
break;
|
||||
|
||||
case ALIGN_TOOL_NO_ACTION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (status)
|
||||
{
|
||||
pika_tool_push_status (tool, display, "%s", status);
|
||||
g_free (status);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_draw (PikaDrawTool *draw_tool)
|
||||
{
|
||||
PikaAlignTool *align_tool = PIKA_ALIGN_TOOL (draw_tool);
|
||||
PikaAlignOptions *options = PIKA_ALIGN_TOOL_GET_OPTIONS (align_tool);
|
||||
GObject *reference;
|
||||
GList *objects;
|
||||
GList *iter;
|
||||
gint x, y, w, h;
|
||||
|
||||
/* draw rubber-band rectangle */
|
||||
x = MIN (align_tool->x2, align_tool->x1);
|
||||
y = MIN (align_tool->y2, align_tool->y1);
|
||||
w = MAX (align_tool->x2, align_tool->x1) - x;
|
||||
h = MAX (align_tool->y2, align_tool->y1) - y;
|
||||
|
||||
if (w != 0 && h != 0)
|
||||
pika_draw_tool_add_rectangle (draw_tool, FALSE, x, y, w, h);
|
||||
|
||||
/* Draw handles on the reference object. */
|
||||
reference = pika_align_options_get_reference (options, FALSE);
|
||||
if (PIKA_IS_ITEM (reference))
|
||||
{
|
||||
PikaItem *item = PIKA_ITEM (reference);
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_bounds (item, &x, &y, &w, &h);
|
||||
|
||||
pika_item_get_offset (item, &off_x, &off_y);
|
||||
x += off_x;
|
||||
y += off_y;
|
||||
|
||||
if (pika_align_options_align_contents (options))
|
||||
{
|
||||
gint shrunk_x;
|
||||
gint shrunk_y;
|
||||
|
||||
if (pika_pickable_auto_shrink (PIKA_PICKABLE (reference),
|
||||
0, 0,
|
||||
pika_item_get_width (PIKA_ITEM (reference)),
|
||||
pika_item_get_height (PIKA_ITEM (reference)),
|
||||
&shrunk_x, &shrunk_y, &w, &h) == PIKA_AUTO_SHRINK_SHRINK)
|
||||
{
|
||||
x += shrunk_x;
|
||||
y += shrunk_y;
|
||||
}
|
||||
}
|
||||
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
x, y,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_NORTH_WEST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
x + w, y,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_NORTH_EAST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
x, y + h,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_SOUTH_WEST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
x + w, y + h,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_SOUTH_EAST);
|
||||
}
|
||||
else if (PIKA_IS_GUIDE (reference))
|
||||
{
|
||||
PikaGuide *guide = PIKA_GUIDE (reference);
|
||||
PikaImage *image = pika_display_get_image (draw_tool->display);
|
||||
gint x, y;
|
||||
gint w, h;
|
||||
|
||||
switch (pika_guide_get_orientation (guide))
|
||||
{
|
||||
case PIKA_ORIENTATION_VERTICAL:
|
||||
x = pika_guide_get_position (guide);
|
||||
h = pika_image_get_height (image);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
x, h,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_SOUTH);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
x, 0,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_NORTH);
|
||||
break;
|
||||
|
||||
case PIKA_ORIENTATION_HORIZONTAL:
|
||||
y = pika_guide_get_position (guide);
|
||||
w = pika_image_get_width (image);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
w, y,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_EAST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
0, y,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_WEST);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (PIKA_IS_IMAGE (reference))
|
||||
{
|
||||
PikaImage *image = PIKA_IMAGE (reference);
|
||||
gint width = pika_image_get_width (image);
|
||||
gint height = pika_image_get_height (image);
|
||||
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
0, 0,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_NORTH_WEST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
width, 0,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_NORTH_EAST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
0, height,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_SOUTH_WEST);
|
||||
pika_draw_tool_add_handle (draw_tool, PIKA_HANDLE_FILLED_SQUARE,
|
||||
width, height,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_TOOL_HANDLE_SIZE_SMALL,
|
||||
PIKA_HANDLE_ANCHOR_SOUTH_EAST);
|
||||
}
|
||||
|
||||
/* Highlight picked guides, similarly to how they are highlighted in Move
|
||||
* tool.
|
||||
*/
|
||||
objects = pika_align_options_get_objects (options);
|
||||
for (iter = objects; iter; iter = iter->next)
|
||||
{
|
||||
if (PIKA_IS_GUIDE (iter->data))
|
||||
{
|
||||
PikaGuide *guide = iter->data;
|
||||
PikaCanvasItem *item;
|
||||
PikaGuideStyle style;
|
||||
|
||||
style = pika_guide_get_style (guide);
|
||||
|
||||
item = pika_draw_tool_add_guide (draw_tool,
|
||||
pika_guide_get_orientation (guide),
|
||||
pika_guide_get_position (guide),
|
||||
style);
|
||||
pika_canvas_item_set_highlight (item, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_redraw (PikaAlignTool *align_tool)
|
||||
{
|
||||
PikaDrawTool *draw_tool = PIKA_DRAW_TOOL (align_tool);
|
||||
|
||||
pika_draw_tool_pause (draw_tool);
|
||||
|
||||
if (! pika_draw_tool_is_active (draw_tool) && draw_tool->display)
|
||||
pika_draw_tool_start (draw_tool, draw_tool->display);
|
||||
|
||||
pika_draw_tool_resume (draw_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_align (PikaAlignTool *align_tool,
|
||||
PikaAlignmentType align_type)
|
||||
{
|
||||
PikaAlignOptions *options = PIKA_ALIGN_TOOL_GET_OPTIONS (align_tool);
|
||||
PikaImage *image;
|
||||
GObject *reference_object = NULL;
|
||||
GList *objects;
|
||||
GList *list;
|
||||
gdouble align_x = 0.0;
|
||||
gdouble align_y = 0.0;
|
||||
|
||||
/* if nothing is selected, just return */
|
||||
objects = pika_align_options_get_objects (options);
|
||||
if (! objects)
|
||||
return;
|
||||
|
||||
image = pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika));
|
||||
list = objects;
|
||||
|
||||
if (align_type < PIKA_ARRANGE_HFILL)
|
||||
{
|
||||
reference_object = pika_align_options_get_reference (options, TRUE);
|
||||
if (! reference_object)
|
||||
return;
|
||||
}
|
||||
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (align_tool));
|
||||
|
||||
pika_align_options_get_pivot (options, &align_x, &align_y);
|
||||
pika_image_arrange_objects (image, list,
|
||||
align_x, align_y,
|
||||
reference_object,
|
||||
align_type,
|
||||
pika_align_options_align_contents (options));
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (align_tool));
|
||||
|
||||
pika_image_flush (image);
|
||||
g_list_free (objects);
|
||||
}
|
||||
|
||||
static gint
|
||||
pika_align_tool_undo_idle (gpointer data)
|
||||
{
|
||||
PikaDrawTool *draw_tool = PIKA_DRAW_TOOL (data);
|
||||
PikaDisplay *display = draw_tool->display;
|
||||
|
||||
/* This makes sure that we properly undraw then redraw the various handles and
|
||||
* highlighted guides after undoing.
|
||||
*/
|
||||
pika_draw_tool_stop (draw_tool);
|
||||
pika_draw_tool_start (draw_tool, display);
|
||||
|
||||
return FALSE; /* remove idle */
|
||||
}
|
||||
|
||||
static void
|
||||
pika_align_tool_display_changed (PikaContext *context,
|
||||
PikaDisplay *display,
|
||||
PikaAlignTool *align_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (align_tool);
|
||||
PikaDrawTool *draw_tool = PIKA_DRAW_TOOL (align_tool);
|
||||
|
||||
pika_draw_tool_pause (draw_tool);
|
||||
|
||||
if (display != tool->display)
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, display);
|
||||
|
||||
tool->display = display;
|
||||
|
||||
if (! pika_draw_tool_is_active (draw_tool) && display)
|
||||
pika_draw_tool_start (draw_tool, display);
|
||||
|
||||
pika_draw_tool_resume (draw_tool);
|
||||
}
|
||||
83
app/tools/pikaaligntool.h
Normal file
83
app/tools/pikaaligntool.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_ALIGN_TOOL_H__
|
||||
#define __PIKA_ALIGN_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
/* tool function/operation/state/mode */
|
||||
typedef enum
|
||||
{
|
||||
ALIGN_TOOL_NO_ACTION,
|
||||
|
||||
ALIGN_TOOL_REF_IDLE,
|
||||
ALIGN_TOOL_REF_PICK_LAYER,
|
||||
ALIGN_TOOL_REF_PICK_GUIDE,
|
||||
ALIGN_TOOL_REF_PICK_PATH,
|
||||
ALIGN_TOOL_REF_DRAG_BOX,
|
||||
|
||||
ALIGN_TOOL_ALIGN_IDLE,
|
||||
ALIGN_TOOL_ALIGN_PICK_GUIDE,
|
||||
ALIGN_TOOL_ALIGN_ADD_GUIDE,
|
||||
} PikaAlignToolFunction;
|
||||
|
||||
|
||||
#define PIKA_TYPE_ALIGN_TOOL (pika_align_tool_get_type ())
|
||||
#define PIKA_ALIGN_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_ALIGN_TOOL, PikaAlignTool))
|
||||
#define PIKA_ALIGN_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_ALIGN_TOOL, PikaAlignToolClass))
|
||||
#define PIKA_IS_ALIGN_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_ALIGN_TOOL))
|
||||
#define PIKA_IS_ALIGN_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_ALIGN_TOOL))
|
||||
#define PIKA_ALIGN_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_ALIGN_TOOL, PikaAlignToolClass))
|
||||
|
||||
#define PIKA_ALIGN_TOOL_GET_OPTIONS(t) (PIKA_ALIGN_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaAlignTool PikaAlignTool;
|
||||
typedef struct _PikaAlignToolClass PikaAlignToolClass;
|
||||
|
||||
struct _PikaAlignTool
|
||||
{
|
||||
PikaDrawTool parent_instance;
|
||||
|
||||
PikaAlignToolFunction function;
|
||||
GList *selected_objects;
|
||||
|
||||
gint x1, y1, x2, y2; /* rubber-band rectangle */
|
||||
|
||||
gboolean set_reference;
|
||||
};
|
||||
|
||||
struct _PikaAlignToolClass
|
||||
{
|
||||
PikaDrawToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_align_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_align_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_ALIGN_TOOL_H__ */
|
||||
323
app/tools/pikabrightnesscontrasttool.c
Normal file
323
app/tools/pikabrightnesscontrasttool.c
Normal file
@ -0,0 +1,323 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "operations/pikabrightnesscontrastconfig.h"
|
||||
|
||||
#include "core/pikadrawable.h"
|
||||
#include "core/pikaerror.h"
|
||||
#include "core/pikaimage.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-constructors.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
|
||||
#include "pikabrightnesscontrasttool.h"
|
||||
#include "pikafilteroptions.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
#define SLIDER_WIDTH 200
|
||||
|
||||
|
||||
static gboolean pika_brightness_contrast_tool_initialize (PikaTool *tool,
|
||||
PikaDisplay *display,
|
||||
GError **error);
|
||||
static void pika_brightness_contrast_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_brightness_contrast_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_brightness_contrast_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
|
||||
static gchar *
|
||||
pika_brightness_contrast_tool_get_operation (PikaFilterTool *filter_tool,
|
||||
gchar **description);
|
||||
static void pika_brightness_contrast_tool_dialog (PikaFilterTool *filter_tool);
|
||||
|
||||
static void brightness_contrast_to_levels_callback (GtkWidget *widget,
|
||||
PikaFilterTool *filter_tool);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaBrightnessContrastTool, pika_brightness_contrast_tool,
|
||||
PIKA_TYPE_FILTER_TOOL)
|
||||
|
||||
#define parent_class pika_brightness_contrast_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_brightness_contrast_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL,
|
||||
PIKA_TYPE_FILTER_OPTIONS, NULL,
|
||||
0,
|
||||
"pika-brightness-contrast-tool",
|
||||
_("Brightness-Contrast"),
|
||||
_("Adjust brightness and contrast"),
|
||||
N_("B_rightness-Contrast..."), NULL,
|
||||
NULL, PIKA_HELP_TOOL_BRIGHTNESS_CONTRAST,
|
||||
PIKA_ICON_TOOL_BRIGHTNESS_CONTRAST,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brightness_contrast_tool_class_init (PikaBrightnessContrastToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaFilterToolClass *filter_tool_class = PIKA_FILTER_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->initialize = pika_brightness_contrast_tool_initialize;
|
||||
tool_class->button_press = pika_brightness_contrast_tool_button_press;
|
||||
tool_class->button_release = pika_brightness_contrast_tool_button_release;
|
||||
tool_class->motion = pika_brightness_contrast_tool_motion;
|
||||
|
||||
filter_tool_class->get_operation = pika_brightness_contrast_tool_get_operation;
|
||||
filter_tool_class->dialog = pika_brightness_contrast_tool_dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brightness_contrast_tool_init (PikaBrightnessContrastTool *bc_tool)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_brightness_contrast_tool_initialize (PikaTool *tool,
|
||||
PikaDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
GList *drawables;
|
||||
|
||||
if (! PIKA_TOOL_CLASS (parent_class)->initialize (tool, display, error))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
drawables = pika_image_get_selected_drawables (image);
|
||||
/* Single drawable selection has been checked in parent initialize(). */
|
||||
g_return_val_if_fail (g_list_length (drawables) == 1, FALSE);
|
||||
|
||||
if (pika_drawable_get_component_type (drawables->data) == PIKA_COMPONENT_TYPE_U8)
|
||||
{
|
||||
pika_prop_widget_set_factor (bc_tool->brightness_scale,
|
||||
127.0, 1.0, 8.0, 0);
|
||||
pika_prop_widget_set_factor (bc_tool->contrast_scale,
|
||||
127.0, 1.0, 8.0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_prop_widget_set_factor (bc_tool->brightness_scale,
|
||||
0.5, 0.01, 0.1, 3);
|
||||
pika_prop_widget_set_factor (bc_tool->contrast_scale,
|
||||
0.5, 0.01, 0.1, 3);
|
||||
}
|
||||
|
||||
g_list_free (drawables);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
pika_brightness_contrast_tool_get_operation (PikaFilterTool *filter_tool,
|
||||
gchar **description)
|
||||
{
|
||||
*description = g_strdup (_("Adjust Brightness and Contrast"));
|
||||
|
||||
return g_strdup ("pika:brightness-contrast");
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brightness_contrast_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool);
|
||||
|
||||
bc_tool->dragging = ! pika_filter_tool_on_guide (PIKA_FILTER_TOOL (tool),
|
||||
coords, display);
|
||||
|
||||
if (! bc_tool->dragging)
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
||||
press_type, display);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble brightness;
|
||||
gdouble contrast;
|
||||
|
||||
g_object_get (PIKA_FILTER_TOOL (tool)->config,
|
||||
"brightness", &brightness,
|
||||
"contrast", &contrast,
|
||||
NULL);
|
||||
|
||||
bc_tool->x = coords->x - contrast * 127.0;
|
||||
bc_tool->y = coords->y + brightness * 127.0;
|
||||
bc_tool->dx = contrast * 127.0;
|
||||
bc_tool->dy = - brightness * 127.0;
|
||||
|
||||
tool->display = display;
|
||||
|
||||
pika_tool_control_activate (tool->control);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brightness_contrast_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool);
|
||||
|
||||
if (! bc_tool->dragging)
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state,
|
||||
release_type, display);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_tool_control_halt (tool->control);
|
||||
|
||||
bc_tool->dragging = FALSE;
|
||||
|
||||
if (bc_tool->dx == 0 && bc_tool->dy == 0)
|
||||
return;
|
||||
|
||||
if (release_type == PIKA_BUTTON_RELEASE_CANCEL)
|
||||
pika_config_reset (PIKA_CONFIG (PIKA_FILTER_TOOL (tool)->config));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brightness_contrast_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (tool);
|
||||
|
||||
if (! bc_tool->dragging)
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->motion (tool, coords, time, state,
|
||||
display);
|
||||
}
|
||||
else
|
||||
{
|
||||
bc_tool->dx = (coords->x - bc_tool->x);
|
||||
bc_tool->dy = - (coords->y - bc_tool->y);
|
||||
|
||||
g_object_set (PIKA_FILTER_TOOL (tool)->config,
|
||||
"brightness", CLAMP (bc_tool->dy, -127.0, 127.0) / 127.0,
|
||||
"contrast", CLAMP (bc_tool->dx, -127.0, 127.0) / 127.0,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************/
|
||||
/* Brightness Contrast dialog */
|
||||
/********************************/
|
||||
|
||||
static void
|
||||
pika_brightness_contrast_tool_dialog (PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaBrightnessContrastTool *bc_tool = PIKA_BRIGHTNESS_CONTRAST_TOOL (filter_tool);
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *button;
|
||||
|
||||
main_vbox = pika_filter_tool_dialog_get_vbox (filter_tool);
|
||||
|
||||
/* Create the brightness scale widget */
|
||||
scale = pika_prop_spin_scale_new (filter_tool->config, "brightness",
|
||||
0.01, 0.1, 3);
|
||||
pika_spin_scale_set_label (PIKA_SPIN_SCALE (scale), _("_Brightness"));
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
bc_tool->brightness_scale = scale;
|
||||
|
||||
/* Create the contrast scale widget */
|
||||
scale = pika_prop_spin_scale_new (filter_tool->config, "contrast",
|
||||
0.01, 0.1, 3);
|
||||
pika_spin_scale_set_label (PIKA_SPIN_SCALE (scale), _("_Contrast"));
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
bc_tool->contrast_scale = scale;
|
||||
|
||||
button = pika_icon_button_new (PIKA_ICON_TOOL_LEVELS,
|
||||
_("Edit these Settings as Levels"));
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_show (button);
|
||||
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (brightness_contrast_to_levels_callback),
|
||||
filter_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
brightness_contrast_to_levels_callback (GtkWidget *widget,
|
||||
PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaLevelsConfig *levels;
|
||||
|
||||
levels = pika_brightness_contrast_config_to_levels_config (PIKA_BRIGHTNESS_CONTRAST_CONFIG (filter_tool->config));
|
||||
|
||||
pika_filter_tool_edit_as (filter_tool,
|
||||
"pika-levels-tool",
|
||||
PIKA_CONFIG (levels));
|
||||
|
||||
g_object_unref (levels);
|
||||
}
|
||||
65
app/tools/pikabrightnesscontrasttool.h
Normal file
65
app/tools/pikabrightnesscontrasttool.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_BRIGHTNESS_CONTRAST_TOOL_H__
|
||||
#define __PIKA_BRIGHTNESS_CONTRAST_TOOL_H__
|
||||
|
||||
|
||||
#include "pikafiltertool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL (pika_brightness_contrast_tool_get_type ())
|
||||
#define PIKA_BRIGHTNESS_CONTRAST_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL, PikaBrightnessContrastTool))
|
||||
#define PIKA_BRIGHTNESS_CONTRAST_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL, PikaBrightnessContrastToolClass))
|
||||
#define PIKA_IS_BRIGHTNESS_CONTRAST_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL))
|
||||
#define PIKA_IS_BRIGHTNESS_CONTRAST_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL))
|
||||
#define PIKA_BRIGHTNESS_CONTRAST_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_BRIGHTNESS_CONTRAST_TOOL, PikaBrightnessContrastToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaBrightnessContrastTool PikaBrightnessContrastTool;
|
||||
typedef struct _PikaBrightnessContrastToolClass PikaBrightnessContrastToolClass;
|
||||
|
||||
struct _PikaBrightnessContrastTool
|
||||
{
|
||||
PikaFilterTool parent_instance;
|
||||
|
||||
gboolean dragging;
|
||||
gdouble x, y;
|
||||
gdouble dx, dy;
|
||||
|
||||
/* dialog */
|
||||
GtkWidget *brightness_scale;
|
||||
GtkWidget *contrast_scale;
|
||||
};
|
||||
|
||||
struct _PikaBrightnessContrastToolClass
|
||||
{
|
||||
PikaFilterToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_brightness_contrast_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_brightness_contrast_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_BRIGHTNESS_CONTRAST_TOOL_H__ */
|
||||
455
app/tools/pikabrushtool.c
Normal file
455
app/tools/pikabrushtool.c
Normal file
@ -0,0 +1,455 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikadisplayconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikabezierdesc.h"
|
||||
#include "core/pikabrush.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "paint/pikabrushcore.h"
|
||||
#include "paint/pikapaintoptions.h"
|
||||
|
||||
#include "display/pikacanvashandle.h"
|
||||
#include "display/pikacanvaspath.h"
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikadisplayshell.h"
|
||||
|
||||
#include "pikabrushtool.h"
|
||||
#include "pikapainttool-paint.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
|
||||
static void pika_brush_tool_constructed (GObject *object);
|
||||
|
||||
static void pika_brush_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
static void pika_brush_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_brush_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
static void pika_brush_tool_paint_start (PikaPaintTool *paint_tool);
|
||||
static void pika_brush_tool_paint_end (PikaPaintTool *paint_tool);
|
||||
static void pika_brush_tool_paint_flush (PikaPaintTool *paint_tool);
|
||||
static PikaCanvasItem *
|
||||
pika_brush_tool_get_outline (PikaPaintTool *paint_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
static void pika_brush_tool_brush_changed (PikaContext *context,
|
||||
PikaBrush *brush,
|
||||
PikaBrushTool *brush_tool);
|
||||
static void pika_brush_tool_set_brush (PikaBrushCore *brush_core,
|
||||
PikaBrush *brush,
|
||||
PikaBrushTool *brush_tool);
|
||||
|
||||
static const PikaBezierDesc *
|
||||
pika_brush_tool_get_boundary (PikaBrushTool *brush_tool,
|
||||
gint *width,
|
||||
gint *height);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaBrushTool, pika_brush_tool, PIKA_TYPE_PAINT_TOOL)
|
||||
|
||||
#define parent_class pika_brush_tool_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_brush_tool_class_init (PikaBrushToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaPaintToolClass *paint_tool_class = PIKA_PAINT_TOOL_CLASS (klass);
|
||||
|
||||
object_class->constructed = pika_brush_tool_constructed;
|
||||
|
||||
tool_class->oper_update = pika_brush_tool_oper_update;
|
||||
tool_class->cursor_update = pika_brush_tool_cursor_update;
|
||||
tool_class->options_notify = pika_brush_tool_options_notify;
|
||||
|
||||
paint_tool_class->paint_start = pika_brush_tool_paint_start;
|
||||
paint_tool_class->paint_end = pika_brush_tool_paint_end;
|
||||
paint_tool_class->paint_flush = pika_brush_tool_paint_flush;
|
||||
paint_tool_class->get_outline = pika_brush_tool_get_outline;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_init (PikaBrushTool *brush_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (brush_tool);
|
||||
|
||||
pika_tool_control_set_action_pixel_size (tool->control,
|
||||
"tools-paintbrush-pixel-size-set");
|
||||
pika_tool_control_set_action_size (tool->control,
|
||||
"tools-paintbrush-size-set");
|
||||
pika_tool_control_set_action_aspect (tool->control,
|
||||
"tools-paintbrush-aspect-ratio-set");
|
||||
pika_tool_control_set_action_angle (tool->control,
|
||||
"tools-paintbrush-angle-set");
|
||||
pika_tool_control_set_action_spacing (tool->control,
|
||||
"tools-paintbrush-spacing-set");
|
||||
pika_tool_control_set_action_hardness (tool->control,
|
||||
"tools-paintbrush-hardness-set");
|
||||
pika_tool_control_set_action_force (tool->control,
|
||||
"tools-paintbrush-force-set");
|
||||
pika_tool_control_set_action_object_1 (tool->control,
|
||||
"context-brush-select-set");
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_constructed (GObject *object)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (object);
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
pika_assert (PIKA_IS_BRUSH_CORE (paint_tool->core));
|
||||
|
||||
g_signal_connect_object (pika_tool_get_options (tool), "brush-changed",
|
||||
G_CALLBACK (pika_brush_tool_brush_changed),
|
||||
paint_tool, 0);
|
||||
|
||||
g_signal_connect_object (paint_tool->core, "set-brush",
|
||||
G_CALLBACK (pika_brush_tool_set_brush),
|
||||
paint_tool, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaPaintOptions *paint_options = PIKA_PAINT_TOOL_GET_OPTIONS (tool);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
|
||||
proximity, display);
|
||||
|
||||
if (! pika_color_tool_is_enabled (PIKA_COLOR_TOOL (tool)) &&
|
||||
image && proximity)
|
||||
{
|
||||
PikaContext *context = PIKA_CONTEXT (paint_options);
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
|
||||
pika_brush_core_set_brush (brush_core,
|
||||
pika_context_get_brush (context));
|
||||
|
||||
pika_brush_core_set_dynamics (brush_core,
|
||||
pika_context_get_dynamics (context));
|
||||
|
||||
if (PIKA_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush)
|
||||
{
|
||||
pika_brush_core_eval_transform_dynamics (brush_core,
|
||||
image,
|
||||
paint_options,
|
||||
coords);
|
||||
}
|
||||
}
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaBrushTool *brush_tool = PIKA_BRUSH_TOOL (tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (PIKA_PAINT_TOOL (brush_tool)->core);
|
||||
|
||||
if (! pika_color_tool_is_enabled (PIKA_COLOR_TOOL (tool)))
|
||||
{
|
||||
if (! brush_core->main_brush || ! brush_core->dynamics)
|
||||
{
|
||||
pika_tool_set_cursor (tool, display,
|
||||
pika_tool_control_get_cursor (tool->control),
|
||||
pika_tool_control_get_tool_cursor (tool->control),
|
||||
PIKA_CURSOR_MODIFIER_BAD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec)
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
|
||||
|
||||
if (! strcmp (pspec->name, "brush-size") ||
|
||||
! strcmp (pspec->name, "brush-angle") ||
|
||||
! strcmp (pspec->name, "brush-aspect-ratio"))
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
|
||||
g_signal_emit_by_name (brush_core, "set-brush",
|
||||
brush_core->main_brush);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_paint_start (PikaPaintTool *paint_tool)
|
||||
{
|
||||
PikaBrushTool *brush_tool = PIKA_BRUSH_TOOL (paint_tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
const PikaBezierDesc *boundary;
|
||||
|
||||
if (PIKA_PAINT_TOOL_CLASS (parent_class)->paint_start)
|
||||
PIKA_PAINT_TOOL_CLASS (parent_class)->paint_start (paint_tool);
|
||||
|
||||
boundary = pika_brush_tool_get_boundary (brush_tool,
|
||||
&brush_tool->boundary_width,
|
||||
&brush_tool->boundary_height);
|
||||
|
||||
if (boundary)
|
||||
brush_tool->boundary = pika_bezier_desc_copy (boundary);
|
||||
|
||||
brush_tool->boundary_scale = brush_core->scale;
|
||||
brush_tool->boundary_aspect_ratio = brush_core->aspect_ratio;
|
||||
brush_tool->boundary_angle = brush_core->angle;
|
||||
brush_tool->boundary_reflect = brush_core->reflect;
|
||||
brush_tool->boundary_hardness = brush_core->hardness;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_paint_end (PikaPaintTool *paint_tool)
|
||||
{
|
||||
PikaBrushTool *brush_tool = PIKA_BRUSH_TOOL (paint_tool);
|
||||
|
||||
g_clear_pointer (&brush_tool->boundary, pika_bezier_desc_free);
|
||||
|
||||
if (PIKA_PAINT_TOOL_CLASS (parent_class)->paint_end)
|
||||
PIKA_PAINT_TOOL_CLASS (parent_class)->paint_end (paint_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_paint_flush (PikaPaintTool *paint_tool)
|
||||
{
|
||||
PikaBrushTool *brush_tool = PIKA_BRUSH_TOOL (paint_tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
const PikaBezierDesc *boundary;
|
||||
|
||||
if (PIKA_PAINT_TOOL_CLASS (parent_class)->paint_flush)
|
||||
PIKA_PAINT_TOOL_CLASS (parent_class)->paint_flush (paint_tool);
|
||||
|
||||
if (brush_tool->boundary_scale != brush_core->scale ||
|
||||
brush_tool->boundary_aspect_ratio != brush_core->aspect_ratio ||
|
||||
brush_tool->boundary_angle != brush_core->angle ||
|
||||
brush_tool->boundary_reflect != brush_core->reflect ||
|
||||
brush_tool->boundary_hardness != brush_core->hardness)
|
||||
{
|
||||
g_clear_pointer (&brush_tool->boundary, pika_bezier_desc_free);
|
||||
|
||||
boundary = pika_brush_tool_get_boundary (brush_tool,
|
||||
&brush_tool->boundary_width,
|
||||
&brush_tool->boundary_height);
|
||||
|
||||
if (boundary)
|
||||
brush_tool->boundary = pika_bezier_desc_copy (boundary);
|
||||
|
||||
brush_tool->boundary_scale = brush_core->scale;
|
||||
brush_tool->boundary_aspect_ratio = brush_core->aspect_ratio;
|
||||
brush_tool->boundary_angle = brush_core->angle;
|
||||
brush_tool->boundary_reflect = brush_core->reflect;
|
||||
brush_tool->boundary_hardness = brush_core->hardness;
|
||||
}
|
||||
}
|
||||
|
||||
static PikaCanvasItem *
|
||||
pika_brush_tool_get_outline (PikaPaintTool *paint_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
PikaBrushTool *brush_tool = PIKA_BRUSH_TOOL (paint_tool);
|
||||
PikaCanvasItem *item;
|
||||
|
||||
item = pika_brush_tool_create_outline (brush_tool, display, x, y);
|
||||
|
||||
if (! item)
|
||||
{
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
|
||||
if (brush_core->main_brush && brush_core->dynamics)
|
||||
{
|
||||
/* if an outline was expected, but got scaled away by
|
||||
* transform/dynamics, draw a circle in the "normal" size.
|
||||
*/
|
||||
PikaPaintOptions *options;
|
||||
|
||||
options = PIKA_PAINT_TOOL_GET_OPTIONS (brush_tool);
|
||||
|
||||
pika_paint_tool_set_draw_fallback (paint_tool,
|
||||
TRUE, options->brush_size);
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
PikaCanvasItem *
|
||||
pika_brush_tool_create_outline (PikaBrushTool *brush_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDisplayShell *shell;
|
||||
const PikaBezierDesc *boundary = NULL;
|
||||
gint width = 0;
|
||||
gint height = 0;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_BRUSH_TOOL (brush_tool), NULL);
|
||||
g_return_val_if_fail (PIKA_IS_DISPLAY (display), NULL);
|
||||
|
||||
if (pika_paint_tool_paint_is_active (PIKA_PAINT_TOOL (brush_tool)))
|
||||
{
|
||||
boundary = brush_tool->boundary;
|
||||
width = brush_tool->boundary_width;
|
||||
height = brush_tool->boundary_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundary = pika_brush_tool_get_boundary (brush_tool, &width, &height);
|
||||
}
|
||||
|
||||
if (! boundary)
|
||||
return NULL;
|
||||
|
||||
tool = PIKA_TOOL (brush_tool);
|
||||
shell = pika_display_get_shell (display);
|
||||
|
||||
/* don't draw the boundary if it becomes too small */
|
||||
if (SCALEX (shell, width) > 4 &&
|
||||
SCALEY (shell, height) > 4)
|
||||
{
|
||||
x -= width / 2.0;
|
||||
y -= height / 2.0;
|
||||
|
||||
if (pika_tool_control_get_precision (tool->control) ==
|
||||
PIKA_CURSOR_PRECISION_PIXEL_CENTER)
|
||||
{
|
||||
#define EPSILON 0.000001
|
||||
/* Add EPSILON before rounding since e.g.
|
||||
* (5.0 - 0.5) may end up at (4.499999999....)
|
||||
* due to floating point fnords
|
||||
*/
|
||||
x = RINT (x + EPSILON);
|
||||
y = RINT (y + EPSILON);
|
||||
#undef EPSILON
|
||||
}
|
||||
|
||||
return pika_canvas_path_new (shell, boundary, x, y, FALSE,
|
||||
PIKA_PATH_STYLE_OUTLINE);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_brush_changed (PikaContext *context,
|
||||
PikaBrush *brush,
|
||||
PikaBrushTool *brush_tool)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (brush_tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
|
||||
pika_brush_core_set_brush (brush_core, brush);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
pika_brush_tool_set_brush (PikaBrushCore *brush_core,
|
||||
PikaBrush *brush,
|
||||
PikaBrushTool *brush_tool)
|
||||
{
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (brush_tool));
|
||||
|
||||
if (PIKA_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush)
|
||||
{
|
||||
PikaPaintCore *paint_core = PIKA_PAINT_CORE (brush_core);
|
||||
|
||||
pika_brush_core_eval_transform_dynamics (brush_core,
|
||||
NULL,
|
||||
PIKA_PAINT_TOOL_GET_OPTIONS (brush_tool),
|
||||
&paint_core->cur_coords);
|
||||
}
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (brush_tool));
|
||||
}
|
||||
|
||||
static const PikaBezierDesc *
|
||||
pika_brush_tool_get_boundary (PikaBrushTool *brush_tool,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (brush_tool);
|
||||
PikaBrushCore *brush_core = PIKA_BRUSH_CORE (paint_tool->core);
|
||||
|
||||
if (paint_tool->draw_brush &&
|
||||
brush_core->main_brush &&
|
||||
brush_core->dynamics &&
|
||||
brush_core->scale > 0.0)
|
||||
{
|
||||
return pika_brush_transform_boundary (brush_core->main_brush,
|
||||
brush_core->scale,
|
||||
brush_core->aspect_ratio,
|
||||
brush_core->angle,
|
||||
brush_core->reflect,
|
||||
brush_core->hardness,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
67
app/tools/pikabrushtool.h
Normal file
67
app/tools/pikabrushtool.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_BRUSH_TOOL_H__
|
||||
#define __PIKA_BRUSH_TOOL_H__
|
||||
|
||||
|
||||
#include "pikapainttool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_BRUSH_TOOL (pika_brush_tool_get_type ())
|
||||
#define PIKA_BRUSH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_BRUSH_TOOL, PikaBrushTool))
|
||||
#define PIKA_BRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_BRUSH_TOOL, PikaBrushToolClass))
|
||||
#define PIKA_IS_BRUSH_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_BRUSH_TOOL))
|
||||
#define PIKA_IS_BRUSH_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_BRUSH_TOOL))
|
||||
#define PIKA_BRUSH_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_BRUSH_TOOL, PikaBrushToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaBrushToolClass PikaBrushToolClass;
|
||||
|
||||
struct _PikaBrushTool
|
||||
{
|
||||
PikaPaintTool parent_instance;
|
||||
|
||||
PikaBezierDesc *boundary;
|
||||
gint boundary_width;
|
||||
gint boundary_height;
|
||||
gdouble boundary_scale;
|
||||
gdouble boundary_aspect_ratio;
|
||||
gdouble boundary_angle;
|
||||
gboolean boundary_reflect;
|
||||
gdouble boundary_hardness;
|
||||
};
|
||||
|
||||
struct _PikaBrushToolClass
|
||||
{
|
||||
PikaPaintToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_brush_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
PikaCanvasItem * pika_brush_tool_create_outline (PikaBrushTool *brush_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
|
||||
|
||||
#endif /* __PIKA_BRUSH_TOOL_H__ */
|
||||
876
app/tools/pikabucketfilloptions.c
Normal file
876
app/tools/pikabucketfilloptions.c
Normal file
@ -0,0 +1,876 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
#include "libpikawidgets/pikawidgets-private.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikacoreconfig.h"
|
||||
#include "config/pikadialogconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikacontainer.h"
|
||||
#include "core/pikadatafactory.h"
|
||||
#include "core/pikadrawable.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikapaintinfo.h"
|
||||
#include "core/pikastrokeoptions.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
|
||||
#include "paint/pikasourceoptions.h"
|
||||
|
||||
#include "widgets/pikacontainercombobox.h"
|
||||
#include "widgets/pikacontainertreestore.h"
|
||||
#include "widgets/pikacontainerview.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikaviewablebox.h"
|
||||
#include "widgets/pikaviewrenderer.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikabucketfilloptions.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FILL_MODE,
|
||||
PROP_FILL_AREA,
|
||||
PROP_FILL_TRANSPARENT,
|
||||
PROP_SAMPLE_MERGED,
|
||||
PROP_DIAGONAL_NEIGHBORS,
|
||||
PROP_ANTIALIAS,
|
||||
PROP_FEATHER,
|
||||
PROP_FEATHER_RADIUS,
|
||||
PROP_THRESHOLD,
|
||||
PROP_LINE_ART_SOURCE,
|
||||
PROP_LINE_ART_THRESHOLD,
|
||||
PROP_LINE_ART_MAX_GROW,
|
||||
PROP_LINE_ART_STROKE,
|
||||
PROP_LINE_ART_STROKE_TOOL,
|
||||
PROP_LINE_ART_AUTOMATIC_CLOSURE,
|
||||
PROP_LINE_ART_MAX_GAP_LENGTH,
|
||||
PROP_FILL_CRITERION,
|
||||
PROP_FILL_COLOR_AS_LINE_ART,
|
||||
PROP_FILL_COLOR_AS_LINE_ART_THRESHOLD,
|
||||
};
|
||||
|
||||
struct _PikaBucketFillOptionsPrivate
|
||||
{
|
||||
GtkWidget *diagonal_neighbors_checkbox;
|
||||
GtkWidget *threshold_scale;
|
||||
|
||||
GtkWidget *similar_color_frame;
|
||||
GtkWidget *line_art_settings;
|
||||
GtkWidget *fill_as_line_art_frame;
|
||||
GtkWidget *line_art_detect_opacity;
|
||||
};
|
||||
|
||||
static void pika_bucket_fill_options_config_iface_init (PikaConfigInterface *config_iface);
|
||||
|
||||
static void pika_bucket_fill_options_finalize (GObject *object);
|
||||
static void pika_bucket_fill_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_bucket_fill_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static gboolean
|
||||
pika_bucket_fill_options_select_stroke_tool (PikaContainerView *view,
|
||||
GList *items,
|
||||
GList *paths,
|
||||
PikaBucketFillOptions *options);
|
||||
static void pika_bucket_fill_options_tool_cell_renderer (GtkCellLayout *layout,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data);
|
||||
static void pika_bucket_fill_options_image_changed (PikaContext *context,
|
||||
PikaImage *image,
|
||||
PikaBucketFillOptions *options);
|
||||
|
||||
|
||||
static void pika_bucket_fill_options_reset (PikaConfig *config);
|
||||
static void pika_bucket_fill_options_update_area (PikaBucketFillOptions *options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (PikaBucketFillOptions, pika_bucket_fill_options,
|
||||
PIKA_TYPE_PAINT_OPTIONS,
|
||||
G_ADD_PRIVATE (PikaBucketFillOptions)
|
||||
G_IMPLEMENT_INTERFACE (PIKA_TYPE_CONFIG,
|
||||
pika_bucket_fill_options_config_iface_init))
|
||||
|
||||
#define parent_class pika_bucket_fill_options_parent_class
|
||||
|
||||
static PikaConfigInterface *parent_config_iface = NULL;
|
||||
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_class_init (PikaBucketFillOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_bucket_fill_options_finalize;
|
||||
object_class->set_property = pika_bucket_fill_options_set_property;
|
||||
object_class->get_property = pika_bucket_fill_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FILL_MODE,
|
||||
"fill-mode",
|
||||
_("Fill type"),
|
||||
NULL,
|
||||
PIKA_TYPE_BUCKET_FILL_MODE,
|
||||
PIKA_BUCKET_FILL_FG,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FILL_AREA,
|
||||
"fill-area",
|
||||
_("Fill selection"),
|
||||
_("Which area will be filled"),
|
||||
PIKA_TYPE_BUCKET_FILL_AREA,
|
||||
PIKA_BUCKET_FILL_SIMILAR_COLORS,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_FILL_TRANSPARENT,
|
||||
"fill-transparent",
|
||||
_("Fill transparent areas"),
|
||||
_("Allow completely transparent regions "
|
||||
"to be filled"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_SAMPLE_MERGED,
|
||||
"sample-merged",
|
||||
_("Sample merged"),
|
||||
_("Base filled area on all visible layers"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_DIAGONAL_NEIGHBORS,
|
||||
"diagonal-neighbors",
|
||||
_("Diagonal neighbors"),
|
||||
_("Treat diagonally neighboring pixels as "
|
||||
"connected"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_ANTIALIAS,
|
||||
"antialias",
|
||||
_("Antialiasing"),
|
||||
_("Base fill opacity on color difference from "
|
||||
"the clicked pixel (see threshold) or on line "
|
||||
" art borders. Disable antialiasing to fill "
|
||||
"the entire area uniformly."),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_FEATHER,
|
||||
"feather",
|
||||
_("Feather edges"),
|
||||
_("Enable feathering of fill edges"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_FEATHER_RADIUS,
|
||||
"feather-radius",
|
||||
_("Radius"),
|
||||
_("Radius of feathering"),
|
||||
0.0, 100.0, 10.0,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_THRESHOLD,
|
||||
"threshold",
|
||||
_("Threshold"),
|
||||
_("Maximum color difference"),
|
||||
0.0, 255.0, 15.0,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_LINE_ART_SOURCE,
|
||||
"line-art-source",
|
||||
_("Source"),
|
||||
_("Source image for line art computation"),
|
||||
PIKA_TYPE_LINE_ART_SOURCE,
|
||||
PIKA_LINE_ART_SOURCE_SAMPLE_MERGED,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_FILL_COLOR_AS_LINE_ART,
|
||||
"fill-color-as-line-art",
|
||||
_("Manual closure in fill layer"),
|
||||
_("Consider pixels of selected layer and filled with the fill color as line art closure"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_FILL_COLOR_AS_LINE_ART_THRESHOLD,
|
||||
"fill-color-as-line-art-threshold",
|
||||
_("Threshold"),
|
||||
_("Maximum color difference"),
|
||||
0.0, 255.0, 15.0,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_LINE_ART_THRESHOLD,
|
||||
"line-art-threshold",
|
||||
_("Line art detection threshold"),
|
||||
_("Threshold to detect contour (higher values will include more pixels)"),
|
||||
0.0, 1.0, 0.92,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_LINE_ART_MAX_GROW,
|
||||
"line-art-max-grow",
|
||||
_("Maximum growing size"),
|
||||
_("Maximum number of pixels grown under the line art"),
|
||||
1, 100, 3,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_LINE_ART_STROKE,
|
||||
"line-art-stroke-border",
|
||||
_("Stroke borders"),
|
||||
_("Stroke fill borders with last stroke options"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_STRING (object_class, PROP_LINE_ART_STROKE_TOOL,
|
||||
"line-art-stroke-tool",
|
||||
_("Stroke tool"),
|
||||
_("The tool to stroke the fill borders with"),
|
||||
"pika-pencil", PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_LINE_ART_AUTOMATIC_CLOSURE,
|
||||
"line-art-automatic-closure",
|
||||
_("Automatic closure"),
|
||||
_("Geometric analysis of the stroke contours to close line arts by splines/segments"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_LINE_ART_MAX_GAP_LENGTH,
|
||||
"line-art-max-gap-length",
|
||||
_("Maximum gap length"),
|
||||
_("Maximum gap (in pixels) in line art which can be closed"),
|
||||
0, 1000, 100,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FILL_CRITERION,
|
||||
"fill-criterion",
|
||||
_("Fill by"),
|
||||
_("Criterion used for determining color similarity"),
|
||||
PIKA_TYPE_SELECT_CRITERION,
|
||||
PIKA_SELECT_CRITERION_COMPOSITE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_config_iface_init (PikaConfigInterface *config_iface)
|
||||
{
|
||||
parent_config_iface = g_type_interface_peek_parent (config_iface);
|
||||
|
||||
config_iface->reset = pika_bucket_fill_options_reset;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_init (PikaBucketFillOptions *options)
|
||||
{
|
||||
options->priv = pika_bucket_fill_options_get_instance_private (options);
|
||||
|
||||
options->line_art_stroke_tool = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_finalize (GObject *object)
|
||||
{
|
||||
PikaBucketFillOptions *options = PIKA_BUCKET_FILL_OPTIONS (object);
|
||||
|
||||
g_clear_object (&options->stroke_options);
|
||||
g_clear_pointer (&options->line_art_stroke_tool, g_free);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaBucketFillOptions *options = PIKA_BUCKET_FILL_OPTIONS (object);
|
||||
PikaToolOptions *tool_options = PIKA_TOOL_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILL_MODE:
|
||||
options->fill_mode = g_value_get_enum (value);
|
||||
pika_bucket_fill_options_update_area (options);
|
||||
break;
|
||||
case PROP_FILL_AREA:
|
||||
options->fill_area = g_value_get_enum (value);
|
||||
pika_bucket_fill_options_update_area (options);
|
||||
break;
|
||||
case PROP_FILL_TRANSPARENT:
|
||||
options->fill_transparent = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SAMPLE_MERGED:
|
||||
options->sample_merged = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_DIAGONAL_NEIGHBORS:
|
||||
options->diagonal_neighbors = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_ANTIALIAS:
|
||||
options->antialias = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_FEATHER:
|
||||
options->feather = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_FEATHER_RADIUS:
|
||||
options->feather_radius = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_THRESHOLD:
|
||||
options->threshold = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_LINE_ART_SOURCE:
|
||||
options->line_art_source = g_value_get_enum (value);
|
||||
pika_bucket_fill_options_update_area (options);
|
||||
break;
|
||||
case PROP_LINE_ART_THRESHOLD:
|
||||
options->line_art_threshold = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_LINE_ART_MAX_GROW:
|
||||
options->line_art_max_grow = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_LINE_ART_STROKE:
|
||||
options->line_art_stroke = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_LINE_ART_STROKE_TOOL:
|
||||
g_clear_pointer (&options->line_art_stroke_tool, g_free);
|
||||
options->line_art_stroke_tool = g_value_dup_string (value);
|
||||
|
||||
if (options->stroke_options)
|
||||
{
|
||||
PikaPaintInfo *paint_info = NULL;
|
||||
Pika *pika = tool_options->tool_info->pika;
|
||||
|
||||
if (! options->line_art_stroke_tool)
|
||||
options->line_art_stroke_tool = g_strdup ("pika-pencil");
|
||||
|
||||
paint_info = PIKA_PAINT_INFO (pika_container_get_child_by_name (pika->paint_info_list,
|
||||
options->line_art_stroke_tool));
|
||||
if (! paint_info && ! pika_container_is_empty (pika->paint_info_list))
|
||||
paint_info = PIKA_PAINT_INFO (pika_container_get_child_by_index (pika->paint_info_list, 0));
|
||||
|
||||
g_object_set (options->stroke_options,
|
||||
"paint-info", paint_info,
|
||||
NULL);
|
||||
}
|
||||
break;
|
||||
case PROP_LINE_ART_AUTOMATIC_CLOSURE:
|
||||
options->line_art_automatic_closure = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_LINE_ART_MAX_GAP_LENGTH:
|
||||
options->line_art_max_gap_length = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_FILL_CRITERION:
|
||||
options->fill_criterion = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_FILL_COLOR_AS_LINE_ART:
|
||||
options->fill_as_line_art = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_FILL_COLOR_AS_LINE_ART_THRESHOLD:
|
||||
options->fill_as_line_art_threshold = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaBucketFillOptions *options = PIKA_BUCKET_FILL_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILL_MODE:
|
||||
g_value_set_enum (value, options->fill_mode);
|
||||
break;
|
||||
case PROP_FILL_AREA:
|
||||
g_value_set_enum (value, options->fill_area);
|
||||
break;
|
||||
case PROP_FILL_TRANSPARENT:
|
||||
g_value_set_boolean (value, options->fill_transparent);
|
||||
break;
|
||||
case PROP_SAMPLE_MERGED:
|
||||
g_value_set_boolean (value, options->sample_merged);
|
||||
break;
|
||||
case PROP_DIAGONAL_NEIGHBORS:
|
||||
g_value_set_boolean (value, options->diagonal_neighbors);
|
||||
break;
|
||||
case PROP_ANTIALIAS:
|
||||
g_value_set_boolean (value, options->antialias);
|
||||
break;
|
||||
case PROP_FEATHER:
|
||||
g_value_set_boolean (value, options->feather);
|
||||
break;
|
||||
case PROP_FEATHER_RADIUS:
|
||||
g_value_set_double (value, options->feather_radius);
|
||||
break;
|
||||
case PROP_THRESHOLD:
|
||||
g_value_set_double (value, options->threshold);
|
||||
break;
|
||||
case PROP_LINE_ART_SOURCE:
|
||||
g_value_set_enum (value, options->line_art_source);
|
||||
break;
|
||||
case PROP_LINE_ART_THRESHOLD:
|
||||
g_value_set_double (value, options->line_art_threshold);
|
||||
break;
|
||||
case PROP_LINE_ART_MAX_GROW:
|
||||
g_value_set_int (value, options->line_art_max_grow);
|
||||
break;
|
||||
case PROP_LINE_ART_STROKE:
|
||||
g_value_set_boolean (value, options->line_art_stroke);
|
||||
break;
|
||||
case PROP_LINE_ART_STROKE_TOOL:
|
||||
g_value_set_string (value, options->line_art_stroke_tool);
|
||||
break;
|
||||
case PROP_LINE_ART_AUTOMATIC_CLOSURE:
|
||||
g_value_set_boolean (value, options->line_art_automatic_closure);
|
||||
break;
|
||||
case PROP_LINE_ART_MAX_GAP_LENGTH:
|
||||
g_value_set_int (value, options->line_art_max_gap_length);
|
||||
break;
|
||||
case PROP_FILL_CRITERION:
|
||||
g_value_set_enum (value, options->fill_criterion);
|
||||
break;
|
||||
case PROP_FILL_COLOR_AS_LINE_ART:
|
||||
g_value_set_boolean (value, options->fill_as_line_art);
|
||||
break;
|
||||
case PROP_FILL_COLOR_AS_LINE_ART_THRESHOLD:
|
||||
g_value_set_double (value, options->fill_as_line_art_threshold);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_bucket_fill_options_select_stroke_tool (PikaContainerView *view,
|
||||
GList *items,
|
||||
GList *paths,
|
||||
PikaBucketFillOptions *options)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
for (iter = items; iter; iter = iter->next)
|
||||
{
|
||||
g_object_set (options,
|
||||
"line-art-stroke-tool",
|
||||
iter->data ? pika_object_get_name (iter->data) : NULL,
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_tool_cell_renderer (GtkCellLayout *layout,
|
||||
GtkCellRenderer *cell,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter,
|
||||
gpointer data)
|
||||
{
|
||||
PikaViewRenderer *renderer;
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
PIKA_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
|
||||
-1);
|
||||
|
||||
if (renderer->viewable)
|
||||
{
|
||||
PikaPaintInfo *info = PIKA_PAINT_INFO (renderer->viewable);
|
||||
|
||||
if (PIKA_IS_SOURCE_OPTIONS (info->paint_options))
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model), iter,
|
||||
PIKA_CONTAINER_TREE_STORE_COLUMN_NAME_SENSITIVE, FALSE,
|
||||
-1);
|
||||
}
|
||||
g_object_unref (renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_image_changed (PikaContext *context,
|
||||
PikaImage *image,
|
||||
PikaBucketFillOptions *options)
|
||||
{
|
||||
PikaImage *prev_image;
|
||||
|
||||
prev_image = g_object_get_data (G_OBJECT (options), "pika-bucket-fill-options-image");
|
||||
|
||||
if (image != prev_image)
|
||||
{
|
||||
if (prev_image)
|
||||
g_signal_handlers_disconnect_by_func (prev_image,
|
||||
G_CALLBACK (pika_bucket_fill_options_update_area),
|
||||
options);
|
||||
if (image)
|
||||
{
|
||||
g_signal_connect_object (image, "selected-channels-changed",
|
||||
G_CALLBACK (pika_bucket_fill_options_update_area),
|
||||
options, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (image, "selected-layers-changed",
|
||||
G_CALLBACK (pika_bucket_fill_options_update_area),
|
||||
options, G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
g_object_set_data (G_OBJECT (options), "pika-bucket-fill-options-image", image);
|
||||
pika_bucket_fill_options_update_area (options);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_reset (PikaConfig *config)
|
||||
{
|
||||
PikaToolOptions *tool_options = PIKA_TOOL_OPTIONS (config);
|
||||
GParamSpec *pspec;
|
||||
|
||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config),
|
||||
"threshold");
|
||||
|
||||
if (pspec)
|
||||
G_PARAM_SPEC_DOUBLE (pspec)->default_value =
|
||||
tool_options->tool_info->pika->config->default_threshold;
|
||||
|
||||
parent_config_iface->reset (config);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_bucket_fill_options_update_area (PikaBucketFillOptions *options)
|
||||
{
|
||||
PikaImage *image;
|
||||
GList *drawables = NULL;
|
||||
const gchar *tooltip = _("Opaque pixels will be considered as line art "
|
||||
"instead of low luminance pixels");
|
||||
|
||||
image = pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika));
|
||||
|
||||
/* GUI not created yet. */
|
||||
if (! options->priv->threshold_scale)
|
||||
return;
|
||||
|
||||
if (image)
|
||||
drawables = pika_image_get_selected_drawables (image);
|
||||
|
||||
switch (options->fill_area)
|
||||
{
|
||||
case PIKA_BUCKET_FILL_LINE_ART:
|
||||
gtk_widget_hide (options->priv->similar_color_frame);
|
||||
gtk_widget_show (options->priv->line_art_settings);
|
||||
if ((options->fill_mode == PIKA_BUCKET_FILL_FG ||
|
||||
options->fill_mode == PIKA_BUCKET_FILL_BG) &&
|
||||
(options->line_art_source == PIKA_LINE_ART_SOURCE_LOWER_LAYER ||
|
||||
options->line_art_source == PIKA_LINE_ART_SOURCE_UPPER_LAYER))
|
||||
gtk_widget_set_sensitive (options->priv->fill_as_line_art_frame, TRUE);
|
||||
else
|
||||
gtk_widget_set_sensitive (options->priv->fill_as_line_art_frame, FALSE);
|
||||
|
||||
if (image != NULL &&
|
||||
options->line_art_source != PIKA_LINE_ART_SOURCE_SAMPLE_MERGED &&
|
||||
g_list_length (drawables) == 1)
|
||||
{
|
||||
PikaDrawable *source = NULL;
|
||||
PikaItem *parent;
|
||||
PikaContainer *container;
|
||||
gint index;
|
||||
|
||||
parent = pika_item_get_parent (PIKA_ITEM (drawables->data));
|
||||
if (parent)
|
||||
container = pika_viewable_get_children (PIKA_VIEWABLE (parent));
|
||||
else
|
||||
container = pika_image_get_layers (image);
|
||||
|
||||
index = pika_item_get_index (PIKA_ITEM (drawables->data));
|
||||
if (options->line_art_source == PIKA_LINE_ART_SOURCE_ACTIVE_LAYER)
|
||||
source = drawables->data;
|
||||
else if (options->line_art_source == PIKA_LINE_ART_SOURCE_LOWER_LAYER)
|
||||
source = PIKA_DRAWABLE (pika_container_get_child_by_index (container, index + 1));
|
||||
else if (options->line_art_source == PIKA_LINE_ART_SOURCE_UPPER_LAYER)
|
||||
source = PIKA_DRAWABLE (pika_container_get_child_by_index (container, index - 1));
|
||||
|
||||
gtk_widget_set_sensitive (options->priv->line_art_detect_opacity,
|
||||
source != NULL &&
|
||||
pika_drawable_has_alpha (source));
|
||||
if (source == NULL)
|
||||
tooltip = _("No valid source drawable selected");
|
||||
else if (! pika_drawable_has_alpha (source))
|
||||
tooltip = _("The source drawable has no alpha channel");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (options->priv->line_art_detect_opacity,
|
||||
TRUE);
|
||||
}
|
||||
gtk_widget_set_tooltip_text (options->priv->line_art_detect_opacity,
|
||||
tooltip);
|
||||
break;
|
||||
case PIKA_BUCKET_FILL_SIMILAR_COLORS:
|
||||
gtk_widget_show (options->priv->similar_color_frame);
|
||||
gtk_widget_hide (options->priv->line_art_settings);
|
||||
break;
|
||||
default:
|
||||
gtk_widget_hide (options->priv->similar_color_frame);
|
||||
gtk_widget_hide (options->priv->line_art_settings);
|
||||
break;
|
||||
}
|
||||
|
||||
g_list_free (drawables);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_bucket_fill_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
PikaBucketFillOptions *options = PIKA_BUCKET_FILL_OPTIONS (tool_options);
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
Pika *pika = tool_options->tool_info->pika;
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *box2;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *combo;
|
||||
gchar *str;
|
||||
gboolean bold;
|
||||
GdkModifierType extend_mask = pika_get_extend_selection_mask ();
|
||||
GdkModifierType toggle_mask = GDK_MOD1_MASK;
|
||||
|
||||
/* fill type */
|
||||
str = g_strdup_printf (_("Fill Type (%s)"),
|
||||
pika_get_mod_string (toggle_mask)),
|
||||
frame = pika_prop_enum_radio_frame_new (config, "fill-mode", str, 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
g_free (str);
|
||||
|
||||
hbox = pika_prop_pattern_box_new (NULL, PIKA_CONTEXT (tool_options),
|
||||
NULL, 2,
|
||||
"pattern-view-type", "pattern-view-size");
|
||||
pika_enum_radio_frame_add (GTK_FRAME (frame), hbox,
|
||||
PIKA_BUCKET_FILL_PATTERN, TRUE);
|
||||
|
||||
/* fill selection */
|
||||
str = g_strdup_printf (_("Affected Area (%s)"),
|
||||
pika_get_mod_string (extend_mask));
|
||||
frame = pika_prop_enum_radio_frame_new (config, "fill-area", str, 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
g_free (str);
|
||||
|
||||
/* Similar color frame */
|
||||
frame = pika_frame_new (_("Finding Similar Colors"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
options->priv->similar_color_frame = frame;
|
||||
gtk_widget_show (frame);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box2);
|
||||
gtk_widget_show (box2);
|
||||
|
||||
/* the fill transparent areas toggle */
|
||||
widget = pika_prop_check_button_new (config, "fill-transparent", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, FALSE, 0);
|
||||
|
||||
/* the sample merged toggle */
|
||||
widget = pika_prop_check_button_new (config, "sample-merged", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, FALSE, 0);
|
||||
|
||||
/* the diagonal neighbors toggle */
|
||||
widget = pika_prop_check_button_new (config, "diagonal-neighbors", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, FALSE, 0);
|
||||
options->priv->diagonal_neighbors_checkbox = widget;
|
||||
|
||||
/* the antialias toggle */
|
||||
widget = pika_prop_check_button_new (config, "antialias", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, FALSE, 0);
|
||||
|
||||
/* the threshold scale */
|
||||
scale = pika_prop_spin_scale_new (config, "threshold",
|
||||
1.0, 16.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (box2), scale, FALSE, FALSE, 0);
|
||||
options->priv->threshold_scale = scale;
|
||||
|
||||
/* the fill criterion combo */
|
||||
combo = pika_prop_enum_combo_box_new (config, "fill-criterion", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Fill by"));
|
||||
gtk_box_pack_start (GTK_BOX (box2), combo, FALSE, FALSE, 0);
|
||||
|
||||
/* Line art settings */
|
||||
options->priv->line_art_settings = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), options->priv->line_art_settings, FALSE, FALSE, 0);
|
||||
pika_widget_set_identifier (options->priv->line_art_settings, "line-art-settings");
|
||||
|
||||
frame = pika_frame_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (options->priv->line_art_settings), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* Line art: label widget */
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
|
||||
gtk_frame_set_label_widget (GTK_FRAME (frame), box2);
|
||||
gtk_widget_show (box2);
|
||||
|
||||
widget = gtk_label_new (_("Line Art Detection"));
|
||||
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, FALSE, 0);
|
||||
gtk_widget_style_get (GTK_WIDGET (frame),
|
||||
"label-bold", &bold,
|
||||
NULL);
|
||||
pika_label_set_attributes (GTK_LABEL (widget),
|
||||
PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
|
||||
-1);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
options->line_art_busy_box = pika_busy_box_new (_("(computing...)"));
|
||||
gtk_box_pack_start (GTK_BOX (box2), options->line_art_busy_box,
|
||||
FALSE, FALSE, 0);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box2);
|
||||
gtk_widget_show (box2);
|
||||
|
||||
/* Line Art: source combo (replace sample merged!) */
|
||||
combo = pika_prop_enum_combo_box_new (config, "line-art-source", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Source"));
|
||||
gtk_box_pack_start (GTK_BOX (box2), combo, FALSE, FALSE, 0);
|
||||
|
||||
/* the fill transparent areas toggle */
|
||||
widget = pika_prop_check_button_new (config, "fill-transparent",
|
||||
_("Detect opacity rather than grayscale"));
|
||||
options->priv->line_art_detect_opacity = widget;
|
||||
gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, FALSE, 0);
|
||||
|
||||
/* Line Art: stroke threshold */
|
||||
scale = pika_prop_spin_scale_new (config, "line-art-threshold",
|
||||
0.05, 0.1, 2);
|
||||
gtk_box_pack_start (GTK_BOX (box2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* Line Art Closure frame */
|
||||
frame = pika_frame_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (options->priv->line_art_settings), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* Line Art Closure: frame label */
|
||||
widget = gtk_label_new (_("Line Art Closure"));
|
||||
gtk_frame_set_label_widget (GTK_FRAME (frame), widget);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box2);
|
||||
gtk_widget_show (box2);
|
||||
|
||||
/* Line Art Closure: max gap length */
|
||||
scale = pika_prop_spin_scale_new (config, "line-art-max-gap-length",
|
||||
1, 5, 0);
|
||||
frame = pika_prop_expanding_frame_new (config, "line-art-automatic-closure", NULL,
|
||||
scale, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* Line Art Closure: manual line art closure */
|
||||
scale = pika_prop_spin_scale_new (config, "fill-color-as-line-art-threshold",
|
||||
1.0, 16.0, 1);
|
||||
|
||||
frame = pika_prop_expanding_frame_new (config, "fill-color-as-line-art", NULL,
|
||||
scale, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), frame, FALSE, FALSE, 0);
|
||||
options->priv->fill_as_line_art_frame = frame;
|
||||
|
||||
/* Line Art Borders frame */
|
||||
|
||||
frame = pika_frame_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (options->priv->line_art_settings), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* Line Art Borders: frame label */
|
||||
widget = gtk_label_new (_("Fill borders"));
|
||||
gtk_frame_set_label_widget (GTK_FRAME (frame), widget);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (frame), box2);
|
||||
gtk_widget_show (box2);
|
||||
|
||||
/* Line Art Borders: max growing size */
|
||||
scale = pika_prop_spin_scale_new (config, "line-art-max-grow",
|
||||
1, 5, 0);
|
||||
gtk_box_pack_start (GTK_BOX (box2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* Line Art Borders: feather radius scale */
|
||||
scale = pika_prop_spin_scale_new (config, "feather-radius",
|
||||
1.0, 10.0, 1);
|
||||
|
||||
frame = pika_prop_expanding_frame_new (config, "feather", NULL,
|
||||
scale, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* Line Art Borders: stroke border with paint brush */
|
||||
|
||||
options->stroke_options = pika_stroke_options_new (pika,
|
||||
pika_get_user_context (pika),
|
||||
TRUE);
|
||||
pika_config_sync (G_OBJECT (PIKA_DIALOG_CONFIG (pika->config)->stroke_options),
|
||||
G_OBJECT (options->stroke_options), 0);
|
||||
|
||||
widget = pika_container_combo_box_new (pika->paint_info_list,
|
||||
PIKA_CONTEXT (options->stroke_options),
|
||||
16, 0);
|
||||
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (widget),
|
||||
PIKA_CONTAINER_COMBO_BOX (widget)->viewable_renderer,
|
||||
pika_bucket_fill_options_tool_cell_renderer,
|
||||
options, NULL);
|
||||
g_signal_connect (widget, "select-items",
|
||||
G_CALLBACK (pika_bucket_fill_options_select_stroke_tool),
|
||||
options);
|
||||
|
||||
frame = pika_prop_expanding_frame_new (config, "line-art-stroke-border", NULL,
|
||||
widget, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box2), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (widget);
|
||||
|
||||
pika_bucket_fill_options_update_area (options);
|
||||
|
||||
g_signal_connect (pika_get_user_context (PIKA_CONTEXT (tool_options)->pika),
|
||||
"image-changed",
|
||||
G_CALLBACK (pika_bucket_fill_options_image_changed),
|
||||
tool_options);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
81
app/tools/pikabucketfilloptions.h
Normal file
81
app/tools/pikabucketfilloptions.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_BUCKET_FILL_OPTIONS_H__
|
||||
#define __PIKA_BUCKET_FILL_OPTIONS_H__
|
||||
|
||||
|
||||
#include "paint/pikapaintoptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_BUCKET_FILL_OPTIONS (pika_bucket_fill_options_get_type ())
|
||||
#define PIKA_BUCKET_FILL_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_BUCKET_FILL_OPTIONS, PikaBucketFillOptions))
|
||||
#define PIKA_BUCKET_FILL_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_BUCKET_FILL_OPTIONS, PikaBucketFillOptionsClass))
|
||||
#define PIKA_IS_BUCKET_FILL_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_BUCKET_FILL_OPTIONS))
|
||||
#define PIKA_IS_BUCKET_FILL_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_BUCKET_FILL_OPTIONS))
|
||||
#define PIKA_BUCKET_FILL_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_BUCKET_FILL_OPTIONS, PikaBucketFillOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaBucketFillOptions PikaBucketFillOptions;
|
||||
typedef struct _PikaBucketFillOptionsPrivate PikaBucketFillOptionsPrivate;
|
||||
typedef struct _PikaPaintOptionsClass PikaBucketFillOptionsClass;
|
||||
|
||||
struct _PikaBucketFillOptions
|
||||
{
|
||||
PikaPaintOptions paint_options;
|
||||
|
||||
PikaBucketFillMode fill_mode;
|
||||
PikaBucketFillArea fill_area;
|
||||
gboolean fill_transparent;
|
||||
gboolean sample_merged;
|
||||
gboolean diagonal_neighbors;
|
||||
gboolean antialias;
|
||||
gboolean feather;
|
||||
gdouble feather_radius;
|
||||
gdouble threshold;
|
||||
|
||||
GtkWidget *line_art_busy_box;
|
||||
PikaLineArtSource line_art_source;
|
||||
gdouble line_art_threshold;
|
||||
gint line_art_max_grow;
|
||||
|
||||
gboolean line_art_automatic_closure;
|
||||
gint line_art_max_gap_length;
|
||||
|
||||
gboolean line_art_stroke;
|
||||
gchar *line_art_stroke_tool;
|
||||
PikaStrokeOptions *stroke_options;
|
||||
|
||||
gboolean fill_as_line_art;
|
||||
gdouble fill_as_line_art_threshold;
|
||||
|
||||
PikaSelectCriterion fill_criterion;
|
||||
|
||||
PikaBucketFillOptionsPrivate *priv;
|
||||
};
|
||||
|
||||
|
||||
GType pika_bucket_fill_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_bucket_fill_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_BUCKET_FILL_OPTIONS_H__ */
|
||||
1126
app/tools/pikabucketfilltool.c
Normal file
1126
app/tools/pikabucketfilltool.c
Normal file
File diff suppressed because it is too large
Load Diff
62
app/tools/pikabucketfilltool.h
Normal file
62
app/tools/pikabucketfilltool.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_BUCKET_FILL_TOOL_H__
|
||||
#define __PIKA_BUCKET_FILL_TOOL_H__
|
||||
|
||||
|
||||
#include "pikacolortool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_BUCKET_FILL_TOOL (pika_bucket_fill_tool_get_type ())
|
||||
#define PIKA_BUCKET_FILL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_BUCKET_FILL_TOOL, PikaBucketFillTool))
|
||||
#define PIKA_BUCKET_FILL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_BUCKET_FILL_TOOL, PikaBucketFillToolClass))
|
||||
#define PIKA_IS_BUCKET_FILL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_BUCKET_FILL_TOOL))
|
||||
#define PIKA_IS_BUCKET_FILL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_BUCKET_FILL_TOOL))
|
||||
#define PIKA_BUCKET_FILL_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_BUCKET_FILL_TOOL, PikaBucketFillToolClass))
|
||||
|
||||
#define PIKA_BUCKET_FILL_TOOL_GET_OPTIONS(t) (PIKA_BUCKET_FILL_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaBucketFillTool PikaBucketFillTool;
|
||||
typedef struct _PikaBucketFillToolClass PikaBucketFillToolClass;
|
||||
typedef struct _PikaBucketFillToolPrivate PikaBucketFillToolPrivate;
|
||||
|
||||
struct _PikaBucketFillTool
|
||||
{
|
||||
PikaColorTool parent_instance;
|
||||
|
||||
PikaBucketFillToolPrivate *priv;
|
||||
};
|
||||
|
||||
struct _PikaBucketFillToolClass
|
||||
{
|
||||
PikaColorToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_bucket_fill_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_bucket_fill_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_BUCKET_FILL_TOOL_H__ */
|
||||
167
app/tools/pikabycolorselecttool.c
Normal file
167
app/tools/pikabycolorselecttool.c
Normal file
@ -0,0 +1,167 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikabycolorselecttool.c
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikacontainer.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-new.h"
|
||||
#include "core/pikaitem.h"
|
||||
#include "core/pikapickable.h"
|
||||
#include "core/pikapickable-contiguous-region.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
|
||||
#include "pikabycolorselecttool.h"
|
||||
#include "pikaregionselectoptions.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static GeglBuffer * pika_by_color_select_tool_get_mask (PikaRegionSelectTool *region_select,
|
||||
PikaDisplay *display);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaByColorSelectTool, pika_by_color_select_tool,
|
||||
PIKA_TYPE_REGION_SELECT_TOOL)
|
||||
|
||||
#define parent_class pika_by_color_select_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_by_color_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_BY_COLOR_SELECT_TOOL,
|
||||
PIKA_TYPE_REGION_SELECT_OPTIONS,
|
||||
pika_region_select_options_gui,
|
||||
0,
|
||||
"pika-by-color-select-tool",
|
||||
_("Select by Color"),
|
||||
_("Select by Color Tool: Select regions with similar colors"),
|
||||
N_("_By Color Select"), "<shift>O",
|
||||
NULL, PIKA_HELP_TOOL_BY_COLOR_SELECT,
|
||||
PIKA_ICON_TOOL_BY_COLOR_SELECT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_by_color_select_tool_class_init (PikaByColorSelectToolClass *klass)
|
||||
{
|
||||
PikaRegionSelectToolClass *region_class;
|
||||
|
||||
region_class = PIKA_REGION_SELECT_TOOL_CLASS (klass);
|
||||
|
||||
region_class->undo_desc = C_("command", "Select by Color");
|
||||
region_class->get_mask = pika_by_color_select_tool_get_mask;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_by_color_select_tool_init (PikaByColorSelectTool *by_color_select)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (by_color_select);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_HAND);
|
||||
}
|
||||
|
||||
static GeglBuffer *
|
||||
pika_by_color_select_tool_get_mask (PikaRegionSelectTool *region_select,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (region_select);
|
||||
PikaSelectionOptions *sel_options = PIKA_SELECTION_TOOL_GET_OPTIONS (tool);
|
||||
PikaRegionSelectOptions *options = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
PikaImage *select_image = NULL;
|
||||
GList *drawables = pika_image_get_selected_drawables (image);
|
||||
PikaPickable *pickable;
|
||||
GeglBuffer *mask = NULL;
|
||||
PikaRGB srgb;
|
||||
gint x, y;
|
||||
|
||||
x = region_select->x;
|
||||
y = region_select->y;
|
||||
|
||||
if (! options->sample_merged)
|
||||
{
|
||||
if (g_list_length (drawables) == 1)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (drawables->data, &off_x, &off_y);
|
||||
|
||||
x -= off_x;
|
||||
y -= off_y;
|
||||
|
||||
pickable = PIKA_PICKABLE (drawables->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
select_image = pika_image_new_from_drawables (image->pika, drawables, FALSE, FALSE);
|
||||
pika_container_remove (image->pika->images, PIKA_OBJECT (select_image));
|
||||
|
||||
pickable = PIKA_PICKABLE (select_image);
|
||||
pika_pickable_flush (pickable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pickable = PIKA_PICKABLE (image);
|
||||
}
|
||||
|
||||
g_list_free (drawables);
|
||||
pika_pickable_flush (pickable);
|
||||
|
||||
if (pika_pickable_get_color_at (pickable, x, y, &srgb))
|
||||
{
|
||||
PikaRGB color;
|
||||
|
||||
pika_pickable_srgb_to_image_color (pickable, &srgb, &color);
|
||||
|
||||
mask = pika_pickable_contiguous_region_by_color (pickable,
|
||||
sel_options->antialias,
|
||||
options->threshold / 255.0,
|
||||
options->select_transparent,
|
||||
options->select_criterion,
|
||||
&color);
|
||||
}
|
||||
|
||||
if (select_image)
|
||||
g_object_unref (select_image);
|
||||
|
||||
return mask;
|
||||
}
|
||||
59
app/tools/pikabycolorselecttool.h
Normal file
59
app/tools/pikabycolorselecttool.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikabycolorselectool.h
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_BY_COLOR_SELECT_TOOL_H__
|
||||
#define __PIKA_BY_COLOR_SELECT_TOOL_H__
|
||||
|
||||
|
||||
#include "pikaregionselecttool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_BY_COLOR_SELECT_TOOL (pika_by_color_select_tool_get_type ())
|
||||
#define PIKA_BY_COLOR_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_BY_COLOR_SELECT_TOOL, PikaByColorSelectTool))
|
||||
#define PIKA_BY_COLOR_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_BY_COLOR_SELECT_TOOL, PikaByColorSelectToolClass))
|
||||
#define PIKA_IS_BY_COLOR_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_BY_COLOR_SELECT_TOOL))
|
||||
#define PIKA_IS_BY_COLOR_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_BY_COLOR_SELECT_TOOL))
|
||||
#define PIKA_BY_COLOR_SELECT_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_BY_COLOR_SELECT_TOOL, PikaByColorSelectToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaByColorSelectTool PikaByColorSelectTool;
|
||||
typedef struct _PikaByColorSelectToolClass PikaByColorSelectToolClass;
|
||||
|
||||
struct _PikaByColorSelectTool
|
||||
{
|
||||
PikaRegionSelectTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaByColorSelectToolClass
|
||||
{
|
||||
PikaRegionSelectToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_by_color_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_by_color_select_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_BY_COLOR_SELECT_TOOL_H__ */
|
||||
155
app/tools/pikacageoptions.c
Normal file
155
app/tools/pikacageoptions.c
Normal file
@ -0,0 +1,155 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
*
|
||||
* pikacageoptions.c
|
||||
* Copyright (C) 2010 Michael Muré <batolettre@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "pikacageoptions.h"
|
||||
#include "pikatooloptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CAGE_MODE,
|
||||
PROP_FILL_PLAIN_COLOR
|
||||
};
|
||||
|
||||
|
||||
static void pika_cage_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_cage_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaCageOptions, pika_cage_options,
|
||||
PIKA_TYPE_TOOL_OPTIONS)
|
||||
|
||||
#define parent_class pika_cage_options_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_cage_options_class_init (PikaCageOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_cage_options_set_property;
|
||||
object_class->get_property = pika_cage_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_CAGE_MODE,
|
||||
"cage-mode",
|
||||
NULL, NULL,
|
||||
PIKA_TYPE_CAGE_MODE,
|
||||
PIKA_CAGE_MODE_CAGE_CHANGE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_FILL_PLAIN_COLOR,
|
||||
"fill-plain-color",
|
||||
_("Fill the original position\n"
|
||||
"of the cage with a color"),
|
||||
NULL,
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_cage_options_init (PikaCageOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_cage_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaCageOptions *options = PIKA_CAGE_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_CAGE_MODE:
|
||||
options->cage_mode = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_FILL_PLAIN_COLOR:
|
||||
options->fill_plain_color = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_cage_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaCageOptions *options = PIKA_CAGE_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_CAGE_MODE:
|
||||
g_value_set_enum (value, options->cage_mode);
|
||||
break;
|
||||
case PROP_FILL_PLAIN_COLOR:
|
||||
g_value_set_boolean (value, options->fill_plain_color);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_cage_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_tool_options_gui (tool_options);
|
||||
GtkWidget *mode;
|
||||
GtkWidget *button;
|
||||
|
||||
mode = pika_prop_enum_radio_box_new (config, "cage-mode", 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), mode, FALSE, FALSE, 0);
|
||||
|
||||
button = pika_prop_check_button_new (config, "fill-plain-color", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
61
app/tools/pikacageoptions.h
Normal file
61
app/tools/pikacageoptions.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
*
|
||||
* pikacageoptions.h
|
||||
* Copyright (C) 2010 Michael Muré <batolettre@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CAGE_OPTIONS_H__
|
||||
#define __PIKA_CAGE_OPTIONS_H__
|
||||
|
||||
|
||||
#include "core/pikatooloptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CAGE_OPTIONS (pika_cage_options_get_type ())
|
||||
#define PIKA_CAGE_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CAGE_OPTIONS, PikaCageOptions))
|
||||
#define PIKA_CAGE_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CAGE_OPTIONS, PikaCageOptionsClass))
|
||||
#define PIKA_IS_CAGE_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CAGE_OPTIONS))
|
||||
#define PIKA_IS_CAGE_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CAGE_OPTIONS))
|
||||
#define PIKA_CAGE_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CAGE_OPTIONS, PikaCageOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaCageOptions PikaCageOptions;
|
||||
typedef struct _PikaCageOptionsClass PikaCageOptionsClass;
|
||||
|
||||
struct _PikaCageOptions
|
||||
{
|
||||
PikaToolOptions parent_instance;
|
||||
|
||||
PikaCageMode cage_mode;
|
||||
gboolean fill_plain_color;
|
||||
};
|
||||
|
||||
struct _PikaCageOptionsClass
|
||||
{
|
||||
PikaToolOptionsClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_cage_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_cage_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_CAGE_OPTIONS_H__ */
|
||||
1325
app/tools/pikacagetool.c
Normal file
1325
app/tools/pikacagetool.c
Normal file
File diff suppressed because it is too large
Load Diff
89
app/tools/pikacagetool.h
Normal file
89
app/tools/pikacagetool.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
*
|
||||
* pikacagetool.h
|
||||
* Copyright (C) 2010 Michael Muré <batolettre@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CAGE_TOOL_H__
|
||||
#define __PIKA_CAGE_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CAGE_TOOL (pika_cage_tool_get_type ())
|
||||
#define PIKA_CAGE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CAGE_TOOL, PikaCageTool))
|
||||
#define PIKA_CAGE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CAGE_TOOL, PikaCageToolClass))
|
||||
#define PIKA_IS_CAGE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CAGE_TOOL))
|
||||
#define PIKA_IS_CAGE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CAGE_TOOL))
|
||||
#define PIKA_CAGE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CAGE_TOOL, PikaCageToolClass))
|
||||
|
||||
#define PIKA_CAGE_TOOL_GET_OPTIONS(t) (PIKA_CAGE_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaCageTool PikaCageTool;
|
||||
typedef struct _PikaCageToolClass PikaCageToolClass;
|
||||
|
||||
struct _PikaCageTool
|
||||
{
|
||||
PikaDrawTool parent_instance;
|
||||
|
||||
PikaCageConfig *config;
|
||||
|
||||
gint offset_x; /* used to convert the cage point coords */
|
||||
gint offset_y; /* to drawable coords */
|
||||
|
||||
gdouble cursor_x; /* Hold the cursor x position */
|
||||
gdouble cursor_y; /* Hold the cursor y position */
|
||||
|
||||
gdouble movement_start_x; /* Where the movement started */
|
||||
gdouble movement_start_y; /* Where the movement started */
|
||||
|
||||
gdouble selection_start_x; /* Where the selection started */
|
||||
gdouble selection_start_y; /* Where the selection started */
|
||||
|
||||
gint hovering_handle; /* Handle which the cursor is above */
|
||||
gint hovering_edge; /* Edge which the cursor is above */
|
||||
|
||||
GeglBuffer *coef; /* Gegl buffer where the coefficient of the transformation are stored */
|
||||
gboolean dirty_coef; /* Indicate if the coef are still valid */
|
||||
|
||||
GeglNode *render_node; /* Gegl node graph to render the transformation */
|
||||
GeglNode *cage_node; /* Gegl node that compute the cage transform */
|
||||
GeglNode *coef_node; /* Gegl node that read in the coef buffer */
|
||||
|
||||
gint tool_state; /* Current state in statemachine */
|
||||
|
||||
PikaDrawableFilter *filter; /* For preview */
|
||||
};
|
||||
|
||||
struct _PikaCageToolClass
|
||||
{
|
||||
PikaDrawToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_cage_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_cage_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_CAGE_TOOL_H__ */
|
||||
320
app/tools/pikacloneoptions-gui.c
Normal file
320
app/tools/pikacloneoptions-gui.c
Normal file
@ -0,0 +1,320 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaitem.h"
|
||||
|
||||
#include "paint/pikacloneoptions.h"
|
||||
|
||||
#include "widgets/pikaviewablebox.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikacloneoptions-gui.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static gboolean pika_clone_options_sync_source (GBinding *binding,
|
||||
const GValue *source_value,
|
||||
GValue *target_value,
|
||||
gpointer user_data);
|
||||
|
||||
static void pika_clone_options_gui_drawables_changed (PikaImage *image,
|
||||
PikaSourceOptions *options);
|
||||
static void pika_clone_options_gui_src_changed (PikaSourceOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GtkWidget *label);
|
||||
static void pika_clone_options_gui_context_image_changed (PikaContext *context,
|
||||
PikaImage *image,
|
||||
PikaSourceOptions *options);
|
||||
|
||||
static gboolean pika_clone_options_gui_update_src_label (PikaSourceOptions *options);
|
||||
|
||||
|
||||
static gboolean
|
||||
pika_clone_options_sync_source (GBinding *binding,
|
||||
const GValue *source_value,
|
||||
GValue *target_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
PikaCloneType type = g_value_get_enum (source_value);
|
||||
|
||||
g_value_set_boolean (target_value,
|
||||
type == GPOINTER_TO_INT (user_data));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_clone_options_gui_drawables_changed (PikaImage *image,
|
||||
PikaSourceOptions *options)
|
||||
{
|
||||
GList *drawables;
|
||||
GtkWidget *button;
|
||||
|
||||
drawables = pika_image_get_selected_drawables (image);
|
||||
button = g_object_get_data (G_OBJECT (options), "sample-merged-checkbox");
|
||||
|
||||
gtk_widget_set_sensitive (button, (g_list_length (drawables) < 2));
|
||||
g_list_free (drawables);
|
||||
|
||||
/* In case this was called several times in a row by threads. */
|
||||
g_idle_remove_by_data (options);
|
||||
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
|
||||
(GSourceFunc) pika_clone_options_gui_update_src_label,
|
||||
g_object_ref (options), (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_clone_options_gui_src_changed (PikaSourceOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GtkWidget *label)
|
||||
{
|
||||
/* In case this was called several times in a row by threads. */
|
||||
g_idle_remove_by_data (options);
|
||||
|
||||
/* Why we need absolutely to run this in a thread is that it updates
|
||||
* the GUI. And sometimes this src_changed callback may be called by
|
||||
* paint threads (see pikapainttool-paint.c). This may cause crashes
|
||||
* as in recent GTK, all GTK/GDK calls should be main from the main
|
||||
* thread. Idle functions are ensured to be run in this main thread.
|
||||
*/
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
|
||||
(GSourceFunc) pika_clone_options_gui_update_src_label,
|
||||
g_object_ref (options), (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_clone_options_gui_context_image_changed (PikaContext *context,
|
||||
PikaImage *image,
|
||||
PikaSourceOptions *options)
|
||||
{
|
||||
PikaImage *prev_image;
|
||||
GtkWidget *button;
|
||||
|
||||
button = g_object_get_data (G_OBJECT (options), "sample-merged-checkbox");
|
||||
prev_image = g_object_get_data (G_OBJECT (button), "pika-clone-options-gui-image");
|
||||
|
||||
if (image != prev_image)
|
||||
{
|
||||
if (prev_image)
|
||||
g_signal_handlers_disconnect_by_func (prev_image,
|
||||
G_CALLBACK (pika_clone_options_gui_drawables_changed),
|
||||
options);
|
||||
if (image)
|
||||
{
|
||||
g_signal_connect_object (image, "selected-channels-changed",
|
||||
G_CALLBACK (pika_clone_options_gui_drawables_changed),
|
||||
options, 0);
|
||||
g_signal_connect_object (image, "selected-layers-changed",
|
||||
G_CALLBACK (pika_clone_options_gui_drawables_changed),
|
||||
options, 0);
|
||||
pika_clone_options_gui_drawables_changed (image, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (button, TRUE);
|
||||
}
|
||||
|
||||
g_object_set_data (G_OBJECT (button), "pika-clone-options-gui-image", image);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_clone_options_gui_update_src_label (PikaSourceOptions *options)
|
||||
{
|
||||
GtkWidget *label;
|
||||
gchar *markup = NULL;
|
||||
|
||||
label = g_object_get_data (G_OBJECT (options), "src-label");
|
||||
|
||||
if (options->src_drawables == NULL)
|
||||
{
|
||||
markup = g_strdup_printf ("<i>%s</i>", _("No source selected"));
|
||||
}
|
||||
else
|
||||
{
|
||||
PikaImage *image;
|
||||
GList *drawables;
|
||||
gchar *str = NULL;
|
||||
gboolean sample_merged;
|
||||
|
||||
image = pika_context_get_image (pika_get_user_context (PIKA_CONTEXT (options)->pika));
|
||||
drawables = pika_image_get_selected_drawables (image);
|
||||
|
||||
sample_merged = options->sample_merged && g_list_length (drawables) == 1;
|
||||
|
||||
if (g_list_length (drawables) > 1)
|
||||
{
|
||||
str = g_strdup_printf (ngettext ("Source: %d item to itself",
|
||||
"Source: %d items to themselves",
|
||||
g_list_length (drawables)),
|
||||
g_list_length (drawables));
|
||||
}
|
||||
else
|
||||
{
|
||||
PikaImage *src_image = NULL;
|
||||
|
||||
src_image = pika_item_get_image (options->src_drawables->data);
|
||||
|
||||
if (sample_merged)
|
||||
{
|
||||
if (image == src_image)
|
||||
str = g_strdup (_("All composited visible layers"));
|
||||
else
|
||||
str = g_strdup_printf (_("All composited visible layers from '%s'"),
|
||||
pika_image_get_display_name (src_image));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (image == src_image)
|
||||
str = g_strdup_printf (ngettext ("Source: %d item",
|
||||
"Source: %d items",
|
||||
g_list_length (options->src_drawables)),
|
||||
g_list_length (options->src_drawables));
|
||||
else
|
||||
str = g_strdup_printf (ngettext ("Source: %d item from '%s'",
|
||||
"Source: %d items from '%s'",
|
||||
g_list_length (options->src_drawables)),
|
||||
g_list_length (options->src_drawables),
|
||||
pika_image_get_display_name (src_image));
|
||||
}
|
||||
}
|
||||
markup = g_strdup_printf ("<i>%s</i>", str);
|
||||
|
||||
g_list_free (drawables);
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||
g_free (markup);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
||||
/* Public functions. */
|
||||
|
||||
|
||||
GtkWidget *
|
||||
pika_clone_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *frame;
|
||||
GtkWidget *label;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *source_vbox;
|
||||
GtkWidget *button;
|
||||
GtkWidget *hbox;
|
||||
gchar *str;
|
||||
|
||||
/* the source frame */
|
||||
frame = pika_frame_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_box_reorder_child (GTK_BOX (vbox), frame, 2);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
/* the source type menu */
|
||||
combo = pika_prop_enum_combo_box_new (config, "clone-type", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Source"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_frame_set_label_widget (GTK_FRAME (frame), combo);
|
||||
|
||||
source_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (frame), source_vbox);
|
||||
gtk_widget_show (source_vbox);
|
||||
|
||||
button = pika_prop_check_button_new (config, "sample-merged", NULL);
|
||||
g_object_set_data (G_OBJECT (tool_options), "sample-merged-checkbox", button);
|
||||
gtk_box_pack_start (GTK_BOX (source_vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property_full (config, "clone-type",
|
||||
button, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
pika_clone_options_sync_source,
|
||||
NULL,
|
||||
GINT_TO_POINTER (PIKA_CLONE_IMAGE), NULL);
|
||||
|
||||
label = gtk_label_new (NULL);
|
||||
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
|
||||
str = g_strdup_printf ("<i>%s</i>", _("No source selected"));
|
||||
gtk_label_set_markup (GTK_LABEL (label), str);
|
||||
g_object_set_data_full (G_OBJECT (tool_options), "src-label",
|
||||
g_object_ref (label),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_free (str);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (source_vbox), label, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property_full (config, "clone-type",
|
||||
label, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
pika_clone_options_sync_source,
|
||||
NULL,
|
||||
GINT_TO_POINTER (PIKA_CLONE_IMAGE), NULL);
|
||||
|
||||
g_signal_connect (pika_get_user_context (PIKA_CONTEXT (tool_options)->pika),
|
||||
"image-changed",
|
||||
G_CALLBACK (pika_clone_options_gui_context_image_changed),
|
||||
tool_options);
|
||||
|
||||
hbox = pika_prop_pattern_box_new (NULL, PIKA_CONTEXT (tool_options),
|
||||
NULL, 2,
|
||||
"pattern-view-type", "pattern-view-size");
|
||||
gtk_box_pack_start (GTK_BOX (source_vbox), hbox, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property_full (config, "clone-type",
|
||||
hbox, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
pika_clone_options_sync_source,
|
||||
NULL,
|
||||
GINT_TO_POINTER (PIKA_CLONE_PATTERN), NULL);
|
||||
|
||||
combo = pika_prop_enum_combo_box_new (config, "align-mode", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Alignment"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0);
|
||||
gtk_box_reorder_child (GTK_BOX (vbox), combo, 3);
|
||||
|
||||
/* A few options which can trigger a change in the source label. */
|
||||
g_signal_connect (config, "notify::src-drawables",
|
||||
G_CALLBACK (pika_clone_options_gui_src_changed),
|
||||
label);
|
||||
g_signal_connect (config, "notify::sample-merged",
|
||||
G_CALLBACK (pika_clone_options_gui_src_changed),
|
||||
label);
|
||||
pika_clone_options_gui_src_changed (PIKA_SOURCE_OPTIONS (config), NULL, label);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
29
app/tools/pikacloneoptions-gui.h
Normal file
29
app/tools/pikacloneoptions-gui.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CLONE_OPTIONS_GUI_H__
|
||||
#define __PIKA_CLONE_OPTIONS_GUI_H__
|
||||
|
||||
|
||||
GtkWidget * pika_clone_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_CLONE_OPTIONS_GUI_H__ */
|
||||
112
app/tools/pikaclonetool.c
Normal file
112
app/tools/pikaclonetool.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "operations/layer-modes/pika-layer-modes.h"
|
||||
|
||||
#include "paint/pikaclone.h"
|
||||
#include "paint/pikacloneoptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
|
||||
#include "pikaclonetool.h"
|
||||
#include "pikacloneoptions-gui.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static gboolean pika_clone_tool_is_alpha_only (PikaPaintTool *paint_tool,
|
||||
PikaDrawable *drawable);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaCloneTool, pika_clone_tool, PIKA_TYPE_SOURCE_TOOL)
|
||||
|
||||
#define parent_class pika_clone_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_clone_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_CLONE_TOOL,
|
||||
PIKA_TYPE_CLONE_OPTIONS,
|
||||
pika_clone_options_gui,
|
||||
PIKA_PAINT_OPTIONS_CONTEXT_MASK |
|
||||
PIKA_CONTEXT_PROP_MASK_PATTERN,
|
||||
"pika-clone-tool",
|
||||
_("Clone"),
|
||||
_("Clone Tool: Selectively copy from an image or pattern, using a brush"),
|
||||
N_("_Clone"), "C",
|
||||
NULL, PIKA_HELP_TOOL_CLONE,
|
||||
PIKA_ICON_TOOL_CLONE,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_clone_tool_class_init (PikaCloneToolClass *klass)
|
||||
{
|
||||
PikaPaintToolClass *paint_tool_class = PIKA_PAINT_TOOL_CLASS (klass);
|
||||
|
||||
paint_tool_class->is_alpha_only = pika_clone_tool_is_alpha_only;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_clone_tool_init (PikaCloneTool *clone)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (clone);
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (tool);
|
||||
PikaSourceTool *source_tool = PIKA_SOURCE_TOOL (tool);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_CLONE);
|
||||
pika_tool_control_set_action_object_2 (tool->control,
|
||||
"context-pattern-select-set");
|
||||
|
||||
paint_tool->status = _("Click to clone");
|
||||
paint_tool->status_ctrl = _("%s to set a new clone source");
|
||||
|
||||
source_tool->status_paint = _("Click to clone");
|
||||
/* Translators: the translation of "Click" must be the first word */
|
||||
source_tool->status_set_source = _("Click to set a new clone source");
|
||||
source_tool->status_set_source_ctrl = _("%s to set a new clone source");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_clone_tool_is_alpha_only (PikaPaintTool *paint_tool,
|
||||
PikaDrawable *drawable)
|
||||
{
|
||||
PikaPaintOptions *paint_options = PIKA_PAINT_TOOL_GET_OPTIONS (paint_tool);
|
||||
PikaContext *context = PIKA_CONTEXT (paint_options);
|
||||
PikaLayerMode paint_mode = pika_context_get_paint_mode (context);
|
||||
|
||||
return pika_layer_mode_is_alpha_only (paint_mode);
|
||||
}
|
||||
57
app/tools/pikaclonetool.h
Normal file
57
app/tools/pikaclonetool.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CLONE_TOOL_H__
|
||||
#define __PIKA_CLONE_TOOL_H__
|
||||
|
||||
|
||||
#include "pikasourcetool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CLONE_TOOL (pika_clone_tool_get_type ())
|
||||
#define PIKA_CLONE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CLONE_TOOL, PikaCloneTool))
|
||||
#define PIKA_CLONE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CLONE_TOOL, PikaCloneToolClass))
|
||||
#define PIKA_IS_CLONE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CLONE_TOOL))
|
||||
#define PIKA_IS_CLONE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CLONE_TOOL))
|
||||
#define PIKA_CLONE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CLONE_TOOL, PikaCloneToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaCloneTool PikaCloneTool;
|
||||
typedef struct _PikaCloneToolClass PikaCloneToolClass;
|
||||
|
||||
struct _PikaCloneTool
|
||||
{
|
||||
PikaSourceTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaCloneToolClass
|
||||
{
|
||||
PikaSourceToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_clone_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_clone_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_CLONE_TOOL_H__ */
|
||||
173
app/tools/pikacoloroptions.c
Normal file
173
app/tools/pikacoloroptions.c
Normal file
@ -0,0 +1,173 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
|
||||
#include "pikacoloroptions.h"
|
||||
#include "pikatooloptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SAMPLE_MERGED,
|
||||
PROP_SAMPLE_AVERAGE,
|
||||
PROP_AVERAGE_RADIUS
|
||||
};
|
||||
|
||||
|
||||
static void pika_color_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_color_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaColorOptions, pika_color_options,
|
||||
PIKA_TYPE_TOOL_OPTIONS)
|
||||
|
||||
|
||||
static void
|
||||
pika_color_options_class_init (PikaColorOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_color_options_set_property;
|
||||
object_class->get_property = pika_color_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_SAMPLE_MERGED,
|
||||
"sample-merged",
|
||||
_("Sample merged"),
|
||||
_("Use merged color value from "
|
||||
"all composited visible layers"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_SAMPLE_AVERAGE,
|
||||
"sample-average",
|
||||
_("Sample average"),
|
||||
_("Use averaged color value from "
|
||||
"nearby pixels"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_AVERAGE_RADIUS,
|
||||
"average-radius",
|
||||
_("Radius"),
|
||||
_("Color Picker Average Radius"),
|
||||
1.0, 300.0, 3.0,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_options_init (PikaColorOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaColorOptions *options = PIKA_COLOR_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_SAMPLE_MERGED:
|
||||
options->sample_merged = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SAMPLE_AVERAGE:
|
||||
options->sample_average = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_AVERAGE_RADIUS:
|
||||
options->average_radius = g_value_get_double (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaColorOptions *options = PIKA_COLOR_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_SAMPLE_MERGED:
|
||||
g_value_set_boolean (value, options->sample_merged);
|
||||
break;
|
||||
case PROP_SAMPLE_AVERAGE:
|
||||
g_value_set_boolean (value, options->sample_average);
|
||||
break;
|
||||
case PROP_AVERAGE_RADIUS:
|
||||
g_value_set_double (value, options->average_radius);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_color_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_tool_options_gui (tool_options);
|
||||
GtkWidget *button;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *scale;
|
||||
|
||||
/* the sample average options */
|
||||
scale = pika_prop_spin_scale_new (config, "average-radius",
|
||||
1.0, 10.0, 0);
|
||||
|
||||
frame = pika_prop_expanding_frame_new (config, "sample-average", NULL,
|
||||
scale, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
|
||||
|
||||
/* The Sample merged checkbox. */
|
||||
button = pika_prop_check_button_new (config, "sample-merged", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
59
app/tools/pikacoloroptions.h
Normal file
59
app/tools/pikacoloroptions.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_COLOR_OPTIONS_H__
|
||||
#define __PIKA_COLOR_OPTIONS_H__
|
||||
|
||||
|
||||
#include "core/pikatooloptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_OPTIONS (pika_color_options_get_type ())
|
||||
#define PIKA_COLOR_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_COLOR_OPTIONS, PikaColorOptions))
|
||||
#define PIKA_COLOR_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_OPTIONS, PikaColorOptionsClass))
|
||||
#define PIKA_IS_COLOR_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_COLOR_OPTIONS))
|
||||
#define PIKA_IS_COLOR_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_OPTIONS))
|
||||
#define PIKA_COLOR_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_OPTIONS, PikaColorOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaColorOptionsClass PikaColorOptionsClass;
|
||||
|
||||
struct _PikaColorOptions
|
||||
{
|
||||
PikaToolOptions parent_instance;
|
||||
|
||||
gboolean sample_merged;
|
||||
gboolean sample_average;
|
||||
gdouble average_radius;
|
||||
};
|
||||
|
||||
struct _PikaColorOptionsClass
|
||||
{
|
||||
PikaToolOptionsClass parent_instance;
|
||||
};
|
||||
|
||||
|
||||
GType pika_color_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_color_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_COLOR_OPTIONS_H__ */
|
||||
209
app/tools/pikacolorpickeroptions.c
Normal file
209
app/tools/pikacolorpickeroptions.c
Normal file
@ -0,0 +1,209 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikacolorpickeroptions.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SAMPLE_AVERAGE, /* overrides a PikaColorOptions property */
|
||||
PROP_PICK_TARGET,
|
||||
PROP_USE_INFO_WINDOW,
|
||||
PROP_FRAME1_MODE,
|
||||
PROP_FRAME2_MODE
|
||||
};
|
||||
|
||||
|
||||
static void pika_color_picker_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_color_picker_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaColorPickerOptions, pika_color_picker_options,
|
||||
PIKA_TYPE_COLOR_OPTIONS)
|
||||
|
||||
|
||||
static void
|
||||
pika_color_picker_options_class_init (PikaColorPickerOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_color_picker_options_set_property;
|
||||
object_class->get_property = pika_color_picker_options_get_property;
|
||||
|
||||
/* override a PikaColorOptions property to get a different default value */
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_SAMPLE_AVERAGE,
|
||||
"sample-average",
|
||||
_("Sample average"),
|
||||
_("Use averaged color value from "
|
||||
"nearby pixels"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_PICK_TARGET,
|
||||
"pick-target",
|
||||
_("Pick Target"),
|
||||
_("Choose what the color picker will do"),
|
||||
PIKA_TYPE_COLOR_PICK_TARGET,
|
||||
PIKA_COLOR_PICK_TARGET_FOREGROUND,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_USE_INFO_WINDOW,
|
||||
"use-info-window",
|
||||
_("Use info window"),
|
||||
_("Open a floating dialog to view picked "
|
||||
"color values in various color models"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FRAME1_MODE,
|
||||
"frame1-mode",
|
||||
"Frame 1 Mode", NULL,
|
||||
PIKA_TYPE_COLOR_PICK_MODE,
|
||||
PIKA_COLOR_PICK_MODE_PIXEL,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FRAME2_MODE,
|
||||
"frame2-mode",
|
||||
"Frame 2 Mode", NULL,
|
||||
PIKA_TYPE_COLOR_PICK_MODE,
|
||||
PIKA_COLOR_PICK_MODE_RGB_PERCENT,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_options_init (PikaColorPickerOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaColorPickerOptions *options = PIKA_COLOR_PICKER_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_SAMPLE_AVERAGE:
|
||||
PIKA_COLOR_OPTIONS (options)->sample_average = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_PICK_TARGET:
|
||||
options->pick_target = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_USE_INFO_WINDOW:
|
||||
options->use_info_window = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_FRAME1_MODE:
|
||||
options->frame1_mode = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_FRAME2_MODE:
|
||||
options->frame2_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaColorPickerOptions *options = PIKA_COLOR_PICKER_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_SAMPLE_AVERAGE:
|
||||
g_value_set_boolean (value,
|
||||
PIKA_COLOR_OPTIONS (options)->sample_average);
|
||||
break;
|
||||
case PROP_PICK_TARGET:
|
||||
g_value_set_enum (value, options->pick_target);
|
||||
break;
|
||||
case PROP_USE_INFO_WINDOW:
|
||||
g_value_set_boolean (value, options->use_info_window);
|
||||
break;
|
||||
case PROP_FRAME1_MODE:
|
||||
g_value_set_enum (value, options->frame1_mode);
|
||||
break;
|
||||
case PROP_FRAME2_MODE:
|
||||
g_value_set_enum (value, options->frame2_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_color_picker_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_color_options_gui (tool_options);
|
||||
GtkWidget *button;
|
||||
GtkWidget *frame;
|
||||
gchar *str;
|
||||
GdkModifierType extend_mask = pika_get_extend_selection_mask ();
|
||||
GdkModifierType toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
/* the pick FG/BG frame */
|
||||
str = g_strdup_printf (_("Pick Target (%s)"),
|
||||
pika_get_mod_string (toggle_mask));
|
||||
frame = pika_prop_enum_radio_frame_new (config, "pick-target", str, -1, -1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
|
||||
g_free (str);
|
||||
|
||||
/* the use_info_window toggle button */
|
||||
str = g_strdup_printf (_("Use info window (%s)"),
|
||||
pika_get_mod_string (extend_mask));
|
||||
button = pika_prop_check_button_new (config, "use-info-window", str);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
g_free (str);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
56
app/tools/pikacolorpickeroptions.h
Normal file
56
app/tools/pikacolorpickeroptions.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_COLOR_PICKER_OPTIONS_H__
|
||||
#define __PIKA_COLOR_PICKER_OPTIONS_H__
|
||||
|
||||
|
||||
#include "pikacoloroptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_PICKER_OPTIONS (pika_color_picker_options_get_type ())
|
||||
#define PIKA_COLOR_PICKER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_COLOR_PICKER_OPTIONS, PikaColorPickerOptions))
|
||||
#define PIKA_COLOR_PICKER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_PICKER_OPTIONS, PikaColorPickerOptionsClass))
|
||||
#define PIKA_IS_COLOR_PICKER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_COLOR_PICKER_OPTIONS))
|
||||
#define PIKA_IS_COLOR_PICKER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_PICKER_OPTIONS))
|
||||
#define PIKA_COLOR_PICKER_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_PICKER_OPTIONS, PikaColorPickerOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaColorPickerOptions PikaColorPickerOptions;
|
||||
typedef struct _PikaToolOptionsClass PikaColorPickerOptionsClass;
|
||||
|
||||
struct _PikaColorPickerOptions
|
||||
{
|
||||
PikaColorOptions parent_instance;
|
||||
|
||||
PikaColorPickTarget pick_target;
|
||||
gboolean use_info_window;
|
||||
PikaColorPickMode frame1_mode;
|
||||
PikaColorPickMode frame2_mode;
|
||||
};
|
||||
|
||||
|
||||
GType pika_color_picker_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_color_picker_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_COLOR_PICKER_OPTIONS_H__ */
|
||||
461
app/tools/pikacolorpickertool.c
Normal file
461
app/tools/pikacolorpickertool.c
Normal file
@ -0,0 +1,461 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikacoreconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikadrawable.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "widgets/pikacolorframe.h"
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikatoolgui.h"
|
||||
|
||||
#include "pikacolorpickeroptions.h"
|
||||
#include "pikacolorpickertool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_color_picker_tool_constructed (GObject *object);
|
||||
static void pika_color_picker_tool_dispose (GObject *object);
|
||||
|
||||
static void pika_color_picker_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_picker_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_picker_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_color_picker_tool_picked (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color);
|
||||
|
||||
static void pika_color_picker_tool_info_create (PikaColorPickerTool *picker_tool,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_picker_tool_info_response (PikaToolGui *gui,
|
||||
gint response_id,
|
||||
PikaColorPickerTool *picker_tool);
|
||||
static void pika_color_picker_tool_info_update (PikaColorPickerTool *picker_tool,
|
||||
PikaDisplay *display,
|
||||
gboolean sample_average,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaColorPickerTool, pika_color_picker_tool,
|
||||
PIKA_TYPE_COLOR_TOOL)
|
||||
|
||||
#define parent_class pika_color_picker_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_color_picker_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_COLOR_PICKER_TOOL,
|
||||
PIKA_TYPE_COLOR_PICKER_OPTIONS,
|
||||
pika_color_picker_options_gui,
|
||||
PIKA_CONTEXT_PROP_MASK_FOREGROUND |
|
||||
PIKA_CONTEXT_PROP_MASK_BACKGROUND,
|
||||
"pika-color-picker-tool",
|
||||
_("Color Picker"),
|
||||
_("Color Picker Tool: Set colors from image pixels"),
|
||||
N_("C_olor Picker"), "O",
|
||||
NULL, PIKA_HELP_TOOL_COLOR_PICKER,
|
||||
PIKA_ICON_TOOL_COLOR_PICKER,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_class_init (PikaColorPickerToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaColorToolClass *color_tool_class = PIKA_COLOR_TOOL_CLASS (klass);
|
||||
|
||||
object_class->constructed = pika_color_picker_tool_constructed;
|
||||
object_class->dispose = pika_color_picker_tool_dispose;
|
||||
|
||||
tool_class->control = pika_color_picker_tool_control;
|
||||
tool_class->modifier_key = pika_color_picker_tool_modifier_key;
|
||||
tool_class->oper_update = pika_color_picker_tool_oper_update;
|
||||
|
||||
color_tool_class->picked = pika_color_picker_tool_picked;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_init (PikaColorPickerTool *picker_tool)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (picker_tool);
|
||||
|
||||
color_tool->pick_target = PIKA_COLOR_PICK_TARGET_FOREGROUND;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_constructed (GObject *object)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (object);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
pika_color_tool_enable (PIKA_COLOR_TOOL (object),
|
||||
PIKA_COLOR_TOOL_GET_OPTIONS (tool));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_dispose (GObject *object)
|
||||
{
|
||||
PikaColorPickerTool *picker_tool = PIKA_COLOR_PICKER_TOOL (object);
|
||||
|
||||
g_clear_object (&picker_tool->gui);
|
||||
picker_tool->color_area = NULL;
|
||||
picker_tool->color_frame1 = NULL;
|
||||
picker_tool->color_frame2 = NULL;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorPickerTool *picker_tool = PIKA_COLOR_PICKER_TOOL (tool);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PIKA_TOOL_ACTION_PAUSE:
|
||||
case PIKA_TOOL_ACTION_RESUME:
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_HALT:
|
||||
if (picker_tool->gui)
|
||||
pika_tool_gui_hide (picker_tool->gui);
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_COMMIT:
|
||||
break;
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->control (tool, action, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorPickerOptions *options = PIKA_COLOR_PICKER_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
if (key == pika_get_extend_selection_mask ())
|
||||
{
|
||||
g_object_set (options, "use-info-window", ! options->use_info_window,
|
||||
NULL);
|
||||
}
|
||||
else if (key == pika_get_toggle_behavior_mask ())
|
||||
{
|
||||
switch (options->pick_target)
|
||||
{
|
||||
case PIKA_COLOR_PICK_TARGET_FOREGROUND:
|
||||
g_object_set (options,
|
||||
"pick-target", PIKA_COLOR_PICK_TARGET_BACKGROUND,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_BACKGROUND:
|
||||
g_object_set (options,
|
||||
"pick-target", PIKA_COLOR_PICK_TARGET_FOREGROUND,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorPickerTool *picker_tool = PIKA_COLOR_PICKER_TOOL (tool);
|
||||
PikaColorPickerOptions *options = PIKA_COLOR_PICKER_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
PIKA_COLOR_TOOL (tool)->pick_target = options->pick_target;
|
||||
|
||||
pika_tool_pop_status (tool, display);
|
||||
|
||||
if (proximity)
|
||||
{
|
||||
gchar *status_help = NULL;
|
||||
GdkModifierType extend_mask = 0;
|
||||
GdkModifierType toggle_mask;
|
||||
|
||||
if (! picker_tool->gui)
|
||||
extend_mask = pika_get_extend_selection_mask ();
|
||||
|
||||
toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
switch (options->pick_target)
|
||||
{
|
||||
case PIKA_COLOR_PICK_TARGET_NONE:
|
||||
status_help = pika_suggest_modifiers (_("Click in any image to view"
|
||||
" its color"),
|
||||
extend_mask & ~state,
|
||||
NULL, NULL, NULL);
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_FOREGROUND:
|
||||
status_help = pika_suggest_modifiers (_("Click in any image to pick"
|
||||
" the foreground color"),
|
||||
(extend_mask | toggle_mask) &
|
||||
~state,
|
||||
NULL, NULL, NULL);
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_BACKGROUND:
|
||||
status_help = pika_suggest_modifiers (_("Click in any image to pick"
|
||||
" the background color"),
|
||||
(extend_mask | toggle_mask) &
|
||||
~state,
|
||||
NULL, NULL, NULL);
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_PALETTE:
|
||||
status_help = pika_suggest_modifiers (_("Click in any image to add"
|
||||
" the color to the palette"),
|
||||
extend_mask & ~state,
|
||||
NULL, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status_help != NULL)
|
||||
{
|
||||
pika_tool_push_status (tool, display, "%s", status_help);
|
||||
g_free (status_help);
|
||||
}
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_picked (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color)
|
||||
{
|
||||
PikaColorPickerTool *picker_tool = PIKA_COLOR_PICKER_TOOL (color_tool);
|
||||
PikaColorPickerOptions *options;
|
||||
|
||||
options = PIKA_COLOR_PICKER_TOOL_GET_OPTIONS (color_tool);
|
||||
|
||||
if (options->use_info_window && ! picker_tool->gui)
|
||||
pika_color_picker_tool_info_create (picker_tool, display);
|
||||
|
||||
if (picker_tool->gui &&
|
||||
(options->use_info_window ||
|
||||
pika_tool_gui_get_visible (picker_tool->gui)))
|
||||
{
|
||||
pika_color_picker_tool_info_update (picker_tool, display,
|
||||
PIKA_COLOR_OPTIONS (options)->sample_average,
|
||||
sample_format, pixel, color,
|
||||
(gint) floor (coords->x),
|
||||
(gint) floor (coords->y));
|
||||
}
|
||||
|
||||
PIKA_COLOR_TOOL_CLASS (parent_class)->picked (color_tool,
|
||||
coords, display, pick_state,
|
||||
sample_format, pixel, color);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_info_create (PikaColorPickerTool *picker_tool,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
Pika *pika = pika_display_get_pika (display);
|
||||
PikaTool *tool = PIKA_TOOL (picker_tool);
|
||||
PikaToolOptions *options = PIKA_TOOL_GET_OPTIONS (tool);
|
||||
PikaContext *context = PIKA_CONTEXT (tool->tool_info->tool_options);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
GList *drawables = pika_image_get_selected_drawables (image);
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *frame;
|
||||
PikaRGB color;
|
||||
|
||||
picker_tool->gui = pika_tool_gui_new (tool->tool_info,
|
||||
NULL,
|
||||
_("Color Picker Information"),
|
||||
NULL, NULL,
|
||||
pika_widget_get_monitor (GTK_WIDGET (shell)),
|
||||
TRUE,
|
||||
|
||||
_("_Close"), GTK_RESPONSE_CLOSE,
|
||||
|
||||
NULL);
|
||||
|
||||
pika_tool_gui_set_auto_overlay (picker_tool->gui, TRUE);
|
||||
pika_tool_gui_set_focus_on_map (picker_tool->gui, FALSE);
|
||||
pika_tool_gui_set_viewables (picker_tool->gui, drawables);
|
||||
|
||||
g_signal_connect (picker_tool->gui, "response",
|
||||
G_CALLBACK (pika_color_picker_tool_info_response),
|
||||
picker_tool);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (pika_tool_gui_get_vbox (picker_tool->gui)),
|
||||
hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
picker_tool->color_frame1 = pika_color_frame_new (pika);
|
||||
pika_color_frame_set_color_config (PIKA_COLOR_FRAME (picker_tool->color_frame1),
|
||||
context->pika->config->color_management);
|
||||
pika_color_frame_set_has_coords (PIKA_COLOR_FRAME (picker_tool->color_frame1),
|
||||
TRUE);
|
||||
g_object_bind_property (options, "frame1-mode",
|
||||
picker_tool->color_frame1, "mode",
|
||||
G_BINDING_BIDIRECTIONAL |
|
||||
G_BINDING_SYNC_CREATE);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), picker_tool->color_frame1,
|
||||
FALSE, FALSE, 0);
|
||||
gtk_widget_show (picker_tool->color_frame1);
|
||||
|
||||
picker_tool->color_frame2 = pika_color_frame_new (pika);
|
||||
pika_color_frame_set_color_config (PIKA_COLOR_FRAME (picker_tool->color_frame2),
|
||||
context->pika->config->color_management);
|
||||
g_object_bind_property (options, "frame2-mode",
|
||||
picker_tool->color_frame2, "mode",
|
||||
G_BINDING_BIDIRECTIONAL |
|
||||
G_BINDING_SYNC_CREATE);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), picker_tool->color_frame2,
|
||||
FALSE, FALSE, 0);
|
||||
gtk_widget_show (picker_tool->color_frame2);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
pika_widget_set_fully_opaque (frame, TRUE);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
pika_rgba_set (&color, 0.0, 0.0, 0.0, 0.0);
|
||||
picker_tool->color_area =
|
||||
pika_color_area_new (&color,
|
||||
drawables && pika_drawable_has_alpha (drawables->data) ?
|
||||
PIKA_COLOR_AREA_LARGE_CHECKS :
|
||||
PIKA_COLOR_AREA_FLAT,
|
||||
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK);
|
||||
pika_color_area_set_color_config (PIKA_COLOR_AREA (picker_tool->color_area),
|
||||
context->pika->config->color_management);
|
||||
gtk_widget_set_size_request (picker_tool->color_area, 48, -1);
|
||||
gtk_drag_dest_unset (picker_tool->color_area);
|
||||
gtk_container_add (GTK_CONTAINER (frame), picker_tool->color_area);
|
||||
gtk_widget_show (picker_tool->color_area);
|
||||
|
||||
g_list_free (drawables);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_info_response (PikaToolGui *gui,
|
||||
gint response_id,
|
||||
PikaColorPickerTool *picker_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (picker_tool);
|
||||
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_picker_tool_info_update (PikaColorPickerTool *picker_tool,
|
||||
PikaDisplay *display,
|
||||
gboolean sample_average,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (picker_tool);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
GList *drawables = pika_image_get_selected_drawables (image);
|
||||
|
||||
tool->display = display;
|
||||
|
||||
pika_tool_gui_set_shell (picker_tool->gui,
|
||||
pika_display_get_shell (display));
|
||||
pika_tool_gui_set_viewables (picker_tool->gui, drawables);
|
||||
g_list_free (drawables);
|
||||
|
||||
pika_color_area_set_color (PIKA_COLOR_AREA (picker_tool->color_area),
|
||||
color);
|
||||
|
||||
pika_color_frame_set_color (PIKA_COLOR_FRAME (picker_tool->color_frame1),
|
||||
sample_average, sample_format, pixel, color,
|
||||
x, y);
|
||||
pika_color_frame_set_color (PIKA_COLOR_FRAME (picker_tool->color_frame2),
|
||||
sample_average, sample_format, pixel, color,
|
||||
x, y);
|
||||
|
||||
pika_tool_gui_show (picker_tool->gui);
|
||||
}
|
||||
64
app/tools/pikacolorpickertool.h
Normal file
64
app/tools/pikacolorpickertool.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_COLOR_PICKER_TOOL_H__
|
||||
#define __PIKA_COLOR_PICKER_TOOL_H__
|
||||
|
||||
|
||||
#include "pikacolortool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_PICKER_TOOL (pika_color_picker_tool_get_type ())
|
||||
#define PIKA_COLOR_PICKER_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_COLOR_PICKER_TOOL, PikaColorPickerTool))
|
||||
#define PIKA_COLOR_PICKER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_PICKER_TOOL, PikaColorPickerToolClass))
|
||||
#define PIKA_IS_COLOR_PICKER_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_COLOR_PICKER_TOOL))
|
||||
#define PIKA_IS_COLOR_PICKER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_PICKER_TOOL))
|
||||
#define PIKA_COLOR_PICKER_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_PICKER_TOOL, PikaColorPickerToolClass))
|
||||
|
||||
#define PIKA_COLOR_PICKER_TOOL_GET_OPTIONS(t) (PIKA_COLOR_PICKER_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaColorPickerTool PikaColorPickerTool;
|
||||
typedef struct _PikaColorPickerToolClass PikaColorPickerToolClass;
|
||||
|
||||
struct _PikaColorPickerTool
|
||||
{
|
||||
PikaColorTool parent_instance;
|
||||
|
||||
PikaToolGui *gui;
|
||||
GtkWidget *color_area;
|
||||
GtkWidget *color_frame1;
|
||||
GtkWidget *color_frame2;
|
||||
};
|
||||
|
||||
struct _PikaColorPickerToolClass
|
||||
{
|
||||
PikaColorToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_color_picker_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_color_picker_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_COLOR_PICKER_TOOL_H__ */
|
||||
704
app/tools/pikacolortool.c
Normal file
704
app/tools/pikacolortool.c
Normal file
@ -0,0 +1,704 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikadisplayconfig.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikadata.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-pick-color.h"
|
||||
#include "core/pikaimage-pick-item.h"
|
||||
#include "core/pikaimage-sample-points.h"
|
||||
#include "core/pikamarshal.h"
|
||||
#include "core/pikasamplepoint.h"
|
||||
|
||||
#include "widgets/pikacolormapeditor.h"
|
||||
#include "widgets/pikadialogfactory.h"
|
||||
#include "widgets/pikadockable.h"
|
||||
#include "widgets/pikadockcontainer.h"
|
||||
#include "widgets/pikapaletteeditor.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
#include "widgets/pikawindowstrategy.h"
|
||||
|
||||
#include "display/pikacanvasitem.h"
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikadisplayshell.h"
|
||||
#include "display/pikadisplayshell-appearance.h"
|
||||
|
||||
#include "pikacoloroptions.h"
|
||||
#include "pikacolortool.h"
|
||||
#include "pikasamplepointtool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PICKED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_color_tool_finalize (GObject *object);
|
||||
|
||||
static void pika_color_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_color_tool_draw (PikaDrawTool *draw_tool);
|
||||
|
||||
static gboolean
|
||||
pika_color_tool_real_can_pick (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display);
|
||||
static gboolean pika_color_tool_real_pick (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
const Babl **sample_format,
|
||||
gpointer pixel,
|
||||
PikaRGB *color);
|
||||
static void pika_color_tool_real_picked (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color);
|
||||
|
||||
static gboolean pika_color_tool_can_pick (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display);
|
||||
static void pika_color_tool_pick (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaColorTool, pika_color_tool, PIKA_TYPE_DRAW_TOOL)
|
||||
|
||||
#define parent_class pika_color_tool_parent_class
|
||||
|
||||
static guint pika_color_tool_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
static void
|
||||
pika_color_tool_class_init (PikaColorToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaDrawToolClass *draw_class = PIKA_DRAW_TOOL_CLASS (klass);
|
||||
|
||||
pika_color_tool_signals[PICKED] =
|
||||
g_signal_new ("picked",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (PikaColorToolClass, picked),
|
||||
NULL, NULL,
|
||||
pika_marshal_VOID__POINTER_OBJECT_ENUM_POINTER_POINTER_BOXED,
|
||||
G_TYPE_NONE, 6,
|
||||
G_TYPE_POINTER,
|
||||
PIKA_TYPE_DISPLAY,
|
||||
PIKA_TYPE_COLOR_PICK_STATE,
|
||||
G_TYPE_POINTER,
|
||||
G_TYPE_POINTER,
|
||||
PIKA_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE);
|
||||
|
||||
object_class->finalize = pika_color_tool_finalize;
|
||||
|
||||
tool_class->button_press = pika_color_tool_button_press;
|
||||
tool_class->button_release = pika_color_tool_button_release;
|
||||
tool_class->motion = pika_color_tool_motion;
|
||||
tool_class->oper_update = pika_color_tool_oper_update;
|
||||
tool_class->cursor_update = pika_color_tool_cursor_update;
|
||||
|
||||
draw_class->draw = pika_color_tool_draw;
|
||||
|
||||
klass->can_pick = pika_color_tool_real_can_pick;
|
||||
klass->pick = pika_color_tool_real_pick;
|
||||
klass->picked = pika_color_tool_real_picked;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_init (PikaColorTool *color_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (color_tool);
|
||||
|
||||
pika_tool_control_set_action_size (tool->control,
|
||||
"tools-color-average-radius-set");
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_finalize (GObject *object)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (object);
|
||||
|
||||
g_clear_object (&color_tool->options);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (tool);
|
||||
|
||||
if (color_tool->enabled)
|
||||
{
|
||||
if (color_tool->sample_point)
|
||||
{
|
||||
pika_sample_point_tool_start_edit (tool, display,
|
||||
color_tool->sample_point);
|
||||
}
|
||||
else if (pika_color_tool_can_pick (color_tool, coords, display))
|
||||
{
|
||||
pika_color_tool_pick (color_tool, coords, display,
|
||||
PIKA_COLOR_PICK_STATE_START);
|
||||
|
||||
pika_tool_control_activate (tool->control);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
||||
press_type, display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (tool);
|
||||
|
||||
if (color_tool->enabled)
|
||||
{
|
||||
pika_tool_control_halt (tool->control);
|
||||
|
||||
if (! color_tool->sample_point &&
|
||||
pika_color_tool_can_pick (color_tool, coords, display))
|
||||
{
|
||||
pika_color_tool_pick (color_tool, coords, display,
|
||||
PIKA_COLOR_PICK_STATE_END);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state,
|
||||
release_type, display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (tool);
|
||||
|
||||
if (color_tool->enabled)
|
||||
{
|
||||
if (! color_tool->sample_point)
|
||||
{
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
color_tool->can_pick = pika_color_tool_can_pick (color_tool,
|
||||
coords, display);
|
||||
color_tool->center_x = coords->x;
|
||||
color_tool->center_y = coords->y;
|
||||
|
||||
if (color_tool->can_pick)
|
||||
{
|
||||
pika_color_tool_pick (color_tool, coords, display,
|
||||
PIKA_COLOR_PICK_STATE_UPDATE);
|
||||
}
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->motion (tool, coords, time, state,
|
||||
display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (tool);
|
||||
|
||||
if (color_tool->enabled)
|
||||
{
|
||||
PikaDrawTool *draw_tool = PIKA_DRAW_TOOL (tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaSamplePoint *sample_point = NULL;
|
||||
|
||||
pika_draw_tool_pause (draw_tool);
|
||||
|
||||
if (! draw_tool->widget &&
|
||||
|
||||
pika_draw_tool_is_active (draw_tool) &&
|
||||
(draw_tool->display != display ||
|
||||
! proximity))
|
||||
{
|
||||
pika_draw_tool_stop (draw_tool);
|
||||
}
|
||||
|
||||
if (pika_display_shell_get_show_sample_points (shell) &&
|
||||
proximity)
|
||||
{
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
gint snap_distance = display->config->snap_distance;
|
||||
|
||||
sample_point =
|
||||
pika_image_pick_sample_point (image,
|
||||
coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance));
|
||||
}
|
||||
|
||||
color_tool->sample_point = sample_point;
|
||||
|
||||
color_tool->can_pick = pika_color_tool_can_pick (color_tool,
|
||||
coords, display);
|
||||
color_tool->center_x = coords->x;
|
||||
color_tool->center_y = coords->y;
|
||||
|
||||
if (! draw_tool->widget &&
|
||||
|
||||
! pika_draw_tool_is_active (draw_tool) &&
|
||||
proximity)
|
||||
{
|
||||
pika_draw_tool_start (draw_tool, display);
|
||||
}
|
||||
|
||||
pika_draw_tool_resume (draw_tool);
|
||||
}
|
||||
else
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
|
||||
proximity, display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (tool);
|
||||
|
||||
if (color_tool->enabled)
|
||||
{
|
||||
if (color_tool->sample_point)
|
||||
{
|
||||
pika_tool_set_cursor (tool, display,
|
||||
PIKA_CURSOR_MOUSE,
|
||||
PIKA_TOOL_CURSOR_COLOR_PICKER,
|
||||
PIKA_CURSOR_MODIFIER_MOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
PikaCursorModifier modifier = PIKA_CURSOR_MODIFIER_BAD;
|
||||
|
||||
if (pika_color_tool_can_pick (color_tool, coords, display))
|
||||
{
|
||||
switch (color_tool->pick_target)
|
||||
{
|
||||
case PIKA_COLOR_PICK_TARGET_NONE:
|
||||
modifier = PIKA_CURSOR_MODIFIER_NONE;
|
||||
break;
|
||||
case PIKA_COLOR_PICK_TARGET_FOREGROUND:
|
||||
modifier = PIKA_CURSOR_MODIFIER_FOREGROUND;
|
||||
break;
|
||||
case PIKA_COLOR_PICK_TARGET_BACKGROUND:
|
||||
modifier = PIKA_CURSOR_MODIFIER_BACKGROUND;
|
||||
break;
|
||||
case PIKA_COLOR_PICK_TARGET_PALETTE:
|
||||
modifier = PIKA_CURSOR_MODIFIER_PLUS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pika_tool_set_cursor (tool, display,
|
||||
PIKA_CURSOR_COLOR_PICKER,
|
||||
PIKA_TOOL_CURSOR_COLOR_PICKER,
|
||||
modifier);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state,
|
||||
display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_draw (PikaDrawTool *draw_tool)
|
||||
{
|
||||
PikaColorTool *color_tool = PIKA_COLOR_TOOL (draw_tool);
|
||||
|
||||
PIKA_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
|
||||
|
||||
if (color_tool->enabled)
|
||||
{
|
||||
if (color_tool->sample_point)
|
||||
{
|
||||
PikaImage *image = pika_display_get_image (draw_tool->display);
|
||||
PikaCanvasItem *item;
|
||||
gint index;
|
||||
gint x;
|
||||
gint y;
|
||||
|
||||
pika_sample_point_get_position (color_tool->sample_point, &x, &y);
|
||||
|
||||
index = g_list_index (pika_image_get_sample_points (image),
|
||||
color_tool->sample_point) + 1;
|
||||
|
||||
item = pika_draw_tool_add_sample_point (draw_tool, x, y, index);
|
||||
pika_canvas_item_set_highlight (item, TRUE);
|
||||
}
|
||||
else if (color_tool->can_pick && color_tool->options->sample_average)
|
||||
{
|
||||
gdouble radius = color_tool->options->average_radius;
|
||||
|
||||
pika_draw_tool_add_rectangle (draw_tool,
|
||||
FALSE,
|
||||
color_tool->center_x - radius,
|
||||
color_tool->center_y - radius,
|
||||
2 * radius + 1,
|
||||
2 * radius + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_color_tool_real_can_pick (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
|
||||
return pika_image_coords_in_active_pickable (image, coords,
|
||||
shell->show_all,
|
||||
color_tool->options->sample_merged,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_color_tool_real_pick (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
const Babl **sample_format,
|
||||
gpointer pixel,
|
||||
PikaRGB *color)
|
||||
{
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
GList *drawables = pika_image_get_selected_drawables (image);
|
||||
|
||||
g_return_val_if_fail (drawables != NULL, FALSE);
|
||||
|
||||
return pika_image_pick_color (image, drawables,
|
||||
coords->x, coords->y,
|
||||
shell->show_all,
|
||||
color_tool->options->sample_merged,
|
||||
color_tool->options->sample_average,
|
||||
color_tool->options->average_radius,
|
||||
sample_format,
|
||||
pixel,
|
||||
color);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_real_picked (PikaColorTool *color_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (color_tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImageWindow *image_window;
|
||||
PikaDialogFactory *dialog_factory;
|
||||
PikaContext *context;
|
||||
|
||||
image_window = pika_display_shell_get_window (shell);
|
||||
dialog_factory = pika_dock_container_get_dialog_factory (PIKA_DOCK_CONTAINER (image_window));
|
||||
|
||||
/* use this tool's own options here (NOT color_tool->options) */
|
||||
context = PIKA_CONTEXT (pika_tool_get_options (tool));
|
||||
|
||||
if (color_tool->pick_target == PIKA_COLOR_PICK_TARGET_FOREGROUND ||
|
||||
color_tool->pick_target == PIKA_COLOR_PICK_TARGET_BACKGROUND)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = pika_dialog_factory_find_widget (dialog_factory,
|
||||
"pika-indexed-palette");
|
||||
if (widget)
|
||||
{
|
||||
GtkWidget *editor = gtk_bin_get_child (GTK_BIN (widget));
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
|
||||
if (babl_format_is_palette (sample_format))
|
||||
{
|
||||
guchar *index = pixel;
|
||||
|
||||
pika_colormap_editor_set_index (PIKA_COLORMAP_EDITOR (editor),
|
||||
*index, NULL);
|
||||
}
|
||||
else if (pika_image_get_base_type (image) == PIKA_INDEXED)
|
||||
{
|
||||
/* When Sample merged is set, we don't have the index
|
||||
* information and it is possible to pick colors out of
|
||||
* the colormap (with compositing). In such a case, the
|
||||
* sample format will not be a palette format even though
|
||||
* the image is indexed. Still search if the color exists
|
||||
* in the colormap.
|
||||
* Note that even if it does, we might still pick the
|
||||
* wrong color, since several indexes may contain the same
|
||||
* color and we can't know for sure which is the right
|
||||
* one.
|
||||
*/
|
||||
gint index = pika_colormap_editor_get_index (PIKA_COLORMAP_EDITOR (editor),
|
||||
color);
|
||||
if (index > -1)
|
||||
pika_colormap_editor_set_index (PIKA_COLORMAP_EDITOR (editor),
|
||||
index, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
widget = pika_dialog_factory_find_widget (dialog_factory,
|
||||
"pika-palette-editor");
|
||||
if (widget)
|
||||
{
|
||||
GtkWidget *editor = gtk_bin_get_child (GTK_BIN (widget));
|
||||
gint index;
|
||||
|
||||
index = pika_palette_editor_get_index (PIKA_PALETTE_EDITOR (editor),
|
||||
color);
|
||||
if (index != -1)
|
||||
pika_palette_editor_set_index (PIKA_PALETTE_EDITOR (editor),
|
||||
index, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
switch (color_tool->pick_target)
|
||||
{
|
||||
case PIKA_COLOR_PICK_TARGET_NONE:
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_FOREGROUND:
|
||||
pika_context_set_foreground (context, color);
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_BACKGROUND:
|
||||
pika_context_set_background (context, color);
|
||||
break;
|
||||
|
||||
case PIKA_COLOR_PICK_TARGET_PALETTE:
|
||||
{
|
||||
GdkMonitor *monitor = pika_widget_get_monitor (GTK_WIDGET (shell));
|
||||
GtkWidget *dockable;
|
||||
|
||||
dockable =
|
||||
pika_window_strategy_show_dockable_dialog (PIKA_WINDOW_STRATEGY (pika_get_window_strategy (display->pika)),
|
||||
display->pika,
|
||||
dialog_factory,
|
||||
monitor,
|
||||
"pika-palette-editor");
|
||||
|
||||
if (dockable)
|
||||
{
|
||||
GtkWidget *palette_editor;
|
||||
PikaData *data;
|
||||
|
||||
/* don't blink like mad when updating */
|
||||
if (pick_state != PIKA_COLOR_PICK_STATE_START)
|
||||
pika_widget_blink_cancel (dockable);
|
||||
|
||||
palette_editor = gtk_bin_get_child (GTK_BIN (dockable));
|
||||
|
||||
data = pika_data_editor_get_data (PIKA_DATA_EDITOR (palette_editor));
|
||||
|
||||
if (! data)
|
||||
{
|
||||
data = PIKA_DATA (pika_context_get_palette (context));
|
||||
|
||||
pika_data_editor_set_data (PIKA_DATA_EDITOR (palette_editor),
|
||||
data);
|
||||
}
|
||||
|
||||
pika_palette_editor_pick_color (PIKA_PALETTE_EDITOR (palette_editor),
|
||||
color, pick_state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_color_tool_can_pick (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaColorToolClass *klass;
|
||||
|
||||
klass = PIKA_COLOR_TOOL_GET_CLASS (tool);
|
||||
|
||||
return klass->can_pick && klass->can_pick (tool, coords, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_color_tool_pick (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state)
|
||||
{
|
||||
PikaColorToolClass *klass;
|
||||
const Babl *sample_format;
|
||||
gdouble pixel[4];
|
||||
PikaRGB color;
|
||||
|
||||
klass = PIKA_COLOR_TOOL_GET_CLASS (tool);
|
||||
|
||||
if (klass->pick &&
|
||||
klass->pick (tool, coords, display, &sample_format, pixel, &color))
|
||||
{
|
||||
g_signal_emit (tool, pika_color_tool_signals[PICKED], 0,
|
||||
coords, display, pick_state,
|
||||
sample_format, pixel, &color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_color_tool_enable (PikaColorTool *color_tool,
|
||||
PikaColorOptions *options)
|
||||
{
|
||||
PikaTool *tool;
|
||||
|
||||
g_return_if_fail (PIKA_IS_COLOR_TOOL (color_tool));
|
||||
g_return_if_fail (PIKA_IS_COLOR_OPTIONS (options));
|
||||
|
||||
tool = PIKA_TOOL (color_tool);
|
||||
|
||||
if (pika_tool_control_is_active (tool->control))
|
||||
{
|
||||
g_warning ("Trying to enable PikaColorTool while it is active.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_set_object (&color_tool->options, options);
|
||||
|
||||
/* color picking doesn't snap, see bug #768058 */
|
||||
color_tool->saved_snap_to = pika_tool_control_get_snap_to (tool->control);
|
||||
pika_tool_control_set_snap_to (tool->control, FALSE);
|
||||
|
||||
color_tool->enabled = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
pika_color_tool_disable (PikaColorTool *color_tool)
|
||||
{
|
||||
PikaTool *tool;
|
||||
|
||||
g_return_if_fail (PIKA_IS_COLOR_TOOL (color_tool));
|
||||
|
||||
tool = PIKA_TOOL (color_tool);
|
||||
|
||||
if (pika_tool_control_is_active (tool->control))
|
||||
{
|
||||
g_warning ("Trying to disable PikaColorTool while it is active.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_object (&color_tool->options);
|
||||
|
||||
pika_tool_control_set_snap_to (tool->control, color_tool->saved_snap_to);
|
||||
color_tool->saved_snap_to = FALSE;
|
||||
|
||||
color_tool->enabled = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_color_tool_is_enabled (PikaColorTool *color_tool)
|
||||
{
|
||||
return color_tool->enabled;
|
||||
}
|
||||
91
app/tools/pikacolortool.h
Normal file
91
app/tools/pikacolortool.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_COLOR_TOOL_H__
|
||||
#define __PIKA_COLOR_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_COLOR_TOOL (pika_color_tool_get_type ())
|
||||
#define PIKA_COLOR_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_COLOR_TOOL, PikaColorTool))
|
||||
#define PIKA_COLOR_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_COLOR_TOOL, PikaColorToolClass))
|
||||
#define PIKA_IS_COLOR_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_COLOR_TOOL))
|
||||
#define PIKA_IS_COLOR_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_COLOR_TOOL))
|
||||
#define PIKA_COLOR_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_COLOR_TOOL, PikaColorToolClass))
|
||||
|
||||
#define PIKA_COLOR_TOOL_GET_OPTIONS(t) (PIKA_COLOR_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaColorToolClass PikaColorToolClass;
|
||||
|
||||
struct _PikaColorTool
|
||||
{
|
||||
PikaDrawTool parent_instance;
|
||||
|
||||
gboolean enabled;
|
||||
PikaColorOptions *options;
|
||||
gboolean saved_snap_to;
|
||||
|
||||
PikaColorPickTarget pick_target;
|
||||
|
||||
gboolean can_pick;
|
||||
gint center_x;
|
||||
gint center_y;
|
||||
PikaSamplePoint *sample_point;
|
||||
};
|
||||
|
||||
struct _PikaColorToolClass
|
||||
{
|
||||
PikaDrawToolClass parent_class;
|
||||
|
||||
/* virtual functions */
|
||||
gboolean (* can_pick) (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display);
|
||||
gboolean (* pick) (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
const Babl **sample_format,
|
||||
gpointer pixel,
|
||||
PikaRGB *color);
|
||||
|
||||
/* signals */
|
||||
void (* picked) (PikaColorTool *tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display,
|
||||
PikaColorPickState pick_state,
|
||||
const Babl *sample_format,
|
||||
gpointer pixel,
|
||||
const PikaRGB *color);
|
||||
};
|
||||
|
||||
|
||||
GType pika_color_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_color_tool_enable (PikaColorTool *color_tool,
|
||||
PikaColorOptions *options);
|
||||
void pika_color_tool_disable (PikaColorTool *color_tool);
|
||||
gboolean pika_color_tool_is_enabled (PikaColorTool *color_tool);
|
||||
|
||||
|
||||
#endif /* __PIKA_COLOR_TOOL_H__ */
|
||||
232
app/tools/pikaconvolvetool.c
Normal file
232
app/tools/pikaconvolvetool.c
Normal file
@ -0,0 +1,232 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "paint/pikaconvolveoptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikaconvolvetool.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_convolve_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_convolve_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_convolve_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
static void pika_convolve_tool_status_update (PikaTool *tool,
|
||||
PikaConvolveType type);
|
||||
|
||||
static GtkWidget * pika_convolve_options_gui (PikaToolOptions *options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaConvolveTool, pika_convolve_tool, PIKA_TYPE_BRUSH_TOOL)
|
||||
|
||||
#define parent_class pika_convolve_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_convolve_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_CONVOLVE_TOOL,
|
||||
PIKA_TYPE_CONVOLVE_OPTIONS,
|
||||
pika_convolve_options_gui,
|
||||
PIKA_PAINT_OPTIONS_CONTEXT_MASK,
|
||||
"pika-convolve-tool",
|
||||
_("Blur / Sharpen"),
|
||||
_("Blur / Sharpen Tool: Selective blurring or unblurring using a brush"),
|
||||
N_("Bl_ur / Sharpen"), "<shift>U",
|
||||
NULL, PIKA_HELP_TOOL_CONVOLVE,
|
||||
PIKA_ICON_TOOL_BLUR,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_convolve_tool_class_init (PikaConvolveToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->modifier_key = pika_convolve_tool_modifier_key;
|
||||
tool_class->cursor_update = pika_convolve_tool_cursor_update;
|
||||
tool_class->oper_update = pika_convolve_tool_oper_update;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_convolve_tool_init (PikaConvolveTool *convolve)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (convolve);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_BLUR);
|
||||
pika_tool_control_set_toggle_cursor_modifier (tool->control,
|
||||
PIKA_CURSOR_MODIFIER_MINUS);
|
||||
|
||||
pika_convolve_tool_status_update (tool, PIKA_CONVOLVE_BLUR);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_convolve_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaConvolveTool *convolve = PIKA_CONVOLVE_TOOL (tool);
|
||||
PikaConvolveOptions *options = PIKA_CONVOLVE_TOOL_GET_OPTIONS (tool);
|
||||
GdkModifierType line_mask = PIKA_PAINT_TOOL_LINE_MASK;
|
||||
GdkModifierType toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
if (((key == toggle_mask) &&
|
||||
! (state & line_mask) && /* leave stuff untouched in line draw mode */
|
||||
press != convolve->toggled)
|
||||
|
||||
||
|
||||
|
||||
(key == line_mask && /* toggle back after keypresses CTRL(hold)-> */
|
||||
! press && /* SHIFT(hold)->CTRL(release)->SHIFT(release) */
|
||||
convolve->toggled &&
|
||||
! (state & toggle_mask)))
|
||||
{
|
||||
convolve->toggled = press;
|
||||
|
||||
switch (options->type)
|
||||
{
|
||||
case PIKA_CONVOLVE_BLUR:
|
||||
g_object_set (options, "type", PIKA_CONVOLVE_SHARPEN, NULL);
|
||||
break;
|
||||
|
||||
case PIKA_CONVOLVE_SHARPEN:
|
||||
g_object_set (options, "type", PIKA_CONVOLVE_BLUR, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_convolve_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaConvolveOptions *options = PIKA_CONVOLVE_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
pika_tool_control_set_toggled (tool->control,
|
||||
options->type == PIKA_CONVOLVE_SHARPEN);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_convolve_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaConvolveOptions *options = PIKA_CONVOLVE_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
pika_convolve_tool_status_update (tool, options->type);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_convolve_tool_status_update (PikaTool *tool,
|
||||
PikaConvolveType type)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (tool);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PIKA_CONVOLVE_BLUR:
|
||||
paint_tool->status = _("Click to blur");
|
||||
paint_tool->status_line = _("Click to blur the line");
|
||||
paint_tool->status_ctrl = _("%s to sharpen");
|
||||
break;
|
||||
|
||||
case PIKA_CONVOLVE_SHARPEN:
|
||||
paint_tool->status = _("Click to sharpen");
|
||||
paint_tool->status_line = _("Click to sharpen the line");
|
||||
paint_tool->status_ctrl = _("%s to blur");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* tool options stuff */
|
||||
|
||||
static GtkWidget *
|
||||
pika_convolve_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *frame;
|
||||
GtkWidget *scale;
|
||||
gchar *str;
|
||||
GdkModifierType toggle_mask;
|
||||
|
||||
toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
/* the type radio box */
|
||||
str = g_strdup_printf (_("Convolve Type (%s)"),
|
||||
pika_get_mod_string (toggle_mask));
|
||||
|
||||
frame = pika_prop_enum_radio_frame_new (config, "type",
|
||||
str, 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
g_free (str);
|
||||
|
||||
/* the rate scale */
|
||||
scale = pika_prop_spin_scale_new (config, "rate",
|
||||
1.0, 10.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
61
app/tools/pikaconvolvetool.h
Normal file
61
app/tools/pikaconvolvetool.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CONVOLVE_TOOL_H__
|
||||
#define __PIKA_CONVOLVE_TOOL_H__
|
||||
|
||||
|
||||
#include "pikabrushtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CONVOLVE_TOOL (pika_convolve_tool_get_type ())
|
||||
#define PIKA_CONVOLVE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CONVOLVE_TOOL, PikaConvolveTool))
|
||||
#define PIKA_CONVOLVE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CONVOLVE_TOOL, PikaConvolveToolClass))
|
||||
#define PIKA_IS_CONVOLVE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CONVOLVE_TOOL))
|
||||
#define PIKA_IS_CONVOLVE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CONVOLVE_TOOL))
|
||||
#define PIKA_CONVOLVE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CONVOLVE_TOOL, PikaConvolveToolClass))
|
||||
|
||||
#define PIKA_CONVOLVE_TOOL_GET_OPTIONS(t) (PIKA_CONVOLVE_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaConvolveTool PikaConvolveTool;
|
||||
typedef struct _PikaConvolveToolClass PikaConvolveToolClass;
|
||||
|
||||
struct _PikaConvolveTool
|
||||
{
|
||||
PikaBrushTool parent_instance;
|
||||
|
||||
gboolean toggled;
|
||||
};
|
||||
|
||||
struct _PikaConvolveToolClass
|
||||
{
|
||||
PikaBrushToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_convolve_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_convolve_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_CONVOLVE_TOOL_H__ */
|
||||
243
app/tools/pikacropoptions.c
Normal file
243
app/tools/pikacropoptions.c
Normal file
@ -0,0 +1,243 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikarectangleoptions.h"
|
||||
#include "pikacropoptions.h"
|
||||
#include "pikatooloptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_LAYER_ONLY = PIKA_RECTANGLE_OPTIONS_PROP_LAST + 1,
|
||||
PROP_ALLOW_GROWING,
|
||||
PROP_FILL_TYPE,
|
||||
PROP_DELETE_PIXELS
|
||||
};
|
||||
|
||||
|
||||
static void pika_crop_options_rectangle_options_iface_init (PikaRectangleOptionsInterface *iface);
|
||||
|
||||
static void pika_crop_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_crop_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (PikaCropOptions, pika_crop_options,
|
||||
PIKA_TYPE_TOOL_OPTIONS,
|
||||
G_IMPLEMENT_INTERFACE (PIKA_TYPE_RECTANGLE_OPTIONS,
|
||||
pika_crop_options_rectangle_options_iface_init))
|
||||
|
||||
|
||||
static void
|
||||
pika_crop_options_class_init (PikaCropOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_crop_options_set_property;
|
||||
object_class->get_property = pika_crop_options_get_property;
|
||||
|
||||
/* The 'highlight' property is defined here because we want different
|
||||
* default values for the Crop and the Rectangle Select tools.
|
||||
*/
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class,
|
||||
PIKA_RECTANGLE_OPTIONS_PROP_HIGHLIGHT,
|
||||
"highlight",
|
||||
_("Highlight"),
|
||||
_("Dim everything outside selection"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class,
|
||||
PIKA_RECTANGLE_OPTIONS_PROP_HIGHLIGHT_OPACITY,
|
||||
"highlight-opacity",
|
||||
_("Highlight opacity"),
|
||||
_("How much to dim everything outside selection"),
|
||||
0.0, 1.0, 0.5,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_ONLY,
|
||||
"layer-only",
|
||||
_("Selected layers only"),
|
||||
_("Crop only currently selected layers"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_DELETE_PIXELS,
|
||||
"delete-pixels",
|
||||
_("Delete cropped pixels"),
|
||||
_("Discard non-locked layer data that falls out of the crop region"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_ALLOW_GROWING,
|
||||
"allow-growing",
|
||||
_("Allow growing"),
|
||||
_("Allow resizing canvas by dragging cropping frame "
|
||||
"beyond image boundary"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FILL_TYPE,
|
||||
"fill-type",
|
||||
_("Fill with"),
|
||||
_("How to fill new areas created by 'Allow growing'"),
|
||||
PIKA_TYPE_FILL_TYPE,
|
||||
PIKA_FILL_TRANSPARENT,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
pika_rectangle_options_install_properties (object_class);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_options_init (PikaCropOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_options_rectangle_options_iface_init (PikaRectangleOptionsInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaCropOptions *options = PIKA_CROP_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_LAYER_ONLY:
|
||||
options->layer_only = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_DELETE_PIXELS:
|
||||
options->delete_pixels = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_ALLOW_GROWING:
|
||||
options->allow_growing = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_FILL_TYPE:
|
||||
options->fill_type = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
pika_rectangle_options_set_property (object, property_id, value, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaCropOptions *options = PIKA_CROP_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_LAYER_ONLY:
|
||||
g_value_set_boolean (value, options->layer_only);
|
||||
break;
|
||||
|
||||
case PROP_DELETE_PIXELS:
|
||||
g_value_set_boolean (value, options->delete_pixels);
|
||||
break;
|
||||
|
||||
case PROP_ALLOW_GROWING:
|
||||
g_value_set_boolean (value, options->allow_growing);
|
||||
break;
|
||||
|
||||
case PROP_FILL_TYPE:
|
||||
g_value_set_enum (value, options->fill_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
pika_rectangle_options_get_property (object, property_id, value, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_crop_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_tool_options_gui (tool_options);
|
||||
GtkWidget *vbox_rectangle;
|
||||
GtkWidget *button;
|
||||
GtkWidget *button2;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *frame;
|
||||
|
||||
/* layer toggle */
|
||||
button = pika_prop_check_button_new (config, "layer-only", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
/* delete pixels toggle */
|
||||
button2 = pika_prop_check_button_new (config, "delete-pixels", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button2, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property (G_OBJECT (config), "layer-only",
|
||||
G_OBJECT (button2), "sensitive",
|
||||
G_BINDING_SYNC_CREATE |
|
||||
G_BINDING_INVERT_BOOLEAN);
|
||||
|
||||
/* fill type combo */
|
||||
combo = pika_prop_enum_combo_box_new (config, "fill-type", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Fill with"));
|
||||
|
||||
/* allow growing toggle/frame */
|
||||
frame = pika_prop_expanding_frame_new (config, "allow-growing", NULL,
|
||||
combo, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* rectangle options */
|
||||
vbox_rectangle = pika_rectangle_options_gui (tool_options);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), vbox_rectangle, FALSE, FALSE, 0);
|
||||
gtk_widget_show (vbox_rectangle);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
65
app/tools/pikacropoptions.h
Normal file
65
app/tools/pikacropoptions.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CROP_OPTIONS_H__
|
||||
#define __PIKA_CROP_OPTIONS_H__
|
||||
|
||||
|
||||
#include "core/pikatooloptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CROP_OPTIONS (pika_crop_options_get_type ())
|
||||
#define PIKA_CROP_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CROP_OPTIONS, PikaCropOptions))
|
||||
#define PIKA_CROP_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CROP_OPTIONS, PikaCropOptionsClass))
|
||||
#define PIKA_IS_CROP_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CROP_OPTIONS))
|
||||
#define PIKA_IS_CROP_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CROP_OPTIONS))
|
||||
#define PIKA_CROP_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CROP_OPTIONS, PikaCropOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaCropOptions PikaCropOptions;
|
||||
typedef struct _PikaToolOptionsClass PikaCropOptionsClass;
|
||||
|
||||
struct _PikaCropOptions
|
||||
{
|
||||
PikaToolOptions parent_instance;
|
||||
|
||||
/* Work on the current layer rather than the image. */
|
||||
gboolean layer_only;
|
||||
|
||||
/* Allow the crop rectangle to be larger than the image/layer. This
|
||||
* will resize the image/layer.
|
||||
*/
|
||||
gboolean allow_growing;
|
||||
|
||||
/* How to fill new areas created by 'allow_growing. */
|
||||
PikaFillType fill_type;
|
||||
|
||||
/* Whether to discard layer data that falls out of the crop region */
|
||||
gboolean delete_pixels;
|
||||
};
|
||||
|
||||
|
||||
GType pika_crop_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_crop_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_CROP_OPTIONS_H__ */
|
||||
752
app/tools/pikacroptool.c
Normal file
752
app/tools/pikacroptool.c
Normal file
@ -0,0 +1,752 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-crop.h"
|
||||
#include "core/pikaimage-undo.h"
|
||||
#include "core/pikaitem.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikadisplayshell.h"
|
||||
#include "display/pikatoolrectangle.h"
|
||||
|
||||
#include "pikacropoptions.h"
|
||||
#include "pikacroptool.h"
|
||||
#include "pikarectangleoptions.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
#include "pikatools-utils.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_crop_tool_constructed (GObject *object);
|
||||
static void pika_crop_tool_dispose (GObject *object);
|
||||
|
||||
static void pika_crop_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display);
|
||||
static void pika_crop_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_crop_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_crop_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_crop_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
static void pika_crop_tool_rectangle_changed (PikaToolWidget *rectangle,
|
||||
PikaCropTool *crop_tool);
|
||||
static void pika_crop_tool_rectangle_response (PikaToolWidget *rectangle,
|
||||
gint response_id,
|
||||
PikaCropTool *crop_tool);
|
||||
static void pika_crop_tool_rectangle_change_complete (PikaToolRectangle *rectangle,
|
||||
PikaCropTool *crop_tool);
|
||||
|
||||
static void pika_crop_tool_start (PikaCropTool *crop_tool,
|
||||
PikaDisplay *display);
|
||||
static void pika_crop_tool_commit (PikaCropTool *crop_tool);
|
||||
static void pika_crop_tool_halt (PikaCropTool *crop_tool);
|
||||
|
||||
static void pika_crop_tool_update_option_defaults (PikaCropTool *crop_tool,
|
||||
gboolean ignore_pending);
|
||||
static PikaRectangleConstraint
|
||||
pika_crop_tool_get_constraint (PikaCropTool *crop_tool);
|
||||
|
||||
static void pika_crop_tool_image_changed (PikaCropTool *crop_tool,
|
||||
PikaImage *image,
|
||||
PikaContext *context);
|
||||
static void pika_crop_tool_image_size_changed (PikaCropTool *crop_tool);
|
||||
static void pika_crop_tool_image_selected_layers_changed (PikaCropTool *crop_tool);
|
||||
static void pika_crop_tool_layer_size_changed (PikaCropTool *crop_tool);
|
||||
|
||||
static void pika_crop_tool_auto_shrink (PikaCropTool *crop_tool);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaCropTool, pika_crop_tool, PIKA_TYPE_DRAW_TOOL)
|
||||
|
||||
#define parent_class pika_crop_tool_parent_class
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_crop_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_CROP_TOOL,
|
||||
PIKA_TYPE_CROP_OPTIONS,
|
||||
pika_crop_options_gui,
|
||||
PIKA_CONTEXT_PROP_MASK_FOREGROUND |
|
||||
PIKA_CONTEXT_PROP_MASK_BACKGROUND |
|
||||
PIKA_CONTEXT_PROP_MASK_PATTERN,
|
||||
"pika-crop-tool",
|
||||
_("Crop"),
|
||||
_("Crop Tool: Remove edge areas from image or layer"),
|
||||
N_("_Crop"), "<shift>C",
|
||||
NULL, PIKA_HELP_TOOL_CROP,
|
||||
PIKA_ICON_TOOL_CROP,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_class_init (PikaCropToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
|
||||
object_class->constructed = pika_crop_tool_constructed;
|
||||
object_class->dispose = pika_crop_tool_dispose;
|
||||
|
||||
tool_class->control = pika_crop_tool_control;
|
||||
tool_class->button_press = pika_crop_tool_button_press;
|
||||
tool_class->button_release = pika_crop_tool_button_release;
|
||||
tool_class->motion = pika_crop_tool_motion;
|
||||
tool_class->options_notify = pika_crop_tool_options_notify;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_init (PikaCropTool *crop_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (crop_tool);
|
||||
|
||||
pika_tool_control_set_wants_click (tool->control, TRUE);
|
||||
pika_tool_control_set_active_modifiers (tool->control,
|
||||
PIKA_TOOL_ACTIVE_MODIFIERS_SEPARATE);
|
||||
pika_tool_control_set_precision (tool->control,
|
||||
PIKA_CURSOR_PRECISION_PIXEL_BORDER);
|
||||
pika_tool_control_set_cursor (tool->control,
|
||||
PIKA_CURSOR_CROSSHAIR_SMALL);
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_CROP);
|
||||
|
||||
pika_draw_tool_set_default_status (PIKA_DRAW_TOOL (tool),
|
||||
_("Click-Drag to draw a crop rectangle"));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_constructed (GObject *object)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (object);
|
||||
PikaContext *context;
|
||||
PikaToolInfo *tool_info;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
tool_info = PIKA_TOOL (crop_tool)->tool_info;
|
||||
|
||||
context = pika_get_user_context (tool_info->pika);
|
||||
|
||||
g_signal_connect_object (context, "image-changed",
|
||||
G_CALLBACK (pika_crop_tool_image_changed),
|
||||
crop_tool,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
/* Make sure we are connected to "size-changed" for the initial
|
||||
* image.
|
||||
*/
|
||||
pika_crop_tool_image_changed (crop_tool,
|
||||
pika_context_get_image (context),
|
||||
context);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_dispose (GObject *object)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (object);
|
||||
|
||||
/* Clean up current_image and current_layers. */
|
||||
pika_crop_tool_image_changed (crop_tool, NULL, NULL);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (tool);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PIKA_TOOL_ACTION_PAUSE:
|
||||
case PIKA_TOOL_ACTION_RESUME:
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_HALT:
|
||||
pika_crop_tool_halt (crop_tool);
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_COMMIT:
|
||||
pika_crop_tool_commit (crop_tool);
|
||||
break;
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->control (tool, action, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (tool);
|
||||
|
||||
if (tool->display && display != tool->display)
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, tool->display);
|
||||
|
||||
if (! tool->display)
|
||||
{
|
||||
pika_crop_tool_start (crop_tool, display);
|
||||
|
||||
pika_tool_widget_hover (crop_tool->widget, coords, state, TRUE);
|
||||
|
||||
/* HACK: force CREATING on a newly created rectangle; otherwise,
|
||||
* property bindings would cause the rectangle to start with the
|
||||
* size from tool options.
|
||||
*/
|
||||
pika_tool_rectangle_set_function (PIKA_TOOL_RECTANGLE (crop_tool->widget),
|
||||
PIKA_TOOL_RECTANGLE_CREATING);
|
||||
}
|
||||
|
||||
if (pika_tool_widget_button_press (crop_tool->widget, coords, time, state,
|
||||
press_type))
|
||||
{
|
||||
crop_tool->grab_widget = crop_tool->widget;
|
||||
}
|
||||
|
||||
pika_tool_control_activate (tool->control);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (tool);
|
||||
|
||||
pika_tool_control_halt (tool->control);
|
||||
|
||||
if (crop_tool->grab_widget)
|
||||
{
|
||||
pika_tool_widget_button_release (crop_tool->grab_widget,
|
||||
coords, time, state, release_type);
|
||||
crop_tool->grab_widget = NULL;
|
||||
}
|
||||
|
||||
pika_tool_push_status (tool, display, _("Click or press Enter to crop"));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (tool);
|
||||
|
||||
if (crop_tool->grab_widget)
|
||||
{
|
||||
pika_tool_widget_motion (crop_tool->grab_widget, coords, time, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec)
|
||||
{
|
||||
PikaCropTool *crop_tool = PIKA_CROP_TOOL (tool);
|
||||
|
||||
if (! strcmp (pspec->name, "layer-only") ||
|
||||
! strcmp (pspec->name, "allow-growing"))
|
||||
{
|
||||
if (crop_tool->widget)
|
||||
{
|
||||
pika_tool_rectangle_set_constraint (PIKA_TOOL_RECTANGLE (crop_tool->widget),
|
||||
pika_crop_tool_get_constraint (crop_tool));
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_crop_tool_update_option_defaults (crop_tool, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_rectangle_changed (PikaToolWidget *rectangle,
|
||||
PikaCropTool *crop_tool)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_rectangle_response (PikaToolWidget *rectangle,
|
||||
gint response_id,
|
||||
PikaCropTool *crop_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (crop_tool);
|
||||
|
||||
switch (response_id)
|
||||
{
|
||||
case PIKA_TOOL_WIDGET_RESPONSE_CONFIRM:
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_COMMIT, tool->display);
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_WIDGET_RESPONSE_CANCEL:
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, tool->display);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_rectangle_change_complete (PikaToolRectangle *rectangle,
|
||||
PikaCropTool *crop_tool)
|
||||
{
|
||||
pika_crop_tool_update_option_defaults (crop_tool, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_start (PikaCropTool *crop_tool,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
static const gchar *properties[] =
|
||||
{
|
||||
"highlight",
|
||||
"highlight-opacity",
|
||||
"guide",
|
||||
"x",
|
||||
"y",
|
||||
"width",
|
||||
"height",
|
||||
"fixed-rule-active",
|
||||
"fixed-rule",
|
||||
"desired-fixed-width",
|
||||
"desired-fixed-height",
|
||||
"desired-fixed-size-width",
|
||||
"desired-fixed-size-height",
|
||||
"aspect-numerator",
|
||||
"aspect-denominator",
|
||||
"fixed-center"
|
||||
};
|
||||
|
||||
PikaTool *tool = PIKA_TOOL (crop_tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaCropOptions *options = PIKA_CROP_TOOL_GET_OPTIONS (crop_tool);
|
||||
PikaToolWidget *widget;
|
||||
gint i;
|
||||
|
||||
tool->display = display;
|
||||
|
||||
crop_tool->widget = widget = pika_tool_rectangle_new (shell);
|
||||
|
||||
g_object_set (widget,
|
||||
"status-title", _("Crop to: "),
|
||||
NULL);
|
||||
|
||||
pika_draw_tool_set_widget (PIKA_DRAW_TOOL (tool), widget);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (properties); i++)
|
||||
{
|
||||
GBinding *binding =
|
||||
g_object_bind_property (G_OBJECT (options), properties[i],
|
||||
G_OBJECT (widget), properties[i],
|
||||
G_BINDING_SYNC_CREATE |
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
|
||||
crop_tool->bindings = g_list_prepend (crop_tool->bindings, binding);
|
||||
}
|
||||
|
||||
pika_rectangle_options_connect (PIKA_RECTANGLE_OPTIONS (options),
|
||||
pika_display_get_image (shell->display),
|
||||
G_CALLBACK (pika_crop_tool_auto_shrink),
|
||||
crop_tool);
|
||||
|
||||
pika_tool_rectangle_set_constraint (PIKA_TOOL_RECTANGLE (widget),
|
||||
pika_crop_tool_get_constraint (crop_tool));
|
||||
|
||||
g_signal_connect (widget, "changed",
|
||||
G_CALLBACK (pika_crop_tool_rectangle_changed),
|
||||
crop_tool);
|
||||
g_signal_connect (widget, "response",
|
||||
G_CALLBACK (pika_crop_tool_rectangle_response),
|
||||
crop_tool);
|
||||
g_signal_connect (widget, "change-complete",
|
||||
G_CALLBACK (pika_crop_tool_rectangle_change_complete),
|
||||
crop_tool);
|
||||
|
||||
pika_draw_tool_start (PIKA_DRAW_TOOL (tool), display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_commit (PikaCropTool *crop_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (crop_tool);
|
||||
|
||||
if (tool->display)
|
||||
{
|
||||
PikaCropOptions *options = PIKA_CROP_TOOL_GET_OPTIONS (tool);
|
||||
PikaImage *image = pika_display_get_image (tool->display);
|
||||
gdouble x, y;
|
||||
gdouble x2, y2;
|
||||
gint w, h;
|
||||
|
||||
pika_tool_rectangle_get_public_rect (PIKA_TOOL_RECTANGLE (crop_tool->widget),
|
||||
&x, &y, &x2, &y2);
|
||||
w = x2 - x;
|
||||
h = y2 - y;
|
||||
|
||||
pika_tool_pop_status (tool, tool->display);
|
||||
|
||||
/* if rectangle exists, crop it */
|
||||
if (w > 0 && h > 0)
|
||||
{
|
||||
if (options->layer_only)
|
||||
{
|
||||
GList *layers = pika_image_get_selected_layers (image);
|
||||
GList *iter;
|
||||
gint off_x, off_y;
|
||||
gchar *undo_text;
|
||||
|
||||
if (! layers)
|
||||
{
|
||||
pika_tool_message_literal (tool, tool->display,
|
||||
_("There are no selected layers to crop."));
|
||||
return;
|
||||
}
|
||||
|
||||
for (iter = layers; iter; iter = iter->next)
|
||||
if (! pika_item_is_content_locked (PIKA_ITEM (iter->data), NULL))
|
||||
break;
|
||||
|
||||
if (iter == NULL)
|
||||
{
|
||||
pika_tool_message_literal (tool, tool->display,
|
||||
_("All selected layers' pixels are locked."));
|
||||
pika_tools_blink_lock_box (tool->display->pika, PIKA_ITEM (layers->data));
|
||||
return;
|
||||
}
|
||||
|
||||
undo_text = ngettext ("Resize Layer", "Resize %d layers",
|
||||
g_list_length (layers));
|
||||
undo_text = g_strdup_printf (undo_text, g_list_length (layers));
|
||||
pika_image_undo_group_start (image,
|
||||
PIKA_UNDO_GROUP_IMAGE_CROP,
|
||||
undo_text);
|
||||
g_free (undo_text);
|
||||
for (iter = layers; iter; iter = iter->next)
|
||||
{
|
||||
pika_item_get_offset (PIKA_ITEM (iter->data), &off_x, &off_y);
|
||||
|
||||
off_x -= x;
|
||||
off_y -= y;
|
||||
|
||||
pika_item_resize (PIKA_ITEM (iter->data),
|
||||
PIKA_CONTEXT (options), options->fill_type,
|
||||
w, h, off_x, off_y);
|
||||
}
|
||||
pika_image_undo_group_end (image);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_image_crop (image,
|
||||
PIKA_CONTEXT (options), PIKA_FILL_TRANSPARENT,
|
||||
x, y, w, h, options->delete_pixels);
|
||||
}
|
||||
|
||||
pika_image_flush (image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_halt (PikaCropTool *crop_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (crop_tool);
|
||||
PikaCropOptions *options = PIKA_CROP_TOOL_GET_OPTIONS (crop_tool);
|
||||
|
||||
if (tool->display)
|
||||
{
|
||||
PikaDisplayShell *shell = pika_display_get_shell (tool->display);
|
||||
|
||||
pika_display_shell_set_highlight (shell, NULL, 0.0);
|
||||
|
||||
pika_rectangle_options_disconnect (PIKA_RECTANGLE_OPTIONS (options),
|
||||
G_CALLBACK (pika_crop_tool_auto_shrink),
|
||||
crop_tool);
|
||||
}
|
||||
|
||||
if (pika_draw_tool_is_active (PIKA_DRAW_TOOL (tool)))
|
||||
pika_draw_tool_stop (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
/* disconnect bindings manually so they are really gone *now*, we
|
||||
* might be in the middle of a signal emission that keeps the
|
||||
* widget and its bindings alive.
|
||||
*/
|
||||
g_list_free_full (crop_tool->bindings, (GDestroyNotify) g_object_unref);
|
||||
crop_tool->bindings = NULL;
|
||||
|
||||
pika_draw_tool_set_widget (PIKA_DRAW_TOOL (tool), NULL);
|
||||
g_clear_object (&crop_tool->widget);
|
||||
|
||||
tool->display = NULL;
|
||||
g_list_free (tool->drawables);
|
||||
tool->drawables = NULL;
|
||||
|
||||
pika_crop_tool_update_option_defaults (crop_tool, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_crop_tool_update_option_defaults:
|
||||
* @crop_tool:
|
||||
* @ignore_pending: %TRUE to ignore any pending crop rectangle.
|
||||
*
|
||||
* Sets the default Fixed: Aspect ratio and Fixed: Size option
|
||||
* properties.
|
||||
*/
|
||||
static void
|
||||
pika_crop_tool_update_option_defaults (PikaCropTool *crop_tool,
|
||||
gboolean ignore_pending)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (crop_tool);
|
||||
PikaToolRectangle *rectangle = PIKA_TOOL_RECTANGLE (crop_tool->widget);
|
||||
PikaRectangleOptions *options;
|
||||
|
||||
options = PIKA_RECTANGLE_OPTIONS (PIKA_TOOL_GET_OPTIONS (tool));
|
||||
|
||||
if (rectangle && ! ignore_pending)
|
||||
{
|
||||
/* There is a pending rectangle and we should not ignore it, so
|
||||
* set default Fixed: Aspect ratio to the same as the current
|
||||
* pending rectangle width/height.
|
||||
*/
|
||||
|
||||
pika_tool_rectangle_pending_size_set (rectangle,
|
||||
G_OBJECT (options),
|
||||
"default-aspect-numerator",
|
||||
"default-aspect-denominator");
|
||||
|
||||
g_object_set (G_OBJECT (options),
|
||||
"use-string-current", TRUE,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no pending rectangle, set default Fixed: Aspect
|
||||
* ratio to that of the current image/layer.
|
||||
*/
|
||||
|
||||
if (! rectangle)
|
||||
{
|
||||
/* ugly hack: if we don't have a widget, construct a temporary one
|
||||
* so that we can use it to call
|
||||
* pika_tool_rectangle_constraint_size_set().
|
||||
*/
|
||||
|
||||
PikaContext *context = pika_get_user_context (tool->tool_info->pika);
|
||||
PikaDisplay *display = pika_context_get_display (context);
|
||||
|
||||
if (display)
|
||||
{
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
|
||||
rectangle = PIKA_TOOL_RECTANGLE (pika_tool_rectangle_new (shell));
|
||||
|
||||
pika_tool_rectangle_set_constraint (
|
||||
rectangle, pika_crop_tool_get_constraint (crop_tool));
|
||||
}
|
||||
}
|
||||
|
||||
if (rectangle)
|
||||
{
|
||||
pika_tool_rectangle_constraint_size_set (rectangle,
|
||||
G_OBJECT (options),
|
||||
"default-aspect-numerator",
|
||||
"default-aspect-denominator");
|
||||
|
||||
if (! crop_tool->widget)
|
||||
g_object_unref (rectangle);
|
||||
}
|
||||
|
||||
g_object_set (G_OBJECT (options),
|
||||
"use-string-current", FALSE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static PikaRectangleConstraint
|
||||
pika_crop_tool_get_constraint (PikaCropTool *crop_tool)
|
||||
{
|
||||
PikaCropOptions *crop_options = PIKA_CROP_TOOL_GET_OPTIONS (crop_tool);
|
||||
|
||||
if (crop_options->allow_growing)
|
||||
{
|
||||
return PIKA_RECTANGLE_CONSTRAIN_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return crop_options->layer_only ? PIKA_RECTANGLE_CONSTRAIN_DRAWABLE :
|
||||
PIKA_RECTANGLE_CONSTRAIN_IMAGE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_image_changed (PikaCropTool *crop_tool,
|
||||
PikaImage *image,
|
||||
PikaContext *context)
|
||||
{
|
||||
if (crop_tool->current_image)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (crop_tool->current_image,
|
||||
pika_crop_tool_image_size_changed,
|
||||
NULL);
|
||||
g_signal_handlers_disconnect_by_func (crop_tool->current_image,
|
||||
pika_crop_tool_image_selected_layers_changed,
|
||||
NULL);
|
||||
}
|
||||
|
||||
g_set_weak_pointer (&crop_tool->current_image, image);
|
||||
|
||||
if (crop_tool->current_image)
|
||||
{
|
||||
g_signal_connect_object (crop_tool->current_image, "size-changed",
|
||||
G_CALLBACK (pika_crop_tool_image_size_changed),
|
||||
crop_tool,
|
||||
G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (crop_tool->current_image, "selected-layers-changed",
|
||||
G_CALLBACK (pika_crop_tool_image_selected_layers_changed),
|
||||
crop_tool,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
/* Make sure we are connected to "size-changed" for the initial
|
||||
* layer.
|
||||
*/
|
||||
pika_crop_tool_image_selected_layers_changed (crop_tool);
|
||||
|
||||
pika_crop_tool_update_option_defaults (PIKA_CROP_TOOL (crop_tool), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_image_size_changed (PikaCropTool *crop_tool)
|
||||
{
|
||||
pika_crop_tool_update_option_defaults (crop_tool, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_image_selected_layers_changed (PikaCropTool *crop_tool)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
if (crop_tool->current_layers)
|
||||
{
|
||||
for (iter = crop_tool->current_layers; iter; iter = iter->next)
|
||||
{
|
||||
if (iter->data)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (iter->data,
|
||||
pika_crop_tool_layer_size_changed,
|
||||
NULL);
|
||||
|
||||
g_clear_weak_pointer (&iter->data);
|
||||
}
|
||||
}
|
||||
g_list_free (crop_tool->current_layers);
|
||||
crop_tool->current_layers = NULL;
|
||||
}
|
||||
|
||||
if (crop_tool->current_image)
|
||||
{
|
||||
crop_tool->current_layers = pika_image_get_selected_layers (crop_tool->current_image);
|
||||
crop_tool->current_layers = g_list_copy (crop_tool->current_layers);
|
||||
}
|
||||
else
|
||||
{
|
||||
crop_tool->current_layers = NULL;
|
||||
}
|
||||
|
||||
if (crop_tool->current_layers)
|
||||
{
|
||||
for (iter = crop_tool->current_layers; iter; iter = iter->next)
|
||||
{
|
||||
/* NOT g_set_weak_pointer() because the pointer is already set */
|
||||
g_object_add_weak_pointer (G_OBJECT (iter->data),
|
||||
(gpointer) &iter->data);
|
||||
|
||||
g_signal_connect_object (iter->data, "size-changed",
|
||||
G_CALLBACK (pika_crop_tool_layer_size_changed),
|
||||
crop_tool,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
}
|
||||
|
||||
pika_crop_tool_update_option_defaults (crop_tool, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_layer_size_changed (PikaCropTool *crop_tool)
|
||||
{
|
||||
pika_crop_tool_update_option_defaults (crop_tool, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_crop_tool_auto_shrink (PikaCropTool *crop_tool)
|
||||
{
|
||||
gboolean shrink_merged ;
|
||||
|
||||
g_object_get (pika_tool_get_options (PIKA_TOOL (crop_tool)),
|
||||
"shrink-merged", &shrink_merged,
|
||||
NULL);
|
||||
|
||||
pika_tool_rectangle_auto_shrink (PIKA_TOOL_RECTANGLE (crop_tool->widget),
|
||||
shrink_merged);
|
||||
}
|
||||
66
app/tools/pikacroptool.h
Normal file
66
app/tools/pikacroptool.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CROP_TOOL_H__
|
||||
#define __PIKA_CROP_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CROP_TOOL (pika_crop_tool_get_type ())
|
||||
#define PIKA_CROP_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CROP_TOOL, PikaCropTool))
|
||||
#define PIKA_CROP_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CROP_TOOL, PikaCropToolClass))
|
||||
#define PIKA_IS_CROP_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CROP_TOOL))
|
||||
#define PIKA_IS_CROP_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CROP_TOOL))
|
||||
#define PIKA_CROP_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_CROP_TOOL, PikaCropToolClass))
|
||||
|
||||
#define PIKA_CROP_TOOL_GET_OPTIONS(t) (PIKA_CROP_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaCropTool PikaCropTool;
|
||||
typedef struct _PikaCropToolClass PikaCropToolClass;
|
||||
|
||||
struct _PikaCropTool
|
||||
{
|
||||
PikaDrawTool parent_instance;
|
||||
|
||||
PikaImage *current_image;
|
||||
GList *current_layers;
|
||||
|
||||
PikaToolWidget *widget;
|
||||
PikaToolWidget *grab_widget;
|
||||
GList *bindings;
|
||||
};
|
||||
|
||||
struct _PikaCropToolClass
|
||||
{
|
||||
PikaDrawToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_crop_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_crop_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_CROP_TOOL_H__ */
|
||||
1177
app/tools/pikacurvestool.c
Normal file
1177
app/tools/pikacurvestool.c
Normal file
File diff suppressed because it is too large
Load Diff
73
app/tools/pikacurvestool.h
Normal file
73
app/tools/pikacurvestool.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_CURVES_TOOL_H__
|
||||
#define __PIKA_CURVES_TOOL_H__
|
||||
|
||||
|
||||
#include "pikafiltertool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_CURVES_TOOL (pika_curves_tool_get_type ())
|
||||
#define PIKA_CURVES_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_CURVES_TOOL, PikaCurvesTool))
|
||||
#define PIKA_IS_CURVES_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_CURVES_TOOL))
|
||||
#define PIKA_CURVES_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_CURVES_TOOL, PikaCurvesToolClass))
|
||||
#define PIKA_IS_CURVES_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_CURVES_TOOL))
|
||||
|
||||
|
||||
typedef struct _PikaCurvesTool PikaCurvesTool;
|
||||
typedef struct _PikaCurvesToolClass PikaCurvesToolClass;
|
||||
|
||||
struct _PikaCurvesTool
|
||||
{
|
||||
PikaFilterTool parent_instance;
|
||||
|
||||
/* dialog */
|
||||
gdouble scale;
|
||||
gdouble picked_color[5];
|
||||
|
||||
GtkWidget *channel_menu;
|
||||
GtkWidget *xrange;
|
||||
GtkWidget *yrange;
|
||||
GtkWidget *graph;
|
||||
GtkWidget *point_box;
|
||||
GtkWidget *point_input;
|
||||
GtkWidget *point_output;
|
||||
GtkWidget *point_type;
|
||||
GtkWidget *curve_type;
|
||||
|
||||
/* export dialog */
|
||||
gboolean export_old_format;
|
||||
};
|
||||
|
||||
struct _PikaCurvesToolClass
|
||||
{
|
||||
PikaFilterToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_curves_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_curves_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_CURVES_TOOL_H__ */
|
||||
242
app/tools/pikadodgeburntool.c
Normal file
242
app/tools/pikadodgeburntool.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "paint/pikadodgeburnoptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikadodgeburntool.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_dodge_burn_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_dodge_burn_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_dodge_burn_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
static void pika_dodge_burn_tool_status_update (PikaTool *tool,
|
||||
PikaDodgeBurnType type);
|
||||
|
||||
static GtkWidget * pika_dodge_burn_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaDodgeBurnTool, pika_dodge_burn_tool, PIKA_TYPE_BRUSH_TOOL)
|
||||
|
||||
#define parent_class pika_dodge_burn_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_dodge_burn_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_DODGE_BURN_TOOL,
|
||||
PIKA_TYPE_DODGE_BURN_OPTIONS,
|
||||
pika_dodge_burn_options_gui,
|
||||
PIKA_PAINT_OPTIONS_CONTEXT_MASK,
|
||||
"pika-dodge-burn-tool",
|
||||
_("Dodge / Burn"),
|
||||
_("Dodge / Burn Tool: Selectively lighten or darken using a brush"),
|
||||
N_("Dod_ge / Burn"), "<shift>D",
|
||||
NULL, PIKA_HELP_TOOL_DODGE_BURN,
|
||||
PIKA_ICON_TOOL_DODGE,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_dodge_burn_tool_class_init (PikaDodgeBurnToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->modifier_key = pika_dodge_burn_tool_modifier_key;
|
||||
tool_class->cursor_update = pika_dodge_burn_tool_cursor_update;
|
||||
tool_class->oper_update = pika_dodge_burn_tool_oper_update;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_dodge_burn_tool_init (PikaDodgeBurnTool *dodgeburn)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (dodgeburn);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_DODGE);
|
||||
pika_tool_control_set_toggle_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_BURN);
|
||||
|
||||
pika_dodge_burn_tool_status_update (tool, PIKA_DODGE_BURN_TYPE_BURN);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_dodge_burn_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaDodgeBurnTool *dodgeburn = PIKA_DODGE_BURN_TOOL (tool);
|
||||
PikaDodgeBurnOptions *options = PIKA_DODGE_BURN_TOOL_GET_OPTIONS (tool);
|
||||
GdkModifierType line_mask = PIKA_PAINT_TOOL_LINE_MASK;
|
||||
GdkModifierType toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
if ((key == toggle_mask &&
|
||||
! (state & line_mask) && /* leave stuff untouched in line draw mode */
|
||||
press != dodgeburn->toggled)
|
||||
|
||||
||
|
||||
|
||||
(key == line_mask && /* toggle back after keypresses CTRL(hold)-> */
|
||||
! press && /* SHIFT(hold)->CTRL(release)->SHIFT(release) */
|
||||
dodgeburn->toggled &&
|
||||
! (state & toggle_mask)))
|
||||
{
|
||||
dodgeburn->toggled = press;
|
||||
|
||||
switch (options->type)
|
||||
{
|
||||
case PIKA_DODGE_BURN_TYPE_DODGE:
|
||||
g_object_set (options, "type", PIKA_DODGE_BURN_TYPE_BURN, NULL);
|
||||
break;
|
||||
|
||||
case PIKA_DODGE_BURN_TYPE_BURN:
|
||||
g_object_set (options, "type", PIKA_DODGE_BURN_TYPE_DODGE, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->modifier_key (tool, key, press, state,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_dodge_burn_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaDodgeBurnOptions *options = PIKA_DODGE_BURN_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
pika_tool_control_set_toggled (tool->control,
|
||||
options->type == PIKA_DODGE_BURN_TYPE_BURN);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_dodge_burn_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaDodgeBurnOptions *options = PIKA_DODGE_BURN_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
pika_dodge_burn_tool_status_update (tool, options->type);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, proximity,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_dodge_burn_tool_status_update (PikaTool *tool,
|
||||
PikaDodgeBurnType type)
|
||||
{
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (tool);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PIKA_DODGE_BURN_TYPE_DODGE:
|
||||
paint_tool->status = _("Click to dodge");
|
||||
paint_tool->status_line = _("Click to dodge the line");
|
||||
paint_tool->status_ctrl = _("%s to burn");
|
||||
break;
|
||||
|
||||
case PIKA_DODGE_BURN_TYPE_BURN:
|
||||
paint_tool->status = _("Click to burn");
|
||||
paint_tool->status_line = _("Click to burn the line");
|
||||
paint_tool->status_ctrl = _("%s to dodge");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* tool options stuff */
|
||||
|
||||
static GtkWidget *
|
||||
pika_dodge_burn_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *frame;
|
||||
GtkWidget *scale;
|
||||
gchar *str;
|
||||
GdkModifierType toggle_mask;
|
||||
|
||||
toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
/* the type (dodge or burn) */
|
||||
str = g_strdup_printf (_("Type (%s)"),
|
||||
pika_get_mod_string (toggle_mask));
|
||||
frame = pika_prop_enum_radio_frame_new (config, "type",
|
||||
str, 0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
g_free (str);
|
||||
|
||||
/* mode (highlights, midtones, or shadows) */
|
||||
frame = pika_prop_enum_radio_frame_new (config, "mode", NULL,
|
||||
0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* the exposure scale */
|
||||
scale = pika_prop_spin_scale_new (config, "exposure",
|
||||
1.0, 10.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
60
app/tools/pikadodgeburntool.h
Normal file
60
app/tools/pikadodgeburntool.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_DODGE_BURN_TOOL_H__
|
||||
#define __PIKA_DODGE_BURN_TOOL_H__
|
||||
|
||||
|
||||
#include "pikabrushtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_DODGE_BURN_TOOL (pika_dodge_burn_tool_get_type ())
|
||||
#define PIKA_DODGE_BURN_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_DODGE_BURN_TOOL, PikaDodgeBurnTool))
|
||||
#define PIKA_IS_DODGE_BURN_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_DODGE_BURN_TOOL))
|
||||
#define PIKA_DODGE_BURN_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_DODGE_BURN_TOOL, PikaDodgeBurnToolClass))
|
||||
#define PIKA_IS_DODGE_BURN_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_DODGE_BURN_TOOL))
|
||||
|
||||
#define PIKA_DODGE_BURN_TOOL_GET_OPTIONS(t) (PIKA_DODGE_BURN_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaDodgeBurnTool PikaDodgeBurnTool;
|
||||
typedef struct _PikaDodgeBurnToolClass PikaDodgeBurnToolClass;
|
||||
|
||||
struct _PikaDodgeBurnTool
|
||||
{
|
||||
PikaBrushTool parent_instance;
|
||||
|
||||
gboolean toggled;
|
||||
};
|
||||
|
||||
struct _PikaDodgeBurnToolClass
|
||||
{
|
||||
PikaBrushToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_dodge_burn_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_dodge_burn_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_DODGEBURN_TOOL_H__ */
|
||||
1334
app/tools/pikadrawtool.c
Normal file
1334
app/tools/pikadrawtool.c
Normal file
File diff suppressed because it is too large
Load Diff
216
app/tools/pikadrawtool.h
Normal file
216
app/tools/pikadrawtool.h
Normal file
@ -0,0 +1,216 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_DRAW_TOOL_H__
|
||||
#define __PIKA_DRAW_TOOL_H__
|
||||
|
||||
|
||||
#include "pikatool.h"
|
||||
|
||||
|
||||
#define PIKA_TOOL_HANDLE_SIZE_CIRCLE 13
|
||||
#define PIKA_TOOL_HANDLE_SIZE_CROSS 15
|
||||
#define PIKA_TOOL_HANDLE_SIZE_CROSSHAIR 43
|
||||
#define PIKA_TOOL_HANDLE_SIZE_LARGE 25
|
||||
#define PIKA_TOOL_HANDLE_SIZE_SMALL 7
|
||||
|
||||
|
||||
#define PIKA_TYPE_DRAW_TOOL (pika_draw_tool_get_type ())
|
||||
#define PIKA_DRAW_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_DRAW_TOOL, PikaDrawTool))
|
||||
#define PIKA_DRAW_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_DRAW_TOOL, PikaDrawToolClass))
|
||||
#define PIKA_IS_DRAW_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_DRAW_TOOL))
|
||||
#define PIKA_IS_DRAW_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_DRAW_TOOL))
|
||||
#define PIKA_DRAW_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_DRAW_TOOL, PikaDrawToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaDrawToolClass PikaDrawToolClass;
|
||||
|
||||
struct _PikaDrawTool
|
||||
{
|
||||
PikaTool parent_instance;
|
||||
|
||||
PikaDisplay *display; /* The display we are drawing to (may be
|
||||
* a different one than tool->display)
|
||||
*/
|
||||
|
||||
gint paused_count; /* count to keep track of multiple pauses */
|
||||
guint draw_timeout; /* draw delay timeout ID */
|
||||
guint64 last_draw_time; /* time of last draw(), monotonically */
|
||||
|
||||
PikaToolWidget *widget;
|
||||
gchar *default_status;
|
||||
PikaCanvasItem *preview;
|
||||
PikaCanvasItem *item;
|
||||
GList *group_stack;
|
||||
};
|
||||
|
||||
struct _PikaDrawToolClass
|
||||
{
|
||||
PikaToolClass parent_class;
|
||||
|
||||
/* virtual function */
|
||||
|
||||
void (* draw) (PikaDrawTool *draw_tool);
|
||||
};
|
||||
|
||||
|
||||
GType pika_draw_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_draw_tool_start (PikaDrawTool *draw_tool,
|
||||
PikaDisplay *display);
|
||||
void pika_draw_tool_stop (PikaDrawTool *draw_tool);
|
||||
|
||||
gboolean pika_draw_tool_is_active (PikaDrawTool *draw_tool);
|
||||
|
||||
void pika_draw_tool_pause (PikaDrawTool *draw_tool);
|
||||
void pika_draw_tool_resume (PikaDrawTool *draw_tool);
|
||||
|
||||
gdouble pika_draw_tool_calc_distance (PikaDrawTool *draw_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2);
|
||||
gdouble pika_draw_tool_calc_distance_square (PikaDrawTool *draw_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2);
|
||||
|
||||
void pika_draw_tool_set_widget (PikaDrawTool *draw_tool,
|
||||
PikaToolWidget *widget);
|
||||
void pika_draw_tool_set_default_status (PikaDrawTool *draw_tool,
|
||||
const gchar *status);
|
||||
|
||||
void pika_draw_tool_add_preview (PikaDrawTool *draw_tool,
|
||||
PikaCanvasItem *item);
|
||||
void pika_draw_tool_remove_preview (PikaDrawTool *draw_tool,
|
||||
PikaCanvasItem *item);
|
||||
|
||||
void pika_draw_tool_add_item (PikaDrawTool *draw_tool,
|
||||
PikaCanvasItem *item);
|
||||
void pika_draw_tool_remove_item (PikaDrawTool *draw_tool,
|
||||
PikaCanvasItem *item);
|
||||
|
||||
PikaCanvasGroup* pika_draw_tool_add_stroke_group (PikaDrawTool *draw_tool);
|
||||
PikaCanvasGroup* pika_draw_tool_add_fill_group (PikaDrawTool *draw_tool);
|
||||
|
||||
void pika_draw_tool_push_group (PikaDrawTool *draw_tool,
|
||||
PikaCanvasGroup *group);
|
||||
void pika_draw_tool_pop_group (PikaDrawTool *draw_tool);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_line (PikaDrawTool *draw_tool,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2);
|
||||
PikaCanvasItem * pika_draw_tool_add_guide (PikaDrawTool *draw_tool,
|
||||
PikaOrientationType orientation,
|
||||
gint position,
|
||||
PikaGuideStyle style);
|
||||
PikaCanvasItem * pika_draw_tool_add_crosshair (PikaDrawTool *draw_tool,
|
||||
gint position_x,
|
||||
gint position_y);
|
||||
PikaCanvasItem * pika_draw_tool_add_sample_point (PikaDrawTool *draw_tool,
|
||||
gint x,
|
||||
gint y,
|
||||
gint index);
|
||||
PikaCanvasItem * pika_draw_tool_add_rectangle (PikaDrawTool *draw_tool,
|
||||
gboolean filled,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gdouble width,
|
||||
gdouble height);
|
||||
PikaCanvasItem * pika_draw_tool_add_arc (PikaDrawTool *draw_tool,
|
||||
gboolean filled,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gdouble width,
|
||||
gdouble height,
|
||||
gdouble start_angle,
|
||||
gdouble slice_angle);
|
||||
PikaCanvasItem * pika_draw_tool_add_transform_preview(PikaDrawTool *draw_tool,
|
||||
PikaPickable *pickable,
|
||||
const PikaMatrix3 *transform,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_handle (PikaDrawTool *draw_tool,
|
||||
PikaHandleType type,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gint width,
|
||||
gint height,
|
||||
PikaHandleAnchor anchor);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_lines (PikaDrawTool *draw_tool,
|
||||
const PikaVector2 *points,
|
||||
gint n_points,
|
||||
PikaMatrix3 *transform,
|
||||
gboolean filled);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_strokes (PikaDrawTool *draw_tool,
|
||||
const PikaCoords *points,
|
||||
gint n_points,
|
||||
PikaMatrix3 *transform,
|
||||
gboolean filled);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_pen (PikaDrawTool *draw_tool,
|
||||
const PikaVector2 *points,
|
||||
gint n_points,
|
||||
PikaContext *context,
|
||||
PikaActiveColor color,
|
||||
gint width);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_boundary (PikaDrawTool *draw_tool,
|
||||
const PikaBoundSeg *bound_segs,
|
||||
gint n_bound_segs,
|
||||
PikaMatrix3 *transform,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_text_cursor (PikaDrawTool *draw_tool,
|
||||
PangoRectangle *cursor,
|
||||
gboolean overwrite,
|
||||
PikaTextDirection direction);
|
||||
|
||||
PikaCanvasItem * pika_draw_tool_add_text (PikaDrawTool *draw_tool,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gdouble font_size,
|
||||
gchar *text);
|
||||
|
||||
gboolean pika_draw_tool_on_handle (PikaDrawTool *draw_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
PikaHandleType type,
|
||||
gdouble handle_x,
|
||||
gdouble handle_y,
|
||||
gint width,
|
||||
gint height,
|
||||
PikaHandleAnchor anchor);
|
||||
|
||||
|
||||
#endif /* __PIKA_DRAW_TOOL_H__ */
|
||||
1456
app/tools/pikaeditselectiontool.c
Normal file
1456
app/tools/pikaeditselectiontool.c
Normal file
File diff suppressed because it is too large
Load Diff
54
app/tools/pikaeditselectiontool.h
Normal file
54
app/tools/pikaeditselectiontool.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_EDIT_SELECTION_TOOL_H__
|
||||
#define __PIKA_EDIT_SELECTION_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_EDIT_SELECTION_TOOL (pika_edit_selection_tool_get_type ())
|
||||
#define PIKA_EDIT_SELECTION_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_EDIT_SELECTION_TOOL, PikaEditSelectionTool))
|
||||
#define PIKA_EDIT_SELECTION_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_EDIT_SELECTION_TOOL, PikaEditSelectionToolClass))
|
||||
#define PIKA_IS_EDIT_SELECTION_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_EDIT_SELECTION_TOOL))
|
||||
#define PIKA_IS_EDIT_SELECTION_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_EDIT_SELECTION_TOOL))
|
||||
|
||||
|
||||
GType pika_edit_selection_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_edit_selection_tool_start (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
const PikaCoords *coords,
|
||||
PikaTranslateMode edit_mode,
|
||||
gboolean propagate_release);
|
||||
|
||||
gboolean pika_edit_selection_tool_key_press (PikaTool *tool,
|
||||
GdkEventKey *kevent,
|
||||
PikaDisplay *display);
|
||||
gboolean pika_edit_selection_tool_translate (PikaTool *tool,
|
||||
GdkEventKey *kevent,
|
||||
PikaTransformType translate_type,
|
||||
PikaDisplay *display,
|
||||
GtkWidget **type_box);
|
||||
|
||||
|
||||
#endif /* __PIKA_EDIT_SELECTION_TOOL_H__ */
|
||||
116
app/tools/pikaellipseselecttool.c
Normal file
116
app/tools/pikaellipseselecttool.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pikachannel-select.h"
|
||||
#include "core/pikaimage.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
|
||||
#include "pikaellipseselecttool.h"
|
||||
#include "pikarectangleselectoptions.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_ellipse_select_tool_select (PikaRectangleSelectTool *rect_tool,
|
||||
PikaChannelOps operation,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaEllipseSelectTool, pika_ellipse_select_tool,
|
||||
PIKA_TYPE_RECTANGLE_SELECT_TOOL)
|
||||
|
||||
#define parent_class pika_ellipse_select_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_ellipse_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_ELLIPSE_SELECT_TOOL,
|
||||
PIKA_TYPE_RECTANGLE_SELECT_OPTIONS,
|
||||
pika_rectangle_select_options_gui,
|
||||
0,
|
||||
"pika-ellipse-select-tool",
|
||||
_("Ellipse Select"),
|
||||
_("Ellipse Select Tool: Select an elliptical region"),
|
||||
N_("_Ellipse Select"), "E",
|
||||
NULL, PIKA_HELP_TOOL_ELLIPSE_SELECT,
|
||||
PIKA_ICON_TOOL_ELLIPSE_SELECT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_ellipse_select_tool_class_init (PikaEllipseSelectToolClass *klass)
|
||||
{
|
||||
PikaRectangleSelectToolClass *rect_tool_class;
|
||||
|
||||
rect_tool_class = PIKA_RECTANGLE_SELECT_TOOL_CLASS (klass);
|
||||
|
||||
rect_tool_class->select = pika_ellipse_select_tool_select;
|
||||
rect_tool_class->draw_ellipse = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_ellipse_select_tool_init (PikaEllipseSelectTool *ellipse_select)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (ellipse_select);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_ELLIPSE_SELECT);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_ellipse_select_tool_select (PikaRectangleSelectTool *rect_tool,
|
||||
PikaChannelOps operation,
|
||||
gint x,
|
||||
gint y,
|
||||
gint w,
|
||||
gint h)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (rect_tool);
|
||||
PikaSelectionOptions *options = PIKA_SELECTION_TOOL_GET_OPTIONS (rect_tool);
|
||||
PikaImage *image = pika_display_get_image (tool->display);
|
||||
|
||||
pika_channel_select_ellipse (pika_image_get_mask (image),
|
||||
x, y, w, h,
|
||||
operation,
|
||||
options->antialias,
|
||||
options->feather,
|
||||
options->feather_radius,
|
||||
options->feather_radius,
|
||||
TRUE);
|
||||
}
|
||||
57
app/tools/pikaellipseselecttool.h
Normal file
57
app/tools/pikaellipseselecttool.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_ELLIPSE_SELECT_TOOL_H__
|
||||
#define __PIKA_ELLIPSE_SELECT_TOOL_H__
|
||||
|
||||
|
||||
#include "pikarectangleselecttool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_ELLIPSE_SELECT_TOOL (pika_ellipse_select_tool_get_type ())
|
||||
#define PIKA_ELLIPSE_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_ELLIPSE_SELECT_TOOL, PikaEllipseSelectTool))
|
||||
#define PIKA_ELLIPSE_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_ELLIPSE_SELECT_TOOL, PikaEllipseSelectToolClass))
|
||||
#define PIKA_IS_ELLIPSE_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_ELLIPSE_SELECT_TOOL))
|
||||
#define PIKA_IS_ELLIPSE_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_ELLIPSE_SELECT_TOOL))
|
||||
#define PIKA_ELLIPSE_SELECT_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_ELLIPSE_SELECT_TOOL, PikaEllipseSelectToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaEllipseSelectTool PikaEllipseSelectTool;
|
||||
typedef struct _PikaEllipseSelectToolClass PikaEllipseSelectToolClass;
|
||||
|
||||
struct _PikaEllipseSelectTool
|
||||
{
|
||||
PikaRectangleSelectTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaEllipseSelectToolClass
|
||||
{
|
||||
PikaRectangleSelectToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_ellipse_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_ellipse_select_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_ELLIPSE_SELECT_TOOL_H__ */
|
||||
179
app/tools/pikaerasertool.c
Normal file
179
app/tools/pikaerasertool.c
Normal file
@ -0,0 +1,179 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pikadrawable.h"
|
||||
|
||||
#include "paint/pikaeraseroptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikaerasertool.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static void pika_eraser_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_eraser_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
|
||||
static gboolean pika_eraser_tool_is_alpha_only (PikaPaintTool *paint_tool,
|
||||
PikaDrawable *drawable);
|
||||
|
||||
static GtkWidget * pika_eraser_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaEraserTool, pika_eraser_tool, PIKA_TYPE_BRUSH_TOOL)
|
||||
|
||||
#define parent_class pika_eraser_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_eraser_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_ERASER_TOOL,
|
||||
PIKA_TYPE_ERASER_OPTIONS,
|
||||
pika_eraser_options_gui,
|
||||
PIKA_PAINT_OPTIONS_CONTEXT_MASK,
|
||||
"pika-eraser-tool",
|
||||
_("Eraser"),
|
||||
_("Eraser Tool: Erase to background or transparency using a brush"),
|
||||
N_("_Eraser"), "<shift>E",
|
||||
NULL, PIKA_HELP_TOOL_ERASER,
|
||||
PIKA_ICON_TOOL_ERASER,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_eraser_tool_class_init (PikaEraserToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaPaintToolClass *paint_tool_class = PIKA_PAINT_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->modifier_key = pika_eraser_tool_modifier_key;
|
||||
tool_class->cursor_update = pika_eraser_tool_cursor_update;
|
||||
|
||||
paint_tool_class->is_alpha_only = pika_eraser_tool_is_alpha_only;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_eraser_tool_init (PikaEraserTool *eraser)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (eraser);
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (eraser);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_ERASER);
|
||||
pika_tool_control_set_toggle_cursor_modifier (tool->control,
|
||||
PIKA_CURSOR_MODIFIER_MINUS);
|
||||
|
||||
pika_paint_tool_enable_color_picker (paint_tool,
|
||||
PIKA_COLOR_PICK_TARGET_BACKGROUND);
|
||||
|
||||
paint_tool->status = _("Click to erase");
|
||||
paint_tool->status_line = _("Click to erase the line");
|
||||
paint_tool->status_ctrl = _("%s to pick a background color");
|
||||
}
|
||||
|
||||
static void
|
||||
pika_eraser_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
if (key == GDK_MOD1_MASK)
|
||||
{
|
||||
PikaEraserOptions *options = PIKA_ERASER_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
g_object_set (options,
|
||||
"anti-erase", ! options->anti_erase,
|
||||
NULL);
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->modifier_key (tool, key, press, state, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_eraser_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaEraserOptions *options = PIKA_ERASER_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
pika_tool_control_set_toggled (tool->control, options->anti_erase);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_eraser_tool_is_alpha_only (PikaPaintTool *paint_tool,
|
||||
PikaDrawable *drawable)
|
||||
{
|
||||
PikaEraserOptions *options = PIKA_ERASER_TOOL_GET_OPTIONS (paint_tool);
|
||||
|
||||
if (! options->anti_erase)
|
||||
return pika_drawable_has_alpha (drawable);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* tool options stuff */
|
||||
|
||||
static GtkWidget *
|
||||
pika_eraser_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *button;
|
||||
gchar *str;
|
||||
|
||||
/* the anti_erase toggle */
|
||||
str = g_strdup_printf (_("Anti erase (%s)"),
|
||||
pika_get_mod_string (GDK_MOD1_MASK));
|
||||
|
||||
button = pika_prop_check_button_new (config, "anti-erase", str);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
g_free (str);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
59
app/tools/pikaerasertool.h
Normal file
59
app/tools/pikaerasertool.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_ERASER_TOOL_H__
|
||||
#define __PIKA_ERASER_TOOL_H__
|
||||
|
||||
|
||||
#include "pikabrushtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_ERASER_TOOL (pika_eraser_tool_get_type ())
|
||||
#define PIKA_ERASER_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_ERASER_TOOL, PikaEraserTool))
|
||||
#define PIKA_ERASER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_ERASER_TOOL, PikaEraserToolClass))
|
||||
#define PIKA_IS_ERASER_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_ERASER_TOOL))
|
||||
#define PIKA_IS_ERASER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_ERASER_TOOL))
|
||||
#define PIKA_ERASER_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_ERASER_TOOL, PikaEraserToolClass))
|
||||
|
||||
#define PIKA_ERASER_TOOL_GET_OPTIONS(t) (PIKA_ERASER_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaEraserTool PikaEraserTool;
|
||||
typedef struct _PikaEraserToolClass PikaEraserToolClass;
|
||||
|
||||
struct _PikaEraserTool
|
||||
{
|
||||
PikaBrushTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaEraserToolClass
|
||||
{
|
||||
PikaBrushToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_eraser_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_eraser_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_ERASER_TOOL_H__ */
|
||||
274
app/tools/pikafilteroptions.c
Normal file
274
app/tools/pikafilteroptions.c
Normal file
@ -0,0 +1,274 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "pikafilteroptions.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_PREVIEW,
|
||||
PROP_PREVIEW_SPLIT,
|
||||
PROP_PREVIEW_SPLIT_ALIGNMENT,
|
||||
PROP_PREVIEW_SPLIT_POSITION,
|
||||
PROP_CONTROLLER,
|
||||
PROP_BLENDING_OPTIONS_EXPANDED,
|
||||
PROP_COLOR_OPTIONS_EXPANDED
|
||||
};
|
||||
|
||||
|
||||
static void pika_filter_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_filter_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaFilterOptions, pika_filter_options,
|
||||
PIKA_TYPE_COLOR_OPTIONS)
|
||||
|
||||
#define parent_class pika_filter_options_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_filter_options_class_init (PikaFilterOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_filter_options_set_property;
|
||||
object_class->get_property = pika_filter_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_PREVIEW,
|
||||
"preview",
|
||||
_("_Preview"),
|
||||
NULL,
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PREVIEW_SPLIT,
|
||||
g_param_spec_boolean ("preview-split",
|
||||
_("Split _view"),
|
||||
NULL,
|
||||
FALSE,
|
||||
PIKA_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PREVIEW_SPLIT_ALIGNMENT,
|
||||
g_param_spec_enum ("preview-split-alignment",
|
||||
NULL, NULL,
|
||||
PIKA_TYPE_ALIGNMENT_TYPE,
|
||||
PIKA_ALIGN_LEFT,
|
||||
PIKA_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PREVIEW_SPLIT_POSITION,
|
||||
g_param_spec_int ("preview-split-position",
|
||||
NULL, NULL,
|
||||
G_MININT, G_MAXINT, 0,
|
||||
PIKA_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_CONTROLLER,
|
||||
"controller",
|
||||
_("On-canvas con_trols"),
|
||||
_("Show on-canvas filter controls"),
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_BLENDING_OPTIONS_EXPANDED,
|
||||
"blending-options-expanded",
|
||||
NULL, NULL,
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_COLOR_OPTIONS_EXPANDED,
|
||||
"color-options-expanded",
|
||||
NULL, NULL,
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_options_init (PikaFilterOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaFilterOptions *options = PIKA_FILTER_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_PREVIEW:
|
||||
options->preview = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_SPLIT:
|
||||
options->preview_split = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_SPLIT_ALIGNMENT:
|
||||
options->preview_split_alignment = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_SPLIT_POSITION:
|
||||
options->preview_split_position = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_CONTROLLER:
|
||||
options->controller = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_BLENDING_OPTIONS_EXPANDED:
|
||||
options->blending_options_expanded = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_OPTIONS_EXPANDED:
|
||||
options->color_options_expanded = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaFilterOptions *options = PIKA_FILTER_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_PREVIEW:
|
||||
g_value_set_boolean (value, options->preview);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_SPLIT:
|
||||
g_value_set_boolean (value, options->preview_split);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_SPLIT_ALIGNMENT:
|
||||
g_value_set_enum (value, options->preview_split_alignment);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_SPLIT_POSITION:
|
||||
g_value_set_int (value, options->preview_split_position);
|
||||
break;
|
||||
|
||||
case PROP_CONTROLLER:
|
||||
g_value_set_boolean (value, options->controller);
|
||||
break;
|
||||
|
||||
case PROP_BLENDING_OPTIONS_EXPANDED:
|
||||
g_value_set_boolean (value, options->blending_options_expanded);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_OPTIONS_EXPANDED:
|
||||
g_value_set_boolean (value, options->color_options_expanded);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_filter_options_switch_preview_side (PikaFilterOptions *options)
|
||||
{
|
||||
PikaAlignmentType alignment;
|
||||
|
||||
g_return_if_fail (PIKA_IS_FILTER_OPTIONS (options));
|
||||
|
||||
switch (options->preview_split_alignment)
|
||||
{
|
||||
case PIKA_ALIGN_LEFT: alignment = PIKA_ALIGN_RIGHT; break;
|
||||
case PIKA_ALIGN_RIGHT: alignment = PIKA_ALIGN_LEFT; break;
|
||||
case PIKA_ALIGN_TOP: alignment = PIKA_ALIGN_BOTTOM; break;
|
||||
case PIKA_ALIGN_BOTTOM: alignment = PIKA_ALIGN_TOP; break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
g_object_set (options, "preview-split-alignment", alignment, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pika_filter_options_switch_preview_orientation (PikaFilterOptions *options,
|
||||
gint position_x,
|
||||
gint position_y)
|
||||
{
|
||||
PikaAlignmentType alignment;
|
||||
gint position;
|
||||
|
||||
g_return_if_fail (PIKA_IS_FILTER_OPTIONS (options));
|
||||
|
||||
switch (options->preview_split_alignment)
|
||||
{
|
||||
case PIKA_ALIGN_LEFT: alignment = PIKA_ALIGN_TOP; break;
|
||||
case PIKA_ALIGN_RIGHT: alignment = PIKA_ALIGN_BOTTOM; break;
|
||||
case PIKA_ALIGN_TOP: alignment = PIKA_ALIGN_LEFT; break;
|
||||
case PIKA_ALIGN_BOTTOM: alignment = PIKA_ALIGN_RIGHT; break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
||||
if (alignment == PIKA_ALIGN_LEFT ||
|
||||
alignment == PIKA_ALIGN_RIGHT)
|
||||
{
|
||||
position = position_x;
|
||||
}
|
||||
else
|
||||
{
|
||||
position = position_y;
|
||||
}
|
||||
|
||||
g_object_set (options,
|
||||
"preview-split-alignment", alignment,
|
||||
"preview-split-position", position,
|
||||
NULL);
|
||||
}
|
||||
67
app/tools/pikafilteroptions.h
Normal file
67
app/tools/pikafilteroptions.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FILTER_OPTIONS_H__
|
||||
#define __PIKA_FILTER_OPTIONS_H__
|
||||
|
||||
|
||||
#include "pikacoloroptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FILTER_OPTIONS (pika_filter_options_get_type ())
|
||||
#define PIKA_FILTER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FILTER_OPTIONS, PikaFilterOptions))
|
||||
#define PIKA_FILTER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FILTER_OPTIONS, PikaFilterOptionsClass))
|
||||
#define PIKA_IS_FILTER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FILTER_OPTIONS))
|
||||
#define PIKA_IS_FILTER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FILTER_OPTIONS))
|
||||
#define PIKA_FILTER_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FILTER_OPTIONS, PikaFilterOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaFilterOptionsClass PikaFilterOptionsClass;
|
||||
|
||||
struct _PikaFilterOptions
|
||||
{
|
||||
PikaColorOptions parent_instance;
|
||||
|
||||
gboolean preview;
|
||||
gboolean preview_split;
|
||||
PikaAlignmentType preview_split_alignment;
|
||||
gint preview_split_position;
|
||||
gboolean controller;
|
||||
|
||||
gboolean blending_options_expanded;
|
||||
gboolean color_options_expanded;
|
||||
};
|
||||
|
||||
struct _PikaFilterOptionsClass
|
||||
{
|
||||
PikaColorOptionsClass parent_instance;
|
||||
};
|
||||
|
||||
|
||||
GType pika_filter_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_filter_options_switch_preview_side (PikaFilterOptions *options);
|
||||
void pika_filter_options_switch_preview_orientation (PikaFilterOptions *options,
|
||||
gint position_x,
|
||||
gint position_y);
|
||||
|
||||
|
||||
#endif /* __PIKA_FILTER_OPTIONS_H__ */
|
||||
256
app/tools/pikafiltertool-settings.c
Normal file
256
app/tools/pikafiltertool-settings.c
Normal file
@ -0,0 +1,256 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikafiltertool-settings.c
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "widgets/pikasettingsbox.h"
|
||||
|
||||
#include "display/pikatoolgui.h"
|
||||
|
||||
#include "pikafiltertool.h"
|
||||
#include "pikafiltertool-settings.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static gboolean pika_filter_tool_settings_import (PikaSettingsBox *box,
|
||||
GFile *file,
|
||||
PikaFilterTool *filter_tool);
|
||||
static gboolean pika_filter_tool_settings_export (PikaSettingsBox *box,
|
||||
GFile *file,
|
||||
PikaFilterTool *filter_tool);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
GtkWidget *
|
||||
pika_filter_tool_get_settings_box (PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaToolInfo *tool_info = PIKA_TOOL (filter_tool)->tool_info;
|
||||
GQuark quark = g_quark_from_static_string ("settings-folder");
|
||||
GType type = G_TYPE_FROM_INSTANCE (filter_tool->config);
|
||||
GFile *settings_folder;
|
||||
GtkWidget *box;
|
||||
GtkWidget *label;
|
||||
GtkWidget *combo;
|
||||
gchar *import_title;
|
||||
gchar *export_title;
|
||||
|
||||
settings_folder = g_type_get_qdata (type, quark);
|
||||
|
||||
import_title = g_strdup_printf (_("Import '%s' Settings"),
|
||||
pika_tool_get_label (PIKA_TOOL (filter_tool)));
|
||||
export_title = g_strdup_printf (_("Export '%s' Settings"),
|
||||
pika_tool_get_label (PIKA_TOOL (filter_tool)));
|
||||
|
||||
box = pika_settings_box_new (tool_info->pika,
|
||||
filter_tool->config,
|
||||
filter_tool->settings,
|
||||
import_title,
|
||||
export_title,
|
||||
pika_tool_get_help_id (PIKA_TOOL (filter_tool)),
|
||||
settings_folder,
|
||||
NULL);
|
||||
|
||||
g_free (import_title);
|
||||
g_free (export_title);
|
||||
|
||||
g_signal_connect (box, "import",
|
||||
G_CALLBACK (pika_filter_tool_settings_import),
|
||||
filter_tool);
|
||||
|
||||
g_signal_connect (box, "export",
|
||||
G_CALLBACK (pika_filter_tool_settings_export),
|
||||
filter_tool);
|
||||
|
||||
g_signal_connect_swapped (box, "selected",
|
||||
G_CALLBACK (pika_filter_tool_set_config),
|
||||
filter_tool);
|
||||
|
||||
label = gtk_label_new_with_mnemonic (_("Pre_sets:"));
|
||||
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
|
||||
gtk_box_reorder_child (GTK_BOX (box), label, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
combo = pika_settings_box_get_combo (PIKA_SETTINGS_BOX (box));
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_filter_tool_real_settings_import (PikaFilterTool *filter_tool,
|
||||
GInputStream *input,
|
||||
GError **error)
|
||||
{
|
||||
return pika_config_deserialize_stream (PIKA_CONFIG (filter_tool->config),
|
||||
input,
|
||||
NULL, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
pika_filter_tool_real_settings_export (PikaFilterTool *filter_tool,
|
||||
GOutputStream *output,
|
||||
GError **error)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (filter_tool);
|
||||
gchar *header;
|
||||
gchar *footer;
|
||||
gboolean success;
|
||||
|
||||
header = g_strdup_printf ("PIKA '%s' settings",
|
||||
pika_tool_get_label (tool));
|
||||
footer = g_strdup_printf ("end of '%s' settings",
|
||||
pika_tool_get_label (tool));
|
||||
|
||||
success = pika_config_serialize_to_stream (PIKA_CONFIG (filter_tool->config),
|
||||
output,
|
||||
header, footer,
|
||||
NULL, error);
|
||||
|
||||
g_free (header);
|
||||
g_free (footer);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static gboolean
|
||||
pika_filter_tool_settings_import (PikaSettingsBox *box,
|
||||
GFile *file,
|
||||
PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaFilterToolClass *tool_class = PIKA_FILTER_TOOL_GET_CLASS (filter_tool);
|
||||
GInputStream *input;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (tool_class->settings_import != NULL, FALSE);
|
||||
|
||||
if (PIKA_TOOL (filter_tool)->tool_info->pika->be_verbose)
|
||||
g_print ("Parsing '%s'\n", pika_file_get_utf8_name (file));
|
||||
|
||||
input = G_INPUT_STREAM (g_file_read (file, NULL, &error));
|
||||
if (! input)
|
||||
{
|
||||
pika_message (PIKA_TOOL (filter_tool)->tool_info->pika,
|
||||
G_OBJECT (pika_tool_gui_get_dialog (filter_tool->gui)),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
_("Could not open '%s' for reading: %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! tool_class->settings_import (filter_tool, input, &error))
|
||||
{
|
||||
pika_message (PIKA_TOOL (filter_tool)->tool_info->pika,
|
||||
G_OBJECT (pika_tool_gui_get_dialog (filter_tool->gui)),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
_("Error reading '%s': %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
g_object_unref (input);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_unref (input);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_filter_tool_settings_export (PikaSettingsBox *box,
|
||||
GFile *file,
|
||||
PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaFilterToolClass *tool_class = PIKA_FILTER_TOOL_GET_CLASS (filter_tool);
|
||||
GOutputStream *output;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_val_if_fail (tool_class->settings_export != NULL, FALSE);
|
||||
|
||||
if (PIKA_TOOL (filter_tool)->tool_info->pika->be_verbose)
|
||||
g_print ("Writing '%s'\n", pika_file_get_utf8_name (file));
|
||||
|
||||
output = G_OUTPUT_STREAM (g_file_replace (file,
|
||||
NULL, FALSE, G_FILE_CREATE_NONE,
|
||||
NULL, &error));
|
||||
if (! output)
|
||||
{
|
||||
pika_message_literal (PIKA_TOOL (filter_tool)->tool_info->pika,
|
||||
G_OBJECT (pika_tool_gui_get_dialog (filter_tool->gui)),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! tool_class->settings_export (filter_tool, output, &error))
|
||||
{
|
||||
GCancellable *cancellable = g_cancellable_new ();
|
||||
|
||||
pika_message (PIKA_TOOL (filter_tool)->tool_info->pika,
|
||||
G_OBJECT (pika_tool_gui_get_dialog (filter_tool->gui)),
|
||||
PIKA_MESSAGE_ERROR,
|
||||
_("Error writing '%s': %s"),
|
||||
pika_file_get_utf8_name (file),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
|
||||
/* Cancel the overwrite initiated by g_file_replace(). */
|
||||
g_cancellable_cancel (cancellable);
|
||||
g_output_stream_close (output, cancellable, NULL);
|
||||
g_object_unref (cancellable);
|
||||
g_object_unref (output);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_unref (output);
|
||||
|
||||
pika_message (PIKA_TOOL (filter_tool)->tool_info->pika,
|
||||
G_OBJECT (PIKA_TOOL (filter_tool)->display),
|
||||
PIKA_MESSAGE_INFO,
|
||||
_("Settings saved to '%s'"),
|
||||
pika_file_get_utf8_name (file));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
41
app/tools/pikafiltertool-settings.h
Normal file
41
app/tools/pikafiltertool-settings.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikafiltertool-settings.h
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FILTER_TOOL_SETTINGS_H__
|
||||
#define __PIKA_FILTER_TOOL_SETTINGS_H__
|
||||
|
||||
|
||||
GtkWidget * pika_filter_tool_get_settings_box (PikaFilterTool *filter_tool);
|
||||
|
||||
|
||||
/* virtual functions of PikaSettingsTool, don't call directly */
|
||||
|
||||
gboolean pika_filter_tool_real_settings_import (PikaFilterTool *filter_tool,
|
||||
GInputStream *input,
|
||||
GError **error);
|
||||
gboolean pika_filter_tool_real_settings_export (PikaFilterTool *filter_tool,
|
||||
GOutputStream *output,
|
||||
GError **error);
|
||||
|
||||
|
||||
#endif /* __PIKA_FILTER_TOOL_SETTINGS_H__ */
|
||||
967
app/tools/pikafiltertool-widgets.c
Normal file
967
app/tools/pikafiltertool-widgets.c
Normal file
@ -0,0 +1,967 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikafiltertool-widgets.c
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pikacontainer.h"
|
||||
#include "core/pikaitem.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikatoolfocus.h"
|
||||
#include "display/pikatoolgyroscope.h"
|
||||
#include "display/pikatoolline.h"
|
||||
#include "display/pikatooltransformgrid.h"
|
||||
#include "display/pikatoolwidgetgroup.h"
|
||||
|
||||
#include "pikafilteroptions.h"
|
||||
#include "pikafiltertool.h"
|
||||
#include "pikafiltertool-widgets.h"
|
||||
|
||||
|
||||
typedef struct _Controller Controller;
|
||||
|
||||
struct _Controller
|
||||
{
|
||||
PikaFilterTool *filter_tool;
|
||||
PikaControllerType controller_type;
|
||||
PikaToolWidget *widget;
|
||||
GCallback creator_callback;
|
||||
gpointer creator_data;
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static Controller * pika_filter_tool_controller_new (void);
|
||||
static void pika_filter_tool_controller_free (Controller *controller);
|
||||
|
||||
static void pika_filter_tool_set_line (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2);
|
||||
static void pika_filter_tool_line_changed (PikaToolWidget *widget,
|
||||
Controller *controller);
|
||||
|
||||
static void pika_filter_tool_set_slider_line (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2,
|
||||
const PikaControllerSlider *sliders,
|
||||
gint n_sliders);
|
||||
static void pika_filter_tool_slider_line_changed (PikaToolWidget *widget,
|
||||
Controller *controller);
|
||||
|
||||
static void pika_filter_tool_set_transform_grid (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
const PikaMatrix3 *transform);
|
||||
static void pika_filter_tool_transform_grid_changed (PikaToolWidget *widget,
|
||||
Controller *controller);
|
||||
|
||||
static void pika_filter_tool_set_transform_grids (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
const PikaMatrix3 *transforms,
|
||||
gint n_transforms);
|
||||
static void pika_filter_tool_transform_grids_changed (PikaToolWidget *widget,
|
||||
Controller *controller);
|
||||
|
||||
static void pika_filter_tool_set_gyroscope (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
gdouble yaw,
|
||||
gdouble pitch,
|
||||
gdouble roll,
|
||||
gdouble zoom,
|
||||
gboolean invert);
|
||||
static void pika_filter_tool_gyroscope_changed (PikaToolWidget *widget,
|
||||
Controller *controller);
|
||||
|
||||
static void pika_filter_tool_set_focus (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
PikaLimitType type,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gdouble radius,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble inner_limit,
|
||||
gdouble midpoint);
|
||||
static void pika_filter_tool_focus_changed (PikaToolWidget *widget,
|
||||
Controller *controller);
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
PikaToolWidget *
|
||||
pika_filter_tool_create_widget (PikaFilterTool *filter_tool,
|
||||
PikaControllerType controller_type,
|
||||
const gchar *status_title,
|
||||
GCallback callback,
|
||||
gpointer callback_data,
|
||||
GCallback *set_func,
|
||||
gpointer *set_func_data)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDisplayShell *shell;
|
||||
Controller *controller;
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_FILTER_TOOL (filter_tool), NULL);
|
||||
g_return_val_if_fail (filter_tool->config != NULL, NULL);
|
||||
|
||||
tool = PIKA_TOOL (filter_tool);
|
||||
|
||||
g_return_val_if_fail (tool->display != NULL, NULL);
|
||||
|
||||
shell = pika_display_get_shell (tool->display);
|
||||
|
||||
controller = pika_filter_tool_controller_new ();
|
||||
|
||||
controller->filter_tool = filter_tool;
|
||||
controller->controller_type = controller_type;
|
||||
controller->creator_callback = callback;
|
||||
controller->creator_data = callback_data;
|
||||
|
||||
switch (controller_type)
|
||||
{
|
||||
case PIKA_CONTROLLER_TYPE_LINE:
|
||||
controller->widget = pika_tool_line_new (shell, 100, 100, 500, 500);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"status-title", status_title,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (controller->widget, "changed",
|
||||
G_CALLBACK (pika_filter_tool_line_changed),
|
||||
controller);
|
||||
|
||||
*set_func = (GCallback) pika_filter_tool_set_line;
|
||||
*set_func_data = controller;
|
||||
break;
|
||||
|
||||
case PIKA_CONTROLLER_TYPE_SLIDER_LINE:
|
||||
controller->widget = pika_tool_line_new (shell, 100, 100, 500, 500);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"status-title", status_title,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (controller->widget, "changed",
|
||||
G_CALLBACK (pika_filter_tool_slider_line_changed),
|
||||
controller);
|
||||
|
||||
*set_func = (GCallback) pika_filter_tool_set_slider_line;
|
||||
*set_func_data = controller;
|
||||
break;
|
||||
|
||||
case PIKA_CONTROLLER_TYPE_TRANSFORM_GRID:
|
||||
{
|
||||
PikaMatrix3 transform;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
gdouble x1, y1;
|
||||
gdouble x2, y2;
|
||||
|
||||
pika_matrix3_identity (&transform);
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
x1 = off_x + area.x;
|
||||
y1 = off_y + area.y;
|
||||
x2 = x1 + area.width;
|
||||
y2 = y1 + area.height;
|
||||
|
||||
controller->widget = pika_tool_transform_grid_new (shell, &transform,
|
||||
x1, y1, x2, y2);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"pivot-x", (x1 + x2) / 2.0,
|
||||
"pivot-y", (y1 + y2) / 2.0,
|
||||
"inside-function", PIKA_TRANSFORM_FUNCTION_MOVE,
|
||||
"outside-function", PIKA_TRANSFORM_FUNCTION_ROTATE,
|
||||
"use-corner-handles", TRUE,
|
||||
"use-perspective-handles", TRUE,
|
||||
"use-side-handles", TRUE,
|
||||
"use-shear-handles", TRUE,
|
||||
"use-pivot-handle", TRUE,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (controller->widget, "changed",
|
||||
G_CALLBACK (pika_filter_tool_transform_grid_changed),
|
||||
controller);
|
||||
|
||||
*set_func = (GCallback) pika_filter_tool_set_transform_grid;
|
||||
*set_func_data = controller;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIKA_CONTROLLER_TYPE_TRANSFORM_GRIDS:
|
||||
{
|
||||
controller->widget = pika_tool_widget_group_new (shell);
|
||||
|
||||
pika_tool_widget_group_set_auto_raise (
|
||||
PIKA_TOOL_WIDGET_GROUP (controller->widget), TRUE);
|
||||
|
||||
g_signal_connect (controller->widget, "changed",
|
||||
G_CALLBACK (pika_filter_tool_transform_grids_changed),
|
||||
controller);
|
||||
|
||||
*set_func = (GCallback) pika_filter_tool_set_transform_grids;
|
||||
*set_func_data = controller;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIKA_CONTROLLER_TYPE_GYROSCOPE:
|
||||
{
|
||||
GeglRectangle area;
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
controller->widget = pika_tool_gyroscope_new (shell);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"speed", 1.0 / MAX (area.width, area.height),
|
||||
"pivot-x", off_x + area.x + area.width / 2.0,
|
||||
"pivot-y", off_y + area.y + area.height / 2.0,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (controller->widget, "changed",
|
||||
G_CALLBACK (pika_filter_tool_gyroscope_changed),
|
||||
controller);
|
||||
|
||||
*set_func = (GCallback) pika_filter_tool_set_gyroscope;
|
||||
*set_func_data = controller;
|
||||
}
|
||||
break;
|
||||
|
||||
case PIKA_CONTROLLER_TYPE_FOCUS:
|
||||
controller->widget = pika_tool_focus_new (shell);
|
||||
|
||||
g_signal_connect (controller->widget, "changed",
|
||||
G_CALLBACK (pika_filter_tool_focus_changed),
|
||||
controller);
|
||||
|
||||
*set_func = (GCallback) pika_filter_tool_set_focus;
|
||||
*set_func_data = controller;
|
||||
break;
|
||||
}
|
||||
|
||||
g_object_add_weak_pointer (G_OBJECT (controller->widget),
|
||||
(gpointer) &controller->widget);
|
||||
|
||||
g_object_set_data_full (filter_tool->config,
|
||||
"pika-filter-tool-controller", controller,
|
||||
(GDestroyNotify) pika_filter_tool_controller_free);
|
||||
|
||||
return controller->widget;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_reset_transform_grid (PikaToolWidget *widget,
|
||||
PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaMatrix3 *transform;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
gdouble x1, y1;
|
||||
gdouble x2, y2;
|
||||
gdouble pivot_x, pivot_y;
|
||||
|
||||
g_object_get (widget,
|
||||
"transform", &transform,
|
||||
NULL);
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
x1 = off_x + area.x;
|
||||
y1 = off_y + area.y;
|
||||
x2 = x1 + area.width;
|
||||
y2 = y1 + area.height;
|
||||
|
||||
pika_matrix3_transform_point (transform,
|
||||
(x1 + x2) / 2.0, (y1 + y2) / 2.0,
|
||||
&pivot_x, &pivot_y);
|
||||
|
||||
g_object_set (widget,
|
||||
"pivot-x", pivot_x,
|
||||
"pivot-y", pivot_y,
|
||||
NULL);
|
||||
|
||||
g_free (transform);
|
||||
}
|
||||
|
||||
void
|
||||
pika_filter_tool_reset_widget (PikaFilterTool *filter_tool,
|
||||
PikaToolWidget *widget)
|
||||
{
|
||||
Controller *controller;
|
||||
|
||||
g_return_if_fail (PIKA_IS_FILTER_TOOL (filter_tool));
|
||||
g_return_if_fail (PIKA_IS_TOOL_WIDGET (widget));
|
||||
g_return_if_fail (filter_tool->config != NULL);
|
||||
|
||||
controller = g_object_get_data (filter_tool->config,
|
||||
"pika-filter-tool-controller");
|
||||
|
||||
g_return_if_fail (controller != NULL);
|
||||
|
||||
switch (controller->controller_type)
|
||||
{
|
||||
case PIKA_CONTROLLER_TYPE_TRANSFORM_GRID:
|
||||
{
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grid_changed,
|
||||
controller);
|
||||
|
||||
pika_filter_tool_reset_transform_grid (controller->widget, filter_tool);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grid_changed,
|
||||
controller);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIKA_CONTROLLER_TYPE_TRANSFORM_GRIDS:
|
||||
{
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grids_changed,
|
||||
controller);
|
||||
|
||||
pika_container_foreach (
|
||||
pika_tool_widget_group_get_children (
|
||||
PIKA_TOOL_WIDGET_GROUP (controller->widget)),
|
||||
(GFunc) pika_filter_tool_reset_transform_grid,
|
||||
filter_tool);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grids_changed,
|
||||
controller);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* private functions */
|
||||
|
||||
static Controller *
|
||||
pika_filter_tool_controller_new (void)
|
||||
{
|
||||
return g_slice_new0 (Controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_controller_free (Controller *controller)
|
||||
{
|
||||
if (controller->widget)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_data (controller->widget, controller);
|
||||
|
||||
g_clear_weak_pointer (&controller->widget);
|
||||
}
|
||||
|
||||
g_slice_free (Controller, controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_set_line (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDrawable *drawable;
|
||||
|
||||
if (! controller->widget)
|
||||
return;
|
||||
|
||||
tool = PIKA_TOOL (controller->filter_tool);
|
||||
drawable = tool->drawables->data;
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (PIKA_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
x1 += off_x + area->x;
|
||||
y1 += off_y + area->y;
|
||||
x2 += off_x + area->x;
|
||||
y2 += off_y + area->y;
|
||||
}
|
||||
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_line_changed,
|
||||
controller);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"x1", x1,
|
||||
"y1", y1,
|
||||
"x2", x2,
|
||||
"y2", y2,
|
||||
NULL);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_line_changed,
|
||||
controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_line_changed (PikaToolWidget *widget,
|
||||
Controller *controller)
|
||||
{
|
||||
PikaFilterTool *filter_tool = controller->filter_tool;
|
||||
PikaControllerLineCallback line_callback;
|
||||
gdouble x1, y1, x2, y2;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
|
||||
line_callback = (PikaControllerLineCallback) controller->creator_callback;
|
||||
|
||||
g_object_get (widget,
|
||||
"x1", &x1,
|
||||
"y1", &y1,
|
||||
"x2", &x2,
|
||||
"y2", &y2,
|
||||
NULL);
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
x1 -= off_x + area.x;
|
||||
y1 -= off_y + area.y;
|
||||
x2 -= off_x + area.x;
|
||||
y2 -= off_y + area.y;
|
||||
|
||||
line_callback (controller->creator_data,
|
||||
&area, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_set_slider_line (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2,
|
||||
const PikaControllerSlider *sliders,
|
||||
gint n_sliders)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDrawable *drawable;
|
||||
|
||||
if (! controller->widget)
|
||||
return;
|
||||
|
||||
tool = PIKA_TOOL (controller->filter_tool);
|
||||
drawable = tool->drawables->data;
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (PIKA_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
x1 += off_x + area->x;
|
||||
y1 += off_y + area->y;
|
||||
x2 += off_x + area->x;
|
||||
y2 += off_y + area->y;
|
||||
}
|
||||
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_slider_line_changed,
|
||||
controller);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"x1", x1,
|
||||
"y1", y1,
|
||||
"x2", x2,
|
||||
"y2", y2,
|
||||
NULL);
|
||||
|
||||
pika_tool_line_set_sliders (PIKA_TOOL_LINE (controller->widget),
|
||||
sliders, n_sliders);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_slider_line_changed,
|
||||
controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_slider_line_changed (PikaToolWidget *widget,
|
||||
Controller *controller)
|
||||
{
|
||||
PikaFilterTool *filter_tool = controller->filter_tool;
|
||||
PikaControllerSliderLineCallback slider_line_callback;
|
||||
gdouble x1, y1, x2, y2;
|
||||
const PikaControllerSlider *sliders;
|
||||
gint n_sliders;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
|
||||
slider_line_callback =
|
||||
(PikaControllerSliderLineCallback) controller->creator_callback;
|
||||
|
||||
g_object_get (widget,
|
||||
"x1", &x1,
|
||||
"y1", &y1,
|
||||
"x2", &x2,
|
||||
"y2", &y2,
|
||||
NULL);
|
||||
|
||||
sliders = pika_tool_line_get_sliders (PIKA_TOOL_LINE (controller->widget),
|
||||
&n_sliders);
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
x1 -= off_x + area.x;
|
||||
y1 -= off_y + area.y;
|
||||
x2 -= off_x + area.x;
|
||||
y2 -= off_y + area.y;
|
||||
|
||||
slider_line_callback (controller->creator_data,
|
||||
&area, x1, y1, x2, y2, sliders, n_sliders);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_set_transform_grid (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
const PikaMatrix3 *transform)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDrawable *drawable;
|
||||
gdouble x1 = area->x;
|
||||
gdouble y1 = area->y;
|
||||
gdouble x2 = area->x + area->width;
|
||||
gdouble y2 = area->y + area->height;
|
||||
PikaMatrix3 matrix;
|
||||
|
||||
if (! controller->widget)
|
||||
return;
|
||||
|
||||
tool = PIKA_TOOL (controller->filter_tool);
|
||||
drawable = tool->drawables->data;
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (PIKA_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
x1 += off_x;
|
||||
y1 += off_y;
|
||||
x2 += off_x;
|
||||
y2 += off_y;
|
||||
}
|
||||
|
||||
pika_matrix3_identity (&matrix);
|
||||
pika_matrix3_translate (&matrix, -x1, -y1);
|
||||
pika_matrix3_mult (transform, &matrix);
|
||||
pika_matrix3_translate (&matrix, +x1, +y1);
|
||||
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grid_changed,
|
||||
controller);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"transform", &matrix,
|
||||
"x1", x1,
|
||||
"y1", y1,
|
||||
"x2", x2,
|
||||
"y2", y2,
|
||||
NULL);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grid_changed,
|
||||
controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_transform_grid_changed (PikaToolWidget *widget,
|
||||
Controller *controller)
|
||||
{
|
||||
PikaFilterTool *filter_tool = controller->filter_tool;
|
||||
PikaControllerTransformGridCallback transform_grid_callback;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
PikaMatrix3 *transform;
|
||||
PikaMatrix3 matrix;
|
||||
|
||||
transform_grid_callback =
|
||||
(PikaControllerTransformGridCallback) controller->creator_callback;
|
||||
|
||||
g_object_get (widget,
|
||||
"transform", &transform,
|
||||
NULL);
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
pika_matrix3_identity (&matrix);
|
||||
pika_matrix3_translate (&matrix, +(off_x + area.x), +(off_y + area.y));
|
||||
pika_matrix3_mult (transform, &matrix);
|
||||
pika_matrix3_translate (&matrix, -(off_x + area.x), -(off_y + area.y));
|
||||
|
||||
transform_grid_callback (controller->creator_data,
|
||||
&area, &matrix);
|
||||
|
||||
g_free (transform);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_set_transform_grids (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
const PikaMatrix3 *transforms,
|
||||
gint n_transforms)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDisplayShell *shell;
|
||||
PikaDrawable *drawable;
|
||||
PikaContainer *grids;
|
||||
PikaToolWidget *grid = NULL;
|
||||
gdouble x1 = area->x;
|
||||
gdouble y1 = area->y;
|
||||
gdouble x2 = area->x + area->width;
|
||||
gdouble y2 = area->y + area->height;
|
||||
PikaMatrix3 matrix;
|
||||
gint i;
|
||||
|
||||
if (! controller->widget)
|
||||
return;
|
||||
|
||||
tool = PIKA_TOOL (controller->filter_tool);
|
||||
shell = pika_display_get_shell (tool->display);
|
||||
drawable = tool->drawables->data;
|
||||
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grids_changed,
|
||||
controller);
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (PIKA_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
x1 += off_x;
|
||||
y1 += off_y;
|
||||
x2 += off_x;
|
||||
y2 += off_y;
|
||||
}
|
||||
|
||||
grids = pika_tool_widget_group_get_children (
|
||||
PIKA_TOOL_WIDGET_GROUP (controller->widget));
|
||||
|
||||
if (n_transforms > pika_container_get_n_children (grids))
|
||||
{
|
||||
pika_matrix3_identity (&matrix);
|
||||
|
||||
for (i = pika_container_get_n_children (grids); i < n_transforms; i++)
|
||||
{
|
||||
gdouble pivot_x;
|
||||
gdouble pivot_y;
|
||||
|
||||
grid = pika_tool_transform_grid_new (shell, &matrix, x1, y1, x2, y2);
|
||||
|
||||
if (i > 0 && ! memcmp (&transforms[i], &transforms[i - 1],
|
||||
sizeof (PikaMatrix3)))
|
||||
{
|
||||
g_object_get (pika_container_get_last_child (grids),
|
||||
"pivot-x", &pivot_x,
|
||||
"pivot-y", &pivot_y,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
pivot_x = (x1 + x2) / 2.0;
|
||||
pivot_y = (y1 + y2) / 2.0;
|
||||
|
||||
pika_matrix3_transform_point (&transforms[i],
|
||||
pivot_x, pivot_y,
|
||||
&pivot_x, &pivot_y);
|
||||
}
|
||||
|
||||
g_object_set (grid,
|
||||
"pivot-x", pivot_x,
|
||||
"pivot-y", pivot_y,
|
||||
"inside-function", PIKA_TRANSFORM_FUNCTION_MOVE,
|
||||
"outside-function", PIKA_TRANSFORM_FUNCTION_ROTATE,
|
||||
"use-corner-handles", TRUE,
|
||||
"use-perspective-handles", TRUE,
|
||||
"use-side-handles", TRUE,
|
||||
"use-shear-handles", TRUE,
|
||||
"use-pivot-handle", TRUE,
|
||||
NULL);
|
||||
|
||||
pika_container_add (grids, PIKA_OBJECT (grid));
|
||||
|
||||
g_object_unref (grid);
|
||||
}
|
||||
|
||||
pika_tool_widget_set_focus (grid, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (pika_container_get_n_children (grids) > n_transforms)
|
||||
pika_container_remove (grids, pika_container_get_last_child (grids));
|
||||
}
|
||||
|
||||
for (i = 0; i < n_transforms; i++)
|
||||
{
|
||||
pika_matrix3_identity (&matrix);
|
||||
pika_matrix3_translate (&matrix, -x1, -y1);
|
||||
pika_matrix3_mult (&transforms[i], &matrix);
|
||||
pika_matrix3_translate (&matrix, +x1, +y1);
|
||||
|
||||
g_object_set (pika_container_get_child_by_index (grids, i),
|
||||
"transform", &matrix,
|
||||
"x1", x1,
|
||||
"y1", y1,
|
||||
"x2", x2,
|
||||
"y2", y2,
|
||||
NULL);
|
||||
}
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_transform_grids_changed,
|
||||
controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_transform_grids_changed (PikaToolWidget *widget,
|
||||
Controller *controller)
|
||||
{
|
||||
PikaFilterTool *filter_tool = controller->filter_tool;
|
||||
PikaControllerTransformGridsCallback transform_grids_callback;
|
||||
PikaContainer *grids;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
PikaMatrix3 *transforms;
|
||||
gint n_transforms;
|
||||
gint i;
|
||||
|
||||
transform_grids_callback =
|
||||
(PikaControllerTransformGridsCallback) controller->creator_callback;
|
||||
|
||||
grids = pika_tool_widget_group_get_children (
|
||||
PIKA_TOOL_WIDGET_GROUP (controller->widget));
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
n_transforms = pika_container_get_n_children (grids);
|
||||
transforms = g_new (PikaMatrix3, n_transforms);
|
||||
|
||||
for (i = 0; i < n_transforms; i++)
|
||||
{
|
||||
PikaMatrix3 *transform;
|
||||
|
||||
g_object_get (pika_container_get_child_by_index (grids, i),
|
||||
"transform", &transform,
|
||||
NULL);
|
||||
|
||||
pika_matrix3_identity (&transforms[i]);
|
||||
pika_matrix3_translate (&transforms[i],
|
||||
+(off_x + area.x), +(off_y + area.y));
|
||||
pika_matrix3_mult (transform, &transforms[i]);
|
||||
pika_matrix3_translate (&transforms[i],
|
||||
-(off_x + area.x), -(off_y + area.y));
|
||||
|
||||
g_free (transform);
|
||||
}
|
||||
|
||||
transform_grids_callback (controller->creator_data,
|
||||
&area, transforms, n_transforms);
|
||||
|
||||
g_free (transforms);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_set_gyroscope (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
gdouble yaw,
|
||||
gdouble pitch,
|
||||
gdouble roll,
|
||||
gdouble zoom,
|
||||
gboolean invert)
|
||||
{
|
||||
if (! controller->widget)
|
||||
return;
|
||||
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_gyroscope_changed,
|
||||
controller);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"yaw", yaw,
|
||||
"pitch", pitch,
|
||||
"roll", roll,
|
||||
"zoom", zoom,
|
||||
"invert", invert,
|
||||
NULL);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_gyroscope_changed,
|
||||
controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_gyroscope_changed (PikaToolWidget *widget,
|
||||
Controller *controller)
|
||||
{
|
||||
PikaFilterTool *filter_tool = controller->filter_tool;
|
||||
PikaControllerGyroscopeCallback gyroscope_callback;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
gdouble yaw;
|
||||
gdouble pitch;
|
||||
gdouble roll;
|
||||
gdouble zoom;
|
||||
gboolean invert;
|
||||
|
||||
gyroscope_callback =
|
||||
(PikaControllerGyroscopeCallback) controller->creator_callback;
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
g_object_get (widget,
|
||||
"yaw", &yaw,
|
||||
"pitch", &pitch,
|
||||
"roll", &roll,
|
||||
"zoom", &zoom,
|
||||
"invert", &invert,
|
||||
NULL);
|
||||
|
||||
gyroscope_callback (controller->creator_data,
|
||||
&area, yaw, pitch, roll, zoom, invert);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_set_focus (Controller *controller,
|
||||
GeglRectangle *area,
|
||||
PikaLimitType type,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gdouble radius,
|
||||
gdouble aspect_ratio,
|
||||
gdouble angle,
|
||||
gdouble inner_limit,
|
||||
gdouble midpoint)
|
||||
{
|
||||
PikaTool *tool;
|
||||
PikaDrawable *drawable;
|
||||
|
||||
if (! controller->widget)
|
||||
return;
|
||||
|
||||
tool = PIKA_TOOL (controller->filter_tool);
|
||||
drawable = tool->drawables->data;
|
||||
|
||||
if (drawable)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (PIKA_ITEM (drawable), &off_x, &off_y);
|
||||
|
||||
x += off_x + area->x;
|
||||
y += off_y + area->y;
|
||||
}
|
||||
|
||||
g_signal_handlers_block_by_func (controller->widget,
|
||||
pika_filter_tool_focus_changed,
|
||||
controller);
|
||||
|
||||
g_object_set (controller->widget,
|
||||
"type", type,
|
||||
"x", x,
|
||||
"y", y,
|
||||
"radius", radius,
|
||||
"aspect-ratio", aspect_ratio,
|
||||
"angle", angle,
|
||||
"inner-limit", inner_limit,
|
||||
"midpoint", midpoint,
|
||||
NULL);
|
||||
|
||||
g_signal_handlers_unblock_by_func (controller->widget,
|
||||
pika_filter_tool_focus_changed,
|
||||
controller);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_filter_tool_focus_changed (PikaToolWidget *widget,
|
||||
Controller *controller)
|
||||
{
|
||||
PikaFilterTool *filter_tool = controller->filter_tool;
|
||||
PikaControllerFocusCallback focus_callback;
|
||||
PikaLimitType type;
|
||||
gdouble x, y;
|
||||
gdouble radius;
|
||||
gdouble aspect_ratio;
|
||||
gdouble angle;
|
||||
gdouble inner_limit;
|
||||
gdouble midpoint;
|
||||
gint off_x, off_y;
|
||||
GeglRectangle area;
|
||||
|
||||
focus_callback = (PikaControllerFocusCallback) controller->creator_callback;
|
||||
|
||||
g_object_get (widget,
|
||||
"type", &type,
|
||||
"x", &x,
|
||||
"y", &y,
|
||||
"radius", &radius,
|
||||
"aspect-ratio", &aspect_ratio,
|
||||
"angle", &angle,
|
||||
"inner-limit", &inner_limit,
|
||||
"midpoint", &midpoint,
|
||||
NULL);
|
||||
|
||||
pika_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
|
||||
|
||||
x -= off_x + area.x;
|
||||
y -= off_y + area.y;
|
||||
|
||||
focus_callback (controller->creator_data,
|
||||
&area,
|
||||
type,
|
||||
x,
|
||||
y,
|
||||
radius,
|
||||
aspect_ratio,
|
||||
angle,
|
||||
inner_limit,
|
||||
midpoint);
|
||||
}
|
||||
40
app/tools/pikafiltertool-widgets.h
Normal file
40
app/tools/pikafiltertool-widgets.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikafiltertool-widgets.h
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FILTER_TOOL_WIDGETS_H__
|
||||
#define __PIKA_FILTER_TOOL_WIDGETS_H__
|
||||
|
||||
|
||||
PikaToolWidget * pika_filter_tool_create_widget (PikaFilterTool *filter_tool,
|
||||
PikaControllerType controller_type,
|
||||
const gchar *status_title,
|
||||
GCallback callback,
|
||||
gpointer callback_data,
|
||||
GCallback *set_func,
|
||||
gpointer *set_func_data);
|
||||
|
||||
void pika_filter_tool_reset_widget (PikaFilterTool *filter_tool,
|
||||
PikaToolWidget *widget);
|
||||
|
||||
|
||||
#endif /* __PIKA_FILTER_TOOL_WIDGETS_H__ */
|
||||
2057
app/tools/pikafiltertool.c
Normal file
2057
app/tools/pikafiltertool.c
Normal file
File diff suppressed because it is too large
Load Diff
153
app/tools/pikafiltertool.h
Normal file
153
app/tools/pikafiltertool.h
Normal file
@ -0,0 +1,153 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FILTER_TOOL_H__
|
||||
#define __PIKA_FILTER_TOOL_H__
|
||||
|
||||
|
||||
#include "pikacolortool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FILTER_TOOL (pika_filter_tool_get_type ())
|
||||
#define PIKA_FILTER_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FILTER_TOOL, PikaFilterTool))
|
||||
#define PIKA_FILTER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FILTER_TOOL, PikaFilterToolClass))
|
||||
#define PIKA_IS_FILTER_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FILTER_TOOL))
|
||||
#define PIKA_IS_FILTER_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FILTER_TOOL))
|
||||
#define PIKA_FILTER_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FILTER_TOOL, PikaFilterToolClass))
|
||||
|
||||
#define PIKA_FILTER_TOOL_GET_OPTIONS(t) (PIKA_FILTER_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaFilterToolClass PikaFilterToolClass;
|
||||
|
||||
struct _PikaFilterTool
|
||||
{
|
||||
PikaColorTool parent_instance;
|
||||
|
||||
GeglNode *operation;
|
||||
GObject *config;
|
||||
GObject *default_config;
|
||||
PikaContainer *settings;
|
||||
|
||||
gchar *description;
|
||||
|
||||
gboolean has_settings;
|
||||
|
||||
PikaDrawableFilter *filter;
|
||||
|
||||
PikaGuide *preview_guide;
|
||||
|
||||
gpointer pick_identifier;
|
||||
gboolean pick_abyss;
|
||||
|
||||
/* dialog */
|
||||
gboolean overlay;
|
||||
PikaToolGui *gui;
|
||||
GtkWidget *settings_box;
|
||||
GtkWidget *controller_toggle;
|
||||
GtkWidget *operation_settings_box;
|
||||
GtkWidget *clip_combo;
|
||||
GtkWidget *region_combo;
|
||||
GtkWidget *active_picker;
|
||||
|
||||
/* widget */
|
||||
PikaToolWidget *widget;
|
||||
PikaToolWidget *grab_widget;
|
||||
};
|
||||
|
||||
struct _PikaFilterToolClass
|
||||
{
|
||||
PikaColorToolClass parent_class;
|
||||
|
||||
/* virtual functions */
|
||||
gchar * (* get_operation) (PikaFilterTool *filter_tool,
|
||||
gchar **description);
|
||||
void (* dialog) (PikaFilterTool *filter_tool);
|
||||
void (* reset) (PikaFilterTool *filter_tool);
|
||||
void (* set_config) (PikaFilterTool *filter_tool,
|
||||
PikaConfig *config);
|
||||
void (* config_notify) (PikaFilterTool *filter_tool,
|
||||
PikaConfig *config,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
gboolean (* settings_import) (PikaFilterTool *filter_tool,
|
||||
GInputStream *input,
|
||||
GError **error);
|
||||
gboolean (* settings_export) (PikaFilterTool *filter_tool,
|
||||
GOutputStream *output,
|
||||
GError **error);
|
||||
|
||||
void (* region_changed) (PikaFilterTool *filter_tool);
|
||||
void (* color_picked) (PikaFilterTool *filter_tool,
|
||||
gpointer identifier,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
const Babl *sample_format,
|
||||
const PikaRGB *color);
|
||||
};
|
||||
|
||||
|
||||
GType pika_filter_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_filter_tool_get_operation (PikaFilterTool *filter_tool);
|
||||
|
||||
void pika_filter_tool_set_config (PikaFilterTool *filter_tool,
|
||||
PikaConfig *config);
|
||||
|
||||
void pika_filter_tool_edit_as (PikaFilterTool *filter_tool,
|
||||
const gchar *new_tool_id,
|
||||
PikaConfig *config);
|
||||
|
||||
gboolean pika_filter_tool_on_guide (PikaFilterTool *filter_tool,
|
||||
const PikaCoords *coords,
|
||||
PikaDisplay *display);
|
||||
|
||||
GtkWidget * pika_filter_tool_dialog_get_vbox (PikaFilterTool *filter_tool);
|
||||
|
||||
void pika_filter_tool_enable_color_picking (PikaFilterTool *filter_tool,
|
||||
gpointer identifier,
|
||||
gboolean pick_abyss);
|
||||
void pika_filter_tool_disable_color_picking (PikaFilterTool *filter_tool);
|
||||
|
||||
GtkWidget * pika_filter_tool_add_color_picker (PikaFilterTool *filter_tool,
|
||||
gpointer identifier,
|
||||
const gchar *icon_name,
|
||||
const gchar *tooltip,
|
||||
gboolean pick_abyss,
|
||||
PikaPickerCallback callback,
|
||||
gpointer callback_data);
|
||||
GCallback pika_filter_tool_add_controller (PikaFilterTool *filter_tool,
|
||||
PikaControllerType controller_type,
|
||||
const gchar *status_title,
|
||||
GCallback callback,
|
||||
gpointer callback_data,
|
||||
gpointer *set_func_data);
|
||||
|
||||
void pika_filter_tool_set_widget (PikaFilterTool *filter_tool,
|
||||
PikaToolWidget *widget);
|
||||
|
||||
gboolean pika_filter_tool_get_drawable_area (PikaFilterTool *filter_tool,
|
||||
gint *drawable_offset_x,
|
||||
gint *drawable_offset_y,
|
||||
GeglRectangle *drawable_area);
|
||||
|
||||
|
||||
#endif /* __PIKA_FILTER_TOOL_H__ */
|
||||
167
app/tools/pikaflipoptions.c
Normal file
167
app/tools/pikaflipoptions.c
Normal file
@ -0,0 +1,167 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikaflipoptions.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FLIP_TYPE
|
||||
};
|
||||
|
||||
|
||||
static void pika_flip_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_flip_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaFlipOptions, pika_flip_options,
|
||||
PIKA_TYPE_TRANSFORM_OPTIONS)
|
||||
|
||||
|
||||
static void
|
||||
pika_flip_options_class_init (PikaFlipOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_flip_options_set_property;
|
||||
object_class->get_property = pika_flip_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_FLIP_TYPE,
|
||||
"flip-type",
|
||||
_("Flip Type"),
|
||||
_("Direction of flipping"),
|
||||
PIKA_TYPE_ORIENTATION_TYPE,
|
||||
PIKA_ORIENTATION_HORIZONTAL,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_options_init (PikaFlipOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaFlipOptions *options = PIKA_FLIP_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FLIP_TYPE:
|
||||
options->flip_type = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaFlipOptions *options = PIKA_FLIP_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FLIP_TYPE:
|
||||
g_value_set_enum (value, options->flip_type);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_flip_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
PikaFlipOptions *options = PIKA_FLIP_OPTIONS (tool_options);
|
||||
PikaTransformOptions *tr_options = PIKA_TRANSFORM_OPTIONS (tool_options);
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *combo;
|
||||
gchar *str;
|
||||
GtkListStore *clip_model;
|
||||
GdkModifierType toggle_mask;
|
||||
|
||||
vbox = pika_transform_options_gui (tool_options, FALSE, FALSE, FALSE);
|
||||
|
||||
toggle_mask = pika_get_toggle_behavior_mask ();
|
||||
|
||||
/* tool toggle */
|
||||
str = g_strdup_printf (_("Direction (%s)"),
|
||||
pika_get_mod_string (toggle_mask));
|
||||
|
||||
frame = pika_prop_enum_radio_frame_new (config, "flip-type",
|
||||
str,
|
||||
PIKA_ORIENTATION_HORIZONTAL,
|
||||
PIKA_ORIENTATION_VERTICAL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
g_free (str);
|
||||
|
||||
options->direction_frame = frame;
|
||||
|
||||
/* the clipping menu */
|
||||
clip_model = pika_enum_store_new_with_range (PIKA_TYPE_TRANSFORM_RESIZE,
|
||||
PIKA_TRANSFORM_RESIZE_ADJUST,
|
||||
PIKA_TRANSFORM_RESIZE_CLIP);
|
||||
|
||||
combo = pika_prop_enum_combo_box_new (config, "clip", 0, 0);
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (clip_model));
|
||||
pika_int_combo_box_set_active (PIKA_INT_COMBO_BOX (combo), tr_options->clip);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Clipping"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
||||
|
||||
g_object_unref (clip_model);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
56
app/tools/pikaflipoptions.h
Normal file
56
app/tools/pikaflipoptions.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FLIP_OPTIONS_H__
|
||||
#define __PIKA_FLIP_OPTIONS_H__
|
||||
|
||||
|
||||
#include "pikatransformoptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FLIP_OPTIONS (pika_flip_options_get_type ())
|
||||
#define PIKA_FLIP_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FLIP_OPTIONS, PikaFlipOptions))
|
||||
#define PIKA_FLIP_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FLIP_OPTIONS, PikaFlipOptionsClass))
|
||||
#define PIKA_IS_FLIP_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FLIP_OPTIONS))
|
||||
#define PIKA_IS_FLIP_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FLIP_OPTIONS))
|
||||
#define PIKA_FLIP_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FLIP_OPTIONS, PikaFlipOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaFlipOptions PikaFlipOptions;
|
||||
typedef struct _PikaToolOptionsClass PikaFlipOptionsClass;
|
||||
|
||||
struct _PikaFlipOptions
|
||||
{
|
||||
PikaTransformOptions parent_instance;
|
||||
|
||||
PikaOrientationType flip_type;
|
||||
|
||||
/* options gui */
|
||||
GtkWidget *direction_frame;
|
||||
};
|
||||
|
||||
|
||||
GType pika_flip_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_flip_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_FLIP_OPTIONS_H__ */
|
||||
454
app/tools/pikafliptool.c
Normal file
454
app/tools/pikafliptool.c
Normal file
@ -0,0 +1,454 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikadisplayconfig.h"
|
||||
|
||||
#include "core/pikadrawable-transform.h"
|
||||
#include "core/pikaguide.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-flip.h"
|
||||
#include "core/pikaimage-item-list.h"
|
||||
#include "core/pikaimage-pick-item.h"
|
||||
#include "core/pikalayer.h"
|
||||
#include "core/pikalayermask.h"
|
||||
#include "core/pikapickable.h"
|
||||
#include "core/pikaprogress.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "display/pikacanvasitem.h"
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikadisplayshell.h"
|
||||
#include "display/pikadisplayshell-appearance.h"
|
||||
|
||||
#include "pikaflipoptions.h"
|
||||
#include "pikafliptool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_flip_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_flip_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
static void pika_flip_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display);
|
||||
static void pika_flip_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_flip_tool_draw (PikaDrawTool *draw_tool);
|
||||
|
||||
static gchar * pika_flip_tool_get_undo_desc (PikaTransformTool *tr_tool);
|
||||
static GeglBuffer * pika_flip_tool_transform (PikaTransformTool *tr_tool,
|
||||
GList *objects,
|
||||
GeglBuffer *orig_buffer,
|
||||
gint orig_offset_x,
|
||||
gint orig_offset_y,
|
||||
PikaColorProfile **buffer_profile,
|
||||
gint *new_offset_x,
|
||||
gint *new_offset_y);
|
||||
|
||||
static PikaOrientationType pika_flip_tool_get_flip_type (PikaFlipTool *flip);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaFlipTool, pika_flip_tool, PIKA_TYPE_TRANSFORM_TOOL)
|
||||
|
||||
#define parent_class pika_flip_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_flip_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_FLIP_TOOL,
|
||||
PIKA_TYPE_FLIP_OPTIONS,
|
||||
pika_flip_options_gui,
|
||||
PIKA_CONTEXT_PROP_MASK_BACKGROUND,
|
||||
"pika-flip-tool",
|
||||
_("Flip"),
|
||||
_("Flip Tool: "
|
||||
"Reverse the layer, selection or path horizontally or vertically"),
|
||||
N_("_Flip"), "<shift>F",
|
||||
NULL, PIKA_HELP_TOOL_FLIP,
|
||||
PIKA_ICON_TOOL_FLIP,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_class_init (PikaFlipToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaDrawToolClass *draw_tool_class = PIKA_DRAW_TOOL_CLASS (klass);
|
||||
PikaTransformToolClass *tr_class = PIKA_TRANSFORM_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->button_press = pika_flip_tool_button_press;
|
||||
tool_class->modifier_key = pika_flip_tool_modifier_key;
|
||||
tool_class->oper_update = pika_flip_tool_oper_update;
|
||||
tool_class->cursor_update = pika_flip_tool_cursor_update;
|
||||
|
||||
draw_tool_class->draw = pika_flip_tool_draw;
|
||||
|
||||
tr_class->get_undo_desc = pika_flip_tool_get_undo_desc;
|
||||
tr_class->transform = pika_flip_tool_transform;
|
||||
|
||||
tr_class->undo_desc = C_("undo-type", "Flip");
|
||||
tr_class->progress_text = _("Flipping");
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_init (PikaFlipTool *flip_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (flip_tool);
|
||||
|
||||
pika_tool_control_set_snap_to (tool->control, FALSE);
|
||||
pika_tool_control_set_precision (tool->control,
|
||||
PIKA_CURSOR_PRECISION_PIXEL_CENTER);
|
||||
pika_tool_control_set_cursor (tool->control, PIKA_CURSOR_MOUSE);
|
||||
pika_tool_control_set_toggle_cursor (tool->control, PIKA_CURSOR_MOUSE);
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_FLIP_HORIZONTAL);
|
||||
pika_tool_control_set_toggle_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_FLIP_VERTICAL);
|
||||
|
||||
flip_tool->guide = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaTransformTool *tr_tool = PIKA_TRANSFORM_TOOL (tool);
|
||||
|
||||
tool->display = display;
|
||||
|
||||
pika_transform_tool_transform (tr_tool, display);
|
||||
|
||||
pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaFlipOptions *options = PIKA_FLIP_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
if (key == pika_get_toggle_behavior_mask ())
|
||||
{
|
||||
switch (options->flip_type)
|
||||
{
|
||||
case PIKA_ORIENTATION_HORIZONTAL:
|
||||
g_object_set (options,
|
||||
"flip-type", PIKA_ORIENTATION_VERTICAL,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case PIKA_ORIENTATION_VERTICAL:
|
||||
g_object_set (options,
|
||||
"flip-type", PIKA_ORIENTATION_HORIZONTAL,
|
||||
NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_oper_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
gboolean proximity,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaFlipTool *flip = PIKA_FLIP_TOOL (tool);
|
||||
PikaDrawTool *draw_tool = PIKA_DRAW_TOOL (tool);
|
||||
PikaFlipOptions *options = PIKA_FLIP_TOOL_GET_OPTIONS (tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
PikaGuide *guide = NULL;
|
||||
|
||||
if (pika_display_shell_get_show_guides (shell) &&
|
||||
proximity)
|
||||
{
|
||||
gint snap_distance = display->config->snap_distance;
|
||||
|
||||
guide = pika_image_pick_guide (image, coords->x, coords->y,
|
||||
FUNSCALEX (shell, snap_distance),
|
||||
FUNSCALEY (shell, snap_distance));
|
||||
}
|
||||
|
||||
if (flip->guide != guide ||
|
||||
(guide && ! pika_draw_tool_is_active (draw_tool)))
|
||||
{
|
||||
pika_draw_tool_pause (draw_tool);
|
||||
|
||||
if (pika_draw_tool_is_active (draw_tool) &&
|
||||
draw_tool->display != display)
|
||||
pika_draw_tool_stop (draw_tool);
|
||||
|
||||
flip->guide = guide;
|
||||
|
||||
if (! pika_draw_tool_is_active (draw_tool))
|
||||
pika_draw_tool_start (draw_tool, display);
|
||||
|
||||
pika_draw_tool_resume (draw_tool);
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive (options->direction_frame, guide == NULL);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->oper_update (tool,
|
||||
coords, state, proximity,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_cursor_update (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaTransformTool *tr_tool = PIKA_TRANSFORM_TOOL (tool);
|
||||
PikaFlipTool *flip = PIKA_FLIP_TOOL (tool);
|
||||
GList *selected_objects;
|
||||
|
||||
selected_objects = pika_transform_tool_check_selected_objects (tr_tool, display, NULL);
|
||||
|
||||
if (! selected_objects)
|
||||
{
|
||||
pika_tool_set_cursor (tool, display,
|
||||
pika_tool_control_get_cursor (tool->control),
|
||||
pika_tool_control_get_tool_cursor (tool->control),
|
||||
PIKA_CURSOR_MODIFIER_BAD);
|
||||
return;
|
||||
}
|
||||
g_list_free (selected_objects);
|
||||
|
||||
pika_tool_control_set_toggled (tool->control,
|
||||
pika_flip_tool_get_flip_type (flip) ==
|
||||
PIKA_ORIENTATION_VERTICAL);
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_flip_tool_draw (PikaDrawTool *draw_tool)
|
||||
{
|
||||
PikaFlipTool *flip = PIKA_FLIP_TOOL (draw_tool);
|
||||
|
||||
if (flip->guide)
|
||||
{
|
||||
PikaCanvasItem *item;
|
||||
PikaGuideStyle style;
|
||||
|
||||
style = pika_guide_get_style (flip->guide);
|
||||
|
||||
item = pika_draw_tool_add_guide (draw_tool,
|
||||
pika_guide_get_orientation (flip->guide),
|
||||
pika_guide_get_position (flip->guide),
|
||||
style);
|
||||
pika_canvas_item_set_highlight (item, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
pika_flip_tool_get_undo_desc (PikaTransformTool *tr_tool)
|
||||
{
|
||||
PikaFlipTool *flip = PIKA_FLIP_TOOL (tr_tool);
|
||||
|
||||
switch (pika_flip_tool_get_flip_type (flip))
|
||||
{
|
||||
case PIKA_ORIENTATION_HORIZONTAL:
|
||||
return g_strdup (C_("undo-type", "Flip horizontally"));
|
||||
|
||||
case PIKA_ORIENTATION_VERTICAL:
|
||||
return g_strdup (C_("undo-type", "Flip vertically"));
|
||||
|
||||
default:
|
||||
/* probably this is not actually reached today, but
|
||||
* could be if someone defined FLIP_DIAGONAL, say...
|
||||
*/
|
||||
return PIKA_TRANSFORM_TOOL_CLASS (parent_class)->get_undo_desc (tr_tool);
|
||||
}
|
||||
}
|
||||
|
||||
static GeglBuffer *
|
||||
pika_flip_tool_transform (PikaTransformTool *tr_tool,
|
||||
GList *objects,
|
||||
GeglBuffer *orig_buffer,
|
||||
gint orig_offset_x,
|
||||
gint orig_offset_y,
|
||||
PikaColorProfile **buffer_profile,
|
||||
gint *new_offset_x,
|
||||
gint *new_offset_y)
|
||||
{
|
||||
PikaFlipTool *flip = PIKA_FLIP_TOOL (tr_tool);
|
||||
PikaFlipOptions *options = PIKA_FLIP_TOOL_GET_OPTIONS (tr_tool);
|
||||
PikaTransformOptions *tr_options = PIKA_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
|
||||
PikaContext *context = PIKA_CONTEXT (options);
|
||||
PikaOrientationType flip_type = PIKA_ORIENTATION_UNKNOWN;
|
||||
gdouble axis = 0.0;
|
||||
gboolean clip_result = FALSE;
|
||||
GeglBuffer *ret = NULL;
|
||||
|
||||
flip_type = pika_flip_tool_get_flip_type (flip);
|
||||
|
||||
if (flip->guide)
|
||||
{
|
||||
axis = pika_guide_get_position (flip->guide);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (flip_type)
|
||||
{
|
||||
case PIKA_ORIENTATION_HORIZONTAL:
|
||||
axis = ((gdouble) tr_tool->x1 +
|
||||
(gdouble) (tr_tool->x2 - tr_tool->x1) / 2.0);
|
||||
break;
|
||||
|
||||
case PIKA_ORIENTATION_VERTICAL:
|
||||
axis = ((gdouble) tr_tool->y1 +
|
||||
(gdouble) (tr_tool->y2 - tr_tool->y1) / 2.0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (tr_options->clip)
|
||||
{
|
||||
case PIKA_TRANSFORM_RESIZE_ADJUST:
|
||||
clip_result = FALSE;
|
||||
break;
|
||||
|
||||
case PIKA_TRANSFORM_RESIZE_CLIP:
|
||||
clip_result = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
if (orig_buffer)
|
||||
{
|
||||
/* this happens when transforming a selection cut out of a
|
||||
* normal drawable
|
||||
*/
|
||||
|
||||
g_return_val_if_fail (PIKA_IS_DRAWABLE (objects->data), NULL);
|
||||
|
||||
ret = pika_drawable_transform_buffer_flip (PIKA_DRAWABLE (objects->data),
|
||||
context,
|
||||
orig_buffer,
|
||||
orig_offset_x,
|
||||
orig_offset_y,
|
||||
flip_type, axis,
|
||||
clip_result,
|
||||
buffer_profile,
|
||||
new_offset_x,
|
||||
new_offset_y);
|
||||
}
|
||||
else if (g_list_length (objects) == 1 && PIKA_IS_IMAGE (objects->data))
|
||||
{
|
||||
/* this happens for images */
|
||||
PikaTransformToolClass *tr_class = PIKA_TRANSFORM_TOOL_GET_CLASS (tr_tool);
|
||||
PikaProgress *progress;
|
||||
|
||||
progress = pika_progress_start (PIKA_PROGRESS (tr_tool), FALSE,
|
||||
"%s", tr_class->progress_text);
|
||||
|
||||
pika_image_flip_full (PIKA_IMAGE (objects->data), context,
|
||||
flip_type, axis, clip_result,
|
||||
progress);
|
||||
|
||||
if (progress)
|
||||
pika_progress_end (progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this happens for entire drawables, paths and layer groups */
|
||||
pika_image_item_list_flip (pika_item_get_image (objects->data),
|
||||
objects, context,
|
||||
flip_type, axis, clip_result);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PikaOrientationType
|
||||
pika_flip_tool_get_flip_type (PikaFlipTool *flip)
|
||||
{
|
||||
PikaFlipOptions *options = PIKA_FLIP_TOOL_GET_OPTIONS (flip);
|
||||
|
||||
if (flip->guide)
|
||||
{
|
||||
switch (pika_guide_get_orientation (flip->guide))
|
||||
{
|
||||
case PIKA_ORIENTATION_HORIZONTAL:
|
||||
return PIKA_ORIENTATION_VERTICAL;
|
||||
|
||||
case PIKA_ORIENTATION_VERTICAL:
|
||||
return PIKA_ORIENTATION_HORIZONTAL;
|
||||
|
||||
default:
|
||||
return pika_guide_get_orientation (flip->guide);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return options->flip_type;
|
||||
}
|
||||
}
|
||||
61
app/tools/pikafliptool.h
Normal file
61
app/tools/pikafliptool.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FLIP_TOOL_H__
|
||||
#define __PIKA_FLIP_TOOL_H__
|
||||
|
||||
|
||||
#include "pikatransformtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FLIP_TOOL (pika_flip_tool_get_type ())
|
||||
#define PIKA_FLIP_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FLIP_TOOL, PikaFlipTool))
|
||||
#define PIKA_FLIP_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FLIP_TOOL, PikaFlipToolClass))
|
||||
#define PIKA_IS_FLIP_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FLIP_TOOL))
|
||||
#define PIKA_IS_FLIP_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FLIP_TOOL))
|
||||
#define PIKA_FLIP_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FLIP_TOOL, PikaFlipToolClass))
|
||||
|
||||
#define PIKA_FLIP_TOOL_GET_OPTIONS(t) (PIKA_FLIP_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaFlipTool PikaFlipTool;
|
||||
typedef struct _PikaFlipToolClass PikaFlipToolClass;
|
||||
|
||||
struct _PikaFlipTool
|
||||
{
|
||||
PikaTransformTool parent_instance;
|
||||
|
||||
PikaGuide *guide;
|
||||
};
|
||||
|
||||
struct _PikaFlipToolClass
|
||||
{
|
||||
PikaTransformToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_flip_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_flip_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_FLIP_TOOL_H__ */
|
||||
395
app/tools/pikaforegroundselectoptions.c
Normal file
395
app/tools/pikaforegroundselectoptions.c
Normal file
@ -0,0 +1,395 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikacolorpanel.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-constructors.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikaforegroundselectoptions.h"
|
||||
#include "pikatooloptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/*
|
||||
* for matting-global: iterations int
|
||||
* for matting-levin: levels int, active levels int
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DRAW_MODE,
|
||||
PROP_PREVIEW_MODE,
|
||||
PROP_STROKE_WIDTH,
|
||||
PROP_MASK_COLOR,
|
||||
PROP_ENGINE,
|
||||
PROP_ITERATIONS,
|
||||
PROP_LEVELS,
|
||||
PROP_ACTIVE_LEVELS
|
||||
};
|
||||
|
||||
|
||||
static void pika_foreground_select_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_foreground_select_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaForegroundSelectOptions, pika_foreground_select_options,
|
||||
PIKA_TYPE_SELECTION_OPTIONS)
|
||||
|
||||
|
||||
static void
|
||||
pika_foreground_select_options_class_init (PikaForegroundSelectOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaRGB blue = {0.0, 0.0, 1.0, 0.5};
|
||||
|
||||
object_class->set_property = pika_foreground_select_options_set_property;
|
||||
object_class->get_property = pika_foreground_select_options_get_property;
|
||||
|
||||
/* override the antialias default value from PikaSelectionOptions */
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_DRAW_MODE,
|
||||
"draw-mode",
|
||||
_("Draw Mode"),
|
||||
_("Paint over areas to mark color values for "
|
||||
"inclusion or exclusion from selection"),
|
||||
PIKA_TYPE_MATTING_DRAW_MODE,
|
||||
PIKA_MATTING_DRAW_MODE_FOREGROUND,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_PREVIEW_MODE,
|
||||
"preview-mode",
|
||||
_("Preview Mode"),
|
||||
_("Preview Mode"),
|
||||
PIKA_TYPE_MATTING_PREVIEW_MODE,
|
||||
PIKA_MATTING_PREVIEW_MODE_ON_COLOR,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_STROKE_WIDTH,
|
||||
"stroke-width",
|
||||
_("Stroke width"),
|
||||
_("Size of the brush used for refinements"),
|
||||
1, 6000, 10,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_RGB (object_class, PROP_MASK_COLOR,
|
||||
"mask-color",
|
||||
_("Preview color"),
|
||||
_("Color of selection preview mask"),
|
||||
PIKA_TYPE_RGB,
|
||||
&blue,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_ENGINE,
|
||||
"engine",
|
||||
_("Engine"),
|
||||
_("Matting engine to use"),
|
||||
PIKA_TYPE_MATTING_ENGINE,
|
||||
PIKA_MATTING_ENGINE_LEVIN,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_LEVELS,
|
||||
"levels",
|
||||
_("Levels"),
|
||||
_("Number of downsampled levels to use"),
|
||||
1, 10, 2,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_ACTIVE_LEVELS,
|
||||
"active-levels",
|
||||
_("Active levels"),
|
||||
_("Number of levels to perform solving"),
|
||||
1, 10, 2,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_ITERATIONS,
|
||||
"iterations",
|
||||
_("Iterations"),
|
||||
_("Number of iterations to perform"),
|
||||
1, 10, 2,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_options_init (PikaForegroundSelectOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaForegroundSelectOptions *options = PIKA_FOREGROUND_SELECT_OPTIONS (object);
|
||||
PikaRGB *color;
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DRAW_MODE:
|
||||
options->draw_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_MODE:
|
||||
options->preview_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_STROKE_WIDTH:
|
||||
options->stroke_width = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_MASK_COLOR:
|
||||
color = g_value_get_boxed (value);
|
||||
options->mask_color = *color;
|
||||
break;
|
||||
|
||||
case PROP_ENGINE:
|
||||
options->engine = g_value_get_enum (value);
|
||||
if ((options->engine == PIKA_MATTING_ENGINE_LEVIN) &&
|
||||
!(gegl_has_operation ("gegl:matting-levin")))
|
||||
{
|
||||
options->engine = PIKA_MATTING_ENGINE_GLOBAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_LEVELS:
|
||||
options->levels = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_ACTIVE_LEVELS:
|
||||
options->active_levels = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_ITERATIONS:
|
||||
options->iterations = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaForegroundSelectOptions *options = PIKA_FOREGROUND_SELECT_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DRAW_MODE:
|
||||
g_value_set_enum (value, options->draw_mode);
|
||||
break;
|
||||
|
||||
case PROP_PREVIEW_MODE:
|
||||
g_value_set_enum (value, options->preview_mode);
|
||||
break;
|
||||
|
||||
case PROP_STROKE_WIDTH:
|
||||
g_value_set_int (value, options->stroke_width);
|
||||
break;
|
||||
|
||||
case PROP_MASK_COLOR:
|
||||
g_value_set_boxed (value, &options->mask_color);
|
||||
break;
|
||||
|
||||
case PROP_ENGINE:
|
||||
g_value_set_enum (value, options->engine);
|
||||
break;
|
||||
|
||||
case PROP_LEVELS:
|
||||
g_value_set_int (value, options->levels);
|
||||
break;
|
||||
|
||||
case PROP_ACTIVE_LEVELS:
|
||||
g_value_set_int (value, options->active_levels);
|
||||
break;
|
||||
|
||||
case PROP_ITERATIONS:
|
||||
g_value_set_int (value, options->iterations);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_options_reset_stroke_width (GtkWidget *button,
|
||||
PikaToolOptions *tool_options)
|
||||
{
|
||||
g_object_set (tool_options, "stroke-width", 10, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_foreground_select_options_sync_engine (GBinding *binding,
|
||||
const GValue *source_value,
|
||||
GValue *target_value,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint type = g_value_get_enum (source_value);
|
||||
|
||||
g_value_set_boolean (target_value,
|
||||
type == GPOINTER_TO_INT (user_data));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_foreground_select_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_selection_options_gui (tool_options);
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *inner_vbox;
|
||||
GtkWidget *antialias_toggle;
|
||||
|
||||
antialias_toggle = PIKA_SELECTION_OPTIONS (tool_options)->antialias_toggle;
|
||||
gtk_widget_hide (antialias_toggle);
|
||||
|
||||
frame = pika_prop_enum_radio_frame_new (config, "draw-mode", NULL,
|
||||
0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
/* stroke width */
|
||||
scale = pika_prop_spin_scale_new (config, "stroke-width",
|
||||
1.0, 10.0, 2);
|
||||
pika_spin_scale_set_scale_limits (PIKA_SPIN_SCALE (scale), 1.0, 1000.0);
|
||||
pika_spin_scale_set_gamma (PIKA_SPIN_SCALE (scale), 1.7);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
|
||||
|
||||
button = pika_icon_button_new (PIKA_ICON_RESET, NULL);
|
||||
gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (gtk_bin_get_child (GTK_BIN (button))),
|
||||
PIKA_ICON_RESET, GTK_ICON_SIZE_MENU);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_show (button);
|
||||
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (pika_foreground_select_options_reset_stroke_width),
|
||||
tool_options);
|
||||
|
||||
pika_help_set_help_data (button,
|
||||
_("Reset stroke width native size"), NULL);
|
||||
|
||||
/* preview mode */
|
||||
|
||||
frame = pika_prop_enum_radio_frame_new (config, "preview-mode", NULL,
|
||||
0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
|
||||
|
||||
/* mask color */
|
||||
button = pika_prop_color_button_new (config, "mask-color",
|
||||
NULL,
|
||||
128, 24,
|
||||
PIKA_COLOR_AREA_SMALL_CHECKS);
|
||||
pika_color_panel_set_context (PIKA_COLOR_PANEL (button),
|
||||
PIKA_CONTEXT (config));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
/* engine */
|
||||
frame = pika_frame_new (NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
combo = pika_prop_enum_combo_box_new (config, "engine", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Engine"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_frame_set_label_widget (GTK_FRAME (frame), combo);
|
||||
|
||||
if (! gegl_has_operation ("gegl:matting-levin"))
|
||||
gtk_widget_set_sensitive (combo, FALSE);
|
||||
|
||||
inner_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_container_add (GTK_CONTAINER (frame), inner_vbox);
|
||||
gtk_widget_show (inner_vbox);
|
||||
|
||||
/* engine parameters */
|
||||
scale = pika_prop_spin_scale_new (config, "levels",
|
||||
1.0, 1.0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (inner_vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property_full (config, "engine",
|
||||
scale, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
pika_foreground_select_options_sync_engine,
|
||||
NULL,
|
||||
GINT_TO_POINTER (PIKA_MATTING_ENGINE_LEVIN),
|
||||
NULL);
|
||||
|
||||
scale = pika_prop_spin_scale_new (config, "active-levels",
|
||||
1.0, 1.0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (inner_vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property_full (config, "engine",
|
||||
scale, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
pika_foreground_select_options_sync_engine,
|
||||
NULL,
|
||||
GINT_TO_POINTER (PIKA_MATTING_ENGINE_LEVIN),
|
||||
NULL);
|
||||
|
||||
scale = pika_prop_spin_scale_new (config, "iterations",
|
||||
1.0, 1.0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (inner_vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
g_object_bind_property_full (config, "engine",
|
||||
scale, "visible",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
pika_foreground_select_options_sync_engine,
|
||||
NULL,
|
||||
GINT_TO_POINTER (PIKA_MATTING_ENGINE_GLOBAL),
|
||||
NULL);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
68
app/tools/pikaforegroundselectoptions.h
Normal file
68
app/tools/pikaforegroundselectoptions.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __PIKA_FOREGROUND_SELECT_OPTIONS_H__
|
||||
#define __PIKA_FOREGROUND_SELECT_OPTIONS_H__
|
||||
|
||||
|
||||
#include "pikaselectionoptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FOREGROUND_SELECT_OPTIONS (pika_foreground_select_options_get_type ())
|
||||
#define PIKA_FOREGROUND_SELECT_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FOREGROUND_SELECT_OPTIONS, PikaForegroundSelectOptions))
|
||||
#define PIKA_FOREGROUND_SELECT_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FOREGROUND_SELECT_OPTIONS, PikaForegroundSelectOptionsClass))
|
||||
#define PIKA_IS_FOREGROUND_SELECT_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FOREGROUND_SELECT_OPTIONS))
|
||||
#define PIKA_IS_FOREGROUND_SELECT_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FOREGROUND_SELECT_OPTIONS))
|
||||
#define PIKA_FOREGROUND_SELECT_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FOREGROUND_SELECT_OPTIONS, PikaForegroundSelectOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaForegroundSelectOptions PikaForegroundSelectOptions;
|
||||
typedef struct _PikaForegroundSelectOptionsClass PikaForegroundSelectOptionsClass;
|
||||
|
||||
struct _PikaForegroundSelectOptions
|
||||
{
|
||||
PikaSelectionOptions parent_instance;
|
||||
|
||||
PikaMattingDrawMode draw_mode;
|
||||
PikaMattingPreviewMode preview_mode;
|
||||
gint stroke_width;
|
||||
PikaRGB mask_color;
|
||||
PikaMattingEngine engine;
|
||||
gint levels;
|
||||
gint active_levels;
|
||||
gint iterations;
|
||||
};
|
||||
|
||||
struct _PikaForegroundSelectOptionsClass
|
||||
{
|
||||
PikaSelectionOptionsClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_foreground_select_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_foreground_select_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
|
||||
#endif /* __PIKA_FOREGROUND_SELECT_OPTIONS_H__ */
|
||||
|
||||
1425
app/tools/pikaforegroundselecttool.c
Normal file
1425
app/tools/pikaforegroundselecttool.c
Normal file
File diff suppressed because it is too large
Load Diff
82
app/tools/pikaforegroundselecttool.h
Normal file
82
app/tools/pikaforegroundselecttool.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FOREGROUND_SELECT_TOOL_H__
|
||||
#define __PIKA_FOREGROUND_SELECT_TOOL_H__
|
||||
|
||||
|
||||
#include "pikapolygonselecttool.h"
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MATTING_STATE_FREE_SELECT = 0,
|
||||
MATTING_STATE_PAINT_TRIMAP,
|
||||
MATTING_STATE_PREVIEW_MASK,
|
||||
} MattingState;
|
||||
|
||||
|
||||
#define PIKA_TYPE_FOREGROUND_SELECT_TOOL (pika_foreground_select_tool_get_type ())
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FOREGROUND_SELECT_TOOL, PikaForegroundSelectTool))
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FOREGROUND_SELECT_TOOL, PikaForegroundSelectToolClass))
|
||||
#define PIKA_IS_FOREGROUND_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FOREGROUND_SELECT_TOOL))
|
||||
#define PIKA_IS_FOREGROUND_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FOREGROUND_SELECT_TOOL))
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FOREGROUND_SELECT_TOOL, PikaForegroundSelectToolClass))
|
||||
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL_GET_OPTIONS(t) (PIKA_FOREGROUND_SELECT_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaForegroundSelectTool PikaForegroundSelectTool;
|
||||
typedef struct _PikaForegroundSelectToolClass PikaForegroundSelectToolClass;
|
||||
|
||||
struct _PikaForegroundSelectTool
|
||||
{
|
||||
PikaPolygonSelectTool parent_instance;
|
||||
|
||||
MattingState state;
|
||||
|
||||
PikaCoords last_coords;
|
||||
GArray *stroke;
|
||||
GeglBuffer *trimap;
|
||||
GeglBuffer *mask;
|
||||
|
||||
GList *undo_stack;
|
||||
GList *redo_stack;
|
||||
|
||||
PikaToolGui *gui;
|
||||
GtkWidget *preview_toggle;
|
||||
|
||||
PikaCanvasItem *grayscale_preview;
|
||||
};
|
||||
|
||||
struct _PikaForegroundSelectToolClass
|
||||
{
|
||||
PikaPolygonSelectToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_foreground_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_foreground_select_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_FOREGROUND_SELECT_TOOL_H__ */
|
||||
165
app/tools/pikaforegroundselecttoolundo.c
Normal file
165
app/tools/pikaforegroundselecttoolundo.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "pikaforegroundselecttool.h"
|
||||
#include "pikaforegroundselecttoolundo.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FOREGROUND_SELECT_TOOL
|
||||
};
|
||||
|
||||
|
||||
static void pika_foreground_select_tool_undo_constructed (GObject *object);
|
||||
static void pika_foreground_select_tool_undo_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_foreground_select_tool_undo_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void pika_foreground_select_tool_undo_pop (PikaUndo *undo,
|
||||
PikaUndoMode undo_mode,
|
||||
PikaUndoAccumulator *accum);
|
||||
static void pika_foreground_select_tool_undo_free (PikaUndo *undo,
|
||||
PikaUndoMode undo_mode);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaForegroundSelectToolUndo, pika_foreground_select_tool_undo,
|
||||
PIKA_TYPE_UNDO)
|
||||
|
||||
#define parent_class pika_foreground_select_tool_undo_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_class_init (PikaForegroundSelectToolUndoClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaUndoClass *undo_class = PIKA_UNDO_CLASS (klass);
|
||||
|
||||
object_class->constructed = pika_foreground_select_tool_undo_constructed;
|
||||
object_class->set_property = pika_foreground_select_tool_undo_set_property;
|
||||
object_class->get_property = pika_foreground_select_tool_undo_get_property;
|
||||
|
||||
undo_class->pop = pika_foreground_select_tool_undo_pop;
|
||||
undo_class->free = pika_foreground_select_tool_undo_free;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_FOREGROUND_SELECT_TOOL,
|
||||
g_param_spec_object ("foreground-select-tool",
|
||||
NULL, NULL,
|
||||
PIKA_TYPE_FOREGROUND_SELECT_TOOL,
|
||||
PIKA_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_init (PikaForegroundSelectToolUndo *undo)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_constructed (GObject *object)
|
||||
{
|
||||
PikaForegroundSelectToolUndo *fg_select_tool_undo;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
fg_select_tool_undo = PIKA_FOREGROUND_SELECT_TOOL_UNDO (object);
|
||||
|
||||
pika_assert (PIKA_IS_FOREGROUND_SELECT_TOOL (fg_select_tool_undo->foreground_select_tool));
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaForegroundSelectToolUndo *fg_select_tool_undo =
|
||||
PIKA_FOREGROUND_SELECT_TOOL_UNDO (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FOREGROUND_SELECT_TOOL:
|
||||
g_set_weak_pointer (&fg_select_tool_undo->foreground_select_tool,
|
||||
g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaForegroundSelectToolUndo *fg_select_tool_undo =
|
||||
PIKA_FOREGROUND_SELECT_TOOL_UNDO (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FOREGROUND_SELECT_TOOL:
|
||||
g_value_set_object (value, fg_select_tool_undo->foreground_select_tool);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_pop (PikaUndo *undo,
|
||||
PikaUndoMode undo_mode,
|
||||
PikaUndoAccumulator *accum)
|
||||
{
|
||||
PIKA_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_foreground_select_tool_undo_free (PikaUndo *undo,
|
||||
PikaUndoMode undo_mode)
|
||||
{
|
||||
PikaForegroundSelectToolUndo *fg_select_tool_undo = PIKA_FOREGROUND_SELECT_TOOL_UNDO (undo);
|
||||
|
||||
g_clear_weak_pointer (&fg_select_tool_undo->foreground_select_tool);
|
||||
|
||||
PIKA_UNDO_CLASS (parent_class)->free (undo, undo_mode);
|
||||
}
|
||||
|
||||
#endif
|
||||
60
app/tools/pikaforegroundselecttoolundo.h
Normal file
60
app/tools/pikaforegroundselecttoolundo.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
#ifndef __PIKA_FOREGROUND_SELECT_TOOL_UNDO_H__
|
||||
#define __PIKA_FOREGROUND_SELECT_TOOL_UNDO_H__
|
||||
|
||||
|
||||
#include "core/pikaundo.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FOREGROUND_SELECT_TOOL_UNDO (pika_foreground_select_tool_undo_get_type ())
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL_UNDO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FOREGROUND_SELECT_TOOL_UNDO, PikaForegroundSelectToolUndo))
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FOREGROUND_SELECT_TOOL_UNDO, PikaForegroundSelectToolUndoClass))
|
||||
#define PIKA_IS_FOREGROUND_SELECT_TOOL_UNDO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FOREGROUND_SELECT_TOOL_UNDO))
|
||||
#define PIKA_IS_FOREGROUND_SELECT_TOOL_UNDO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FOREGROUND_SELECT_TOOL_UNDO))
|
||||
#define PIKA_FOREGROUND_SELECT_TOOL_UNDO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FOREGROUND_SELECT_TOOL_UNDO, PikaForegroundSelectToolUndoClass))
|
||||
|
||||
|
||||
typedef struct _PikaForegroundSelectToolUndo PikaForegroundSelectToolUndo;
|
||||
typedef struct _PikaForegroundSelectToolUndoClass PikaForegroundSelectToolUndoClass;
|
||||
|
||||
struct _PikaForegroundSelectToolUndo
|
||||
{
|
||||
PikaUndo parent_instance;
|
||||
|
||||
PikaForegroundSelectTool *foreground_select_tool;
|
||||
};
|
||||
|
||||
struct _PikaForegroundSelectToolUndoClass
|
||||
{
|
||||
PikaUndoClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_foreground_select_tool_undo_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_FOREGROUND_SELECT_TOOL_UNDO_H__ */
|
||||
|
||||
#endif
|
||||
359
app/tools/pikafreeselecttool.c
Normal file
359
app/tools/pikafreeselecttool.c
Normal file
@ -0,0 +1,359 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* Major improvement to support polygonal segments
|
||||
* Copyright (C) 2008 Martin Nordholts
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pikachannel.h"
|
||||
#include "core/pikachannel-select.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikalayer-floating-selection.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikatoolpolygon.h"
|
||||
|
||||
#include "pikafreeselecttool.h"
|
||||
#include "pikaselectionoptions.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
struct _PikaFreeSelectToolPrivate
|
||||
{
|
||||
gboolean started;
|
||||
gboolean changed;
|
||||
|
||||
/* The selection operation active when the tool was started */
|
||||
PikaChannelOps operation_at_start;
|
||||
};
|
||||
|
||||
|
||||
static void pika_free_select_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display);
|
||||
static void pika_free_select_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_free_select_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_free_select_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
static gboolean pika_free_select_tool_have_selection (PikaSelectionTool *sel_tool,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_free_select_tool_change_complete (PikaPolygonSelectTool *poly_sel,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_free_select_tool_commit (PikaFreeSelectTool *free_sel,
|
||||
PikaDisplay *display);
|
||||
static void pika_free_select_tool_halt (PikaFreeSelectTool *free_sel);
|
||||
|
||||
static gboolean pika_free_select_tool_select (PikaFreeSelectTool *free_sel,
|
||||
PikaDisplay *display);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (PikaFreeSelectTool, pika_free_select_tool,
|
||||
PIKA_TYPE_POLYGON_SELECT_TOOL)
|
||||
|
||||
#define parent_class pika_free_select_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_free_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_FREE_SELECT_TOOL,
|
||||
PIKA_TYPE_SELECTION_OPTIONS,
|
||||
pika_selection_options_gui,
|
||||
0,
|
||||
"pika-free-select-tool",
|
||||
_("Free Select"),
|
||||
_("Free Select Tool: Select a hand-drawn region with free "
|
||||
"and polygonal segments"),
|
||||
N_("_Free Select"), "F",
|
||||
NULL, PIKA_HELP_TOOL_FREE_SELECT,
|
||||
PIKA_ICON_TOOL_FREE_SELECT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_class_init (PikaFreeSelectToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaSelectionToolClass *sel_class = PIKA_SELECTION_TOOL_CLASS (klass);
|
||||
PikaPolygonSelectToolClass *poly_sel_class = PIKA_POLYGON_SELECT_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->control = pika_free_select_tool_control;
|
||||
tool_class->button_press = pika_free_select_tool_button_press;
|
||||
tool_class->button_release = pika_free_select_tool_button_release;
|
||||
tool_class->options_notify = pika_free_select_tool_options_notify;
|
||||
|
||||
sel_class->have_selection = pika_free_select_tool_have_selection;
|
||||
|
||||
poly_sel_class->change_complete = pika_free_select_tool_change_complete;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_init (PikaFreeSelectTool *free_sel)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (free_sel);
|
||||
PikaSelectionTool *sel_tool = PIKA_SELECTION_TOOL (tool);
|
||||
|
||||
free_sel->priv = pika_free_select_tool_get_instance_private (free_sel);
|
||||
|
||||
pika_tool_control_set_preserve (tool->control, FALSE);
|
||||
pika_tool_control_set_dirty_mask (tool->control,
|
||||
PIKA_DIRTY_SELECTION);
|
||||
pika_tool_control_set_dirty_action (tool->control,
|
||||
PIKA_TOOL_ACTION_COMMIT);
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_FREE_SELECT);
|
||||
|
||||
sel_tool->allow_move = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaFreeSelectTool *free_sel = PIKA_FREE_SELECT_TOOL (tool);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PIKA_TOOL_ACTION_PAUSE:
|
||||
case PIKA_TOOL_ACTION_RESUME:
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_HALT:
|
||||
pika_free_select_tool_halt (free_sel);
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_COMMIT:
|
||||
pika_free_select_tool_commit (free_sel, display);
|
||||
break;
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->control (tool, action, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_button_press (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonPressType press_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaSelectionOptions *options = PIKA_SELECTION_TOOL_GET_OPTIONS (tool);
|
||||
PikaFreeSelectTool *free_sel = PIKA_FREE_SELECT_TOOL (tool);
|
||||
PikaPolygonSelectTool *poly_sel = PIKA_POLYGON_SELECT_TOOL (tool);
|
||||
PikaFreeSelectToolPrivate *priv = free_sel->priv;
|
||||
|
||||
if (press_type == PIKA_BUTTON_PRESS_NORMAL &&
|
||||
pika_selection_tool_start_edit (PIKA_SELECTION_TOOL (poly_sel),
|
||||
display, coords))
|
||||
return;
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state,
|
||||
press_type, display);
|
||||
|
||||
if (press_type == PIKA_BUTTON_PRESS_NORMAL &&
|
||||
pika_polygon_select_tool_is_grabbed (poly_sel))
|
||||
{
|
||||
if (! priv->started)
|
||||
{
|
||||
priv->started = TRUE;
|
||||
priv->operation_at_start = options->operation;
|
||||
}
|
||||
|
||||
pika_selection_tool_start_change (
|
||||
PIKA_SELECTION_TOOL (tool),
|
||||
! pika_polygon_select_tool_is_closed (poly_sel),
|
||||
priv->operation_at_start);
|
||||
|
||||
priv->changed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaFreeSelectTool *free_sel = PIKA_FREE_SELECT_TOOL (tool);
|
||||
PikaPolygonSelectTool *poly_sel = PIKA_POLYGON_SELECT_TOOL (tool);
|
||||
PikaFreeSelectToolPrivate *priv = free_sel->priv;
|
||||
|
||||
if (pika_polygon_select_tool_is_grabbed (poly_sel))
|
||||
{
|
||||
pika_selection_tool_end_change (PIKA_SELECTION_TOOL (tool),
|
||||
! priv->changed);
|
||||
|
||||
priv->changed = FALSE;
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state,
|
||||
release_type, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec)
|
||||
{
|
||||
if (! strcmp (pspec->name, "antialias") ||
|
||||
! strcmp (pspec->name, "feather") ||
|
||||
! strcmp (pspec->name, "feather-radius"))
|
||||
{
|
||||
if (tool->display)
|
||||
{
|
||||
pika_free_select_tool_change_complete (
|
||||
PIKA_POLYGON_SELECT_TOOL (tool), tool->display);
|
||||
}
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_free_select_tool_have_selection (PikaSelectionTool *sel_tool,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaPolygonSelectTool *poly_sel = PIKA_POLYGON_SELECT_TOOL (sel_tool);
|
||||
PikaTool *tool = PIKA_TOOL (sel_tool);
|
||||
|
||||
if (display == tool->display)
|
||||
{
|
||||
gint n_points;
|
||||
|
||||
pika_polygon_select_tool_get_points (poly_sel, NULL, &n_points);
|
||||
|
||||
if (n_points > 2)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return PIKA_SELECTION_TOOL_CLASS (parent_class)->have_selection (sel_tool,
|
||||
display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_change_complete (PikaPolygonSelectTool *poly_sel,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaFreeSelectTool *free_sel = PIKA_FREE_SELECT_TOOL (poly_sel);
|
||||
PikaFreeSelectToolPrivate *priv = free_sel->priv;
|
||||
|
||||
priv->changed = TRUE;
|
||||
|
||||
pika_selection_tool_start_change (PIKA_SELECTION_TOOL (free_sel),
|
||||
FALSE,
|
||||
priv->operation_at_start);
|
||||
|
||||
if (pika_polygon_select_tool_is_closed (poly_sel))
|
||||
pika_free_select_tool_select (free_sel, display);
|
||||
|
||||
pika_selection_tool_end_change (PIKA_SELECTION_TOOL (free_sel),
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_halt (PikaFreeSelectTool *free_sel)
|
||||
{
|
||||
PikaFreeSelectToolPrivate *priv = free_sel->priv;
|
||||
|
||||
priv->started = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_free_select_tool_commit (PikaFreeSelectTool *free_sel,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaPolygonSelectTool *poly_sel = PIKA_POLYGON_SELECT_TOOL (free_sel);
|
||||
|
||||
if (! pika_polygon_select_tool_is_closed (poly_sel))
|
||||
{
|
||||
if (pika_free_select_tool_select (free_sel, display))
|
||||
pika_image_flush (pika_display_get_image (display));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_free_select_tool_select (PikaFreeSelectTool *free_sel,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaSelectionOptions *options = PIKA_SELECTION_TOOL_GET_OPTIONS (free_sel);
|
||||
PikaTool *tool = PIKA_TOOL (free_sel);
|
||||
PikaFreeSelectToolPrivate *priv = free_sel->priv;
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
const PikaVector2 *points;
|
||||
gint n_points;
|
||||
|
||||
pika_polygon_select_tool_get_points (PIKA_POLYGON_SELECT_TOOL (free_sel),
|
||||
&points, &n_points);
|
||||
|
||||
if (n_points > 2)
|
||||
{
|
||||
/* prevent this change from halting the tool */
|
||||
pika_tool_control_push_preserve (tool->control, TRUE);
|
||||
|
||||
pika_channel_select_polygon (pika_image_get_mask (image),
|
||||
C_("command", "Free Select"),
|
||||
n_points,
|
||||
points,
|
||||
priv->operation_at_start,
|
||||
options->antialias,
|
||||
options->feather,
|
||||
options->feather_radius,
|
||||
options->feather_radius,
|
||||
TRUE);
|
||||
|
||||
pika_tool_control_pop_preserve (tool->control);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
60
app/tools/pikafreeselecttool.h
Normal file
60
app/tools/pikafreeselecttool.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FREE_SELECT_TOOL_H__
|
||||
#define __PIKA_FREE_SELECT_TOOL_H__
|
||||
|
||||
|
||||
#include "pikapolygonselecttool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FREE_SELECT_TOOL (pika_free_select_tool_get_type ())
|
||||
#define PIKA_FREE_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FREE_SELECT_TOOL, PikaFreeSelectTool))
|
||||
#define PIKA_FREE_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FREE_SELECT_TOOL, PikaFreeSelectToolClass))
|
||||
#define PIKA_IS_FREE_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FREE_SELECT_TOOL))
|
||||
#define PIKA_IS_FREE_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FREE_SELECT_TOOL))
|
||||
#define PIKA_FREE_SELECT_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FREE_SELECT_TOOL, PikaFreeSelectToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaFreeSelectTool PikaFreeSelectTool;
|
||||
typedef struct _PikaFreeSelectToolPrivate PikaFreeSelectToolPrivate;
|
||||
typedef struct _PikaFreeSelectToolClass PikaFreeSelectToolClass;
|
||||
|
||||
struct _PikaFreeSelectTool
|
||||
{
|
||||
PikaPolygonSelectTool parent_instance;
|
||||
|
||||
PikaFreeSelectToolPrivate *priv;
|
||||
};
|
||||
|
||||
struct _PikaFreeSelectToolClass
|
||||
{
|
||||
PikaPolygonSelectToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_free_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_free_select_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_FREE_SELECT_TOOL_H__ */
|
||||
159
app/tools/pikafuzzyselecttool.c
Normal file
159
app/tools/pikafuzzyselecttool.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikafuzzyselecttool.c
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikacontainer.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-new.h"
|
||||
#include "core/pikaitem.h"
|
||||
#include "core/pikapickable.h"
|
||||
#include "core/pikapickable-contiguous-region.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
|
||||
#include "pikafuzzyselecttool.h"
|
||||
#include "pikaregionselectoptions.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static GeglBuffer * pika_fuzzy_select_tool_get_mask (PikaRegionSelectTool *region_select,
|
||||
PikaDisplay *display);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaFuzzySelectTool, pika_fuzzy_select_tool,
|
||||
PIKA_TYPE_REGION_SELECT_TOOL)
|
||||
|
||||
#define parent_class pika_fuzzy_select_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_fuzzy_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_FUZZY_SELECT_TOOL,
|
||||
PIKA_TYPE_REGION_SELECT_OPTIONS,
|
||||
pika_region_select_options_gui,
|
||||
0,
|
||||
"pika-fuzzy-select-tool",
|
||||
_("Fuzzy Select"),
|
||||
_("Fuzzy Select Tool: Select a contiguous region on the basis of color"),
|
||||
N_("Fu_zzy Select"), "U",
|
||||
NULL, PIKA_HELP_TOOL_FUZZY_SELECT,
|
||||
PIKA_ICON_TOOL_FUZZY_SELECT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_fuzzy_select_tool_class_init (PikaFuzzySelectToolClass *klass)
|
||||
{
|
||||
PikaRegionSelectToolClass *region_class;
|
||||
|
||||
region_class = PIKA_REGION_SELECT_TOOL_CLASS (klass);
|
||||
|
||||
region_class->undo_desc = C_("command", "Fuzzy Select");
|
||||
region_class->get_mask = pika_fuzzy_select_tool_get_mask;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_fuzzy_select_tool_init (PikaFuzzySelectTool *fuzzy_select)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (fuzzy_select);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_FUZZY_SELECT);
|
||||
}
|
||||
|
||||
static GeglBuffer *
|
||||
pika_fuzzy_select_tool_get_mask (PikaRegionSelectTool *region_select,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (region_select);
|
||||
PikaSelectionOptions *sel_options = PIKA_SELECTION_TOOL_GET_OPTIONS (tool);
|
||||
PikaRegionSelectOptions *options = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
PikaImage *select_image = NULL;
|
||||
GList *drawables = pika_image_get_selected_drawables (image);
|
||||
PikaPickable *pickable;
|
||||
GeglBuffer *mask;
|
||||
gint x, y;
|
||||
|
||||
x = region_select->x;
|
||||
y = region_select->y;
|
||||
|
||||
if (! options->sample_merged)
|
||||
{
|
||||
if (g_list_length (drawables) == 1)
|
||||
{
|
||||
gint off_x, off_y;
|
||||
|
||||
pika_item_get_offset (drawables->data, &off_x, &off_y);
|
||||
|
||||
x -= off_x;
|
||||
y -= off_y;
|
||||
|
||||
pickable = PIKA_PICKABLE (drawables->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
select_image = pika_image_new_from_drawables (image->pika, drawables, FALSE, FALSE);
|
||||
pika_container_remove (image->pika->images, PIKA_OBJECT (select_image));
|
||||
|
||||
pickable = PIKA_PICKABLE (select_image);
|
||||
pika_pickable_flush (pickable);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pickable = PIKA_PICKABLE (image);
|
||||
}
|
||||
|
||||
g_list_free (drawables);
|
||||
|
||||
mask = pika_pickable_contiguous_region_by_seed (pickable,
|
||||
sel_options->antialias,
|
||||
options->threshold / 255.0,
|
||||
options->select_transparent,
|
||||
options->select_criterion,
|
||||
options->diagonal_neighbors,
|
||||
x, y);
|
||||
|
||||
if (select_image)
|
||||
g_object_unref (select_image);
|
||||
|
||||
return mask;
|
||||
}
|
||||
59
app/tools/pikafuzzyselecttool.h
Normal file
59
app/tools/pikafuzzyselecttool.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* pikafuzzyselecttool.h
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_FUZZY_SELECT_TOOL_H__
|
||||
#define __PIKA_FUZZY_SELECT_TOOL_H__
|
||||
|
||||
|
||||
#include "pikaregionselecttool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_FUZZY_SELECT_TOOL (pika_fuzzy_select_tool_get_type ())
|
||||
#define PIKA_FUZZY_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_FUZZY_SELECT_TOOL, PikaFuzzySelectTool))
|
||||
#define PIKA_FUZZY_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_FUZZY_SELECT_TOOL, PikaFuzzySelectToolClass))
|
||||
#define PIKA_IS_FUZZY_SELECT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_FUZZY_SELECT_TOOL))
|
||||
#define PIKA_IS_FUZZY_SELECT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_FUZZY_SELECT_TOOL))
|
||||
#define PIKA_FUZZY_SELECT_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_FUZZY_SELECT_TOOL, PikaFuzzySelectToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaFuzzySelectTool PikaFuzzySelectTool;
|
||||
typedef struct _PikaFuzzySelectToolClass PikaFuzzySelectToolClass;
|
||||
|
||||
struct _PikaFuzzySelectTool
|
||||
{
|
||||
PikaRegionSelectTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaFuzzySelectToolClass
|
||||
{
|
||||
PikaRegionSelectToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_fuzzy_select_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_fuzzy_select_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_FUZZY_SELECT_TOOL_H__ */
|
||||
302
app/tools/pikagegltool.c
Normal file
302
app/tools/pikagegltool.c
Normal file
@ -0,0 +1,302 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gegl-plugin.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikacolor/pikacolor.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "gegl/pika-gegl-utils.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
|
||||
#include "pikafilteroptions.h"
|
||||
#include "pikagegltool.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
COLUMN_NAME,
|
||||
COLUMN_LABEL,
|
||||
COLUMN_ICON_NAME,
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_gegl_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_gegl_tool_dialog (PikaFilterTool *filter_tool);
|
||||
|
||||
static void pika_gegl_tool_halt (PikaGeglTool *gegl_tool);
|
||||
|
||||
static void pika_gegl_tool_operation_changed (GtkWidget *widget,
|
||||
PikaGeglTool *gegl_tool);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaGeglTool, pika_gegl_tool, PIKA_TYPE_OPERATION_TOOL)
|
||||
|
||||
#define parent_class pika_gegl_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_gegl_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_GEGL_TOOL,
|
||||
PIKA_TYPE_FILTER_OPTIONS,
|
||||
pika_color_options_gui,
|
||||
0,
|
||||
"pika-gegl-tool",
|
||||
_("GEGL Operation"),
|
||||
_("Run an arbitrary GEGL operation"),
|
||||
N_("_GEGL Operation..."), NULL,
|
||||
NULL, PIKA_HELP_TOOL_GEGL,
|
||||
PIKA_ICON_GEGL,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gegl_tool_class_init (PikaGeglToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaFilterToolClass *filter_tool_class = PIKA_FILTER_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->control = pika_gegl_tool_control;
|
||||
|
||||
filter_tool_class->dialog = pika_gegl_tool_dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gegl_tool_init (PikaGeglTool *tool)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gegl_tool_control (PikaTool *tool,
|
||||
PikaToolAction action,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaGeglTool *gegl_tool = PIKA_GEGL_TOOL (tool);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case PIKA_TOOL_ACTION_PAUSE:
|
||||
case PIKA_TOOL_ACTION_RESUME:
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_HALT:
|
||||
pika_gegl_tool_halt (gegl_tool);
|
||||
break;
|
||||
|
||||
case PIKA_TOOL_ACTION_COMMIT:
|
||||
break;
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->control (tool, action, display);
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* Gegl dialog */
|
||||
/*****************/
|
||||
|
||||
static void
|
||||
pika_gegl_tool_dialog (PikaFilterTool *filter_tool)
|
||||
{
|
||||
PikaGeglTool *tool = PIKA_GEGL_TOOL (filter_tool);
|
||||
PikaOperationTool *o_tool = PIKA_OPERATION_TOOL (filter_tool);
|
||||
GtkListStore *store;
|
||||
GtkCellRenderer *cell;
|
||||
GtkWidget *main_vbox;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *options_gui;
|
||||
GtkWidget *options_box;
|
||||
GList *opclasses;
|
||||
GList *iter;
|
||||
|
||||
PIKA_FILTER_TOOL_CLASS (parent_class)->dialog (filter_tool);
|
||||
|
||||
options_box = g_weak_ref_get (&o_tool->options_box_ref);
|
||||
g_return_if_fail (options_box);
|
||||
|
||||
main_vbox = pika_filter_tool_dialog_get_vbox (filter_tool);
|
||||
|
||||
/* The operation combo box */
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
|
||||
gtk_box_reorder_child (GTK_BOX (main_vbox), hbox, 0);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
store = gtk_list_store_new (N_COLUMNS,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||
|
||||
opclasses = pika_gegl_get_op_classes ();
|
||||
|
||||
for (iter = opclasses; iter; iter = iter->next)
|
||||
{
|
||||
GeglOperationClass *opclass = GEGL_OPERATION_CLASS (iter->data);
|
||||
const gchar *icon_name = NULL;
|
||||
const gchar *op_name = opclass->name;
|
||||
const gchar *title;
|
||||
gchar *label;
|
||||
|
||||
if (g_str_has_prefix (opclass->name, "gegl:"))
|
||||
icon_name = PIKA_ICON_GEGL;
|
||||
|
||||
if (g_str_has_prefix (op_name, "gegl:"))
|
||||
op_name += strlen ("gegl:");
|
||||
|
||||
title = gegl_operation_class_get_key (opclass, "title");
|
||||
|
||||
if (title)
|
||||
label = g_strdup_printf ("%s (%s)", title, op_name);
|
||||
else
|
||||
label = g_strdup (op_name);
|
||||
|
||||
gtk_list_store_insert_with_values (store, NULL, -1,
|
||||
COLUMN_NAME, opclass->name,
|
||||
COLUMN_LABEL, label,
|
||||
COLUMN_ICON_NAME, icon_name,
|
||||
-1);
|
||||
|
||||
g_free (label);
|
||||
}
|
||||
|
||||
g_list_free (opclasses);
|
||||
|
||||
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
|
||||
g_object_unref (store);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
|
||||
gtk_widget_show (combo);
|
||||
|
||||
cell = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
|
||||
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,
|
||||
"icon-name", COLUMN_ICON_NAME);
|
||||
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
g_object_set (cell,
|
||||
"ellipsize", PANGO_ELLIPSIZE_MIDDLE,
|
||||
NULL);
|
||||
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
|
||||
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell,
|
||||
"text", COLUMN_LABEL);
|
||||
|
||||
g_signal_connect (combo, "changed",
|
||||
G_CALLBACK (pika_gegl_tool_operation_changed),
|
||||
tool);
|
||||
|
||||
tool->operation_combo = combo;
|
||||
|
||||
tool->description_label = gtk_label_new ("");
|
||||
gtk_label_set_line_wrap (GTK_LABEL (tool->description_label), TRUE);
|
||||
gtk_label_set_xalign (GTK_LABEL (tool->description_label), 0.0);
|
||||
gtk_box_pack_start (GTK_BOX (main_vbox), tool->description_label,
|
||||
FALSE, FALSE, 0);
|
||||
gtk_box_reorder_child (GTK_BOX (main_vbox), tool->description_label, 1);
|
||||
|
||||
/* The options vbox */
|
||||
options_gui = gtk_label_new (_("Select an operation from the list above"));
|
||||
pika_label_set_attributes (GTK_LABEL (options_gui),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
g_object_set (options_gui,
|
||||
"margin-top", 4,
|
||||
"margin-bottom", 4,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (options_box), options_gui);
|
||||
g_object_unref (options_box);
|
||||
g_weak_ref_set (&o_tool->options_gui_ref, options_gui);
|
||||
gtk_widget_show (options_gui);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gegl_tool_halt (PikaGeglTool *gegl_tool)
|
||||
{
|
||||
PikaOperationTool *op_tool = PIKA_OPERATION_TOOL (gegl_tool);
|
||||
|
||||
pika_operation_tool_set_operation (op_tool, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gegl_tool_operation_changed (GtkWidget *widget,
|
||||
PikaGeglTool *tool)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gchar *operation;
|
||||
|
||||
if (! gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter))
|
||||
return;
|
||||
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
COLUMN_NAME, &operation,
|
||||
-1);
|
||||
|
||||
if (operation)
|
||||
{
|
||||
const gchar *description;
|
||||
|
||||
description = gegl_operation_get_key (operation, "description");
|
||||
|
||||
if (description)
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (tool->description_label), description);
|
||||
gtk_widget_show (tool->description_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (tool->description_label);
|
||||
}
|
||||
|
||||
pika_operation_tool_set_operation (PIKA_OPERATION_TOOL (tool),
|
||||
operation,
|
||||
_("GEGL Operation"),
|
||||
_("GEGL Operation"),
|
||||
NULL,
|
||||
PIKA_ICON_GEGL,
|
||||
PIKA_HELP_TOOL_GEGL);
|
||||
g_free (operation);
|
||||
}
|
||||
}
|
||||
61
app/tools/pikagegltool.h
Normal file
61
app/tools/pikagegltool.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_GEGL_TOOL_H__
|
||||
#define __PIKA_GEGL_TOOL_H__
|
||||
|
||||
|
||||
#include "pikaoperationtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_GEGL_TOOL (pika_gegl_tool_get_type ())
|
||||
#define PIKA_GEGL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_GEGL_TOOL, PikaGeglTool))
|
||||
#define PIKA_GEGL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_GEGL_TOOL, PikaGeglToolClass))
|
||||
#define PIKA_IS_GEGL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_GEGL_TOOL))
|
||||
#define PIKA_IS_GEGL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_GEGL_TOOL))
|
||||
#define PIKA_GEGL_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_GEGL_TOOL, PikaGeglToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaGeglTool PikaGeglTool;
|
||||
typedef struct _PikaGeglToolClass PikaGeglToolClass;
|
||||
|
||||
struct _PikaGeglTool
|
||||
{
|
||||
PikaOperationTool parent_instance;
|
||||
|
||||
/* dialog */
|
||||
GtkWidget *operation_combo;
|
||||
GtkWidget *description_label;
|
||||
};
|
||||
|
||||
struct _PikaGeglToolClass
|
||||
{
|
||||
PikaOperationToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_gegl_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_gegl_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_GEGL_TOOL_H__ */
|
||||
174
app/tools/pikagenerictransformtool.c
Normal file
174
app/tools/pikagenerictransformtool.c
Normal file
@ -0,0 +1,174 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika-transform-utils.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikatoolgui.h"
|
||||
|
||||
#include "pikagenerictransformtool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
#include "pikatransformgridoptions.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static gboolean pika_generic_transform_tool_info_to_matrix (PikaTransformGridTool *tg_tool,
|
||||
PikaMatrix3 *transform);
|
||||
static void pika_generic_transform_tool_dialog (PikaTransformGridTool *tg_tool);
|
||||
static void pika_generic_transform_tool_dialog_update (PikaTransformGridTool *tg_tool);
|
||||
static void pika_generic_transform_tool_prepare (PikaTransformGridTool *tg_tool);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaGenericTransformTool, pika_generic_transform_tool,
|
||||
PIKA_TYPE_TRANSFORM_GRID_TOOL)
|
||||
|
||||
#define parent_class pika_generic_transform_tool_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_generic_transform_tool_class_init (PikaGenericTransformToolClass *klass)
|
||||
{
|
||||
PikaTransformGridToolClass *tg_class = PIKA_TRANSFORM_GRID_TOOL_CLASS (klass);
|
||||
|
||||
tg_class->info_to_matrix = pika_generic_transform_tool_info_to_matrix;
|
||||
tg_class->dialog = pika_generic_transform_tool_dialog;
|
||||
tg_class->dialog_update = pika_generic_transform_tool_dialog_update;
|
||||
tg_class->prepare = pika_generic_transform_tool_prepare;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_generic_transform_tool_init (PikaGenericTransformTool *unified_tool)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_generic_transform_tool_info_to_matrix (PikaTransformGridTool *tg_tool,
|
||||
PikaMatrix3 *transform)
|
||||
{
|
||||
PikaGenericTransformTool *generic = PIKA_GENERIC_TRANSFORM_TOOL (tg_tool);
|
||||
|
||||
if (PIKA_GENERIC_TRANSFORM_TOOL_GET_CLASS (generic)->info_to_points)
|
||||
PIKA_GENERIC_TRANSFORM_TOOL_GET_CLASS (generic)->info_to_points (generic);
|
||||
|
||||
pika_matrix3_identity (transform);
|
||||
|
||||
return pika_transform_matrix_generic (transform,
|
||||
generic->input_points,
|
||||
generic->output_points);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_generic_transform_tool_dialog (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
PikaGenericTransformTool *generic = PIKA_GENERIC_TRANSFORM_TOOL (tg_tool);
|
||||
GtkWidget *frame;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *label;
|
||||
GtkSizeGroup *size_group;
|
||||
|
||||
frame = pika_frame_new (_("Transform Matrix"));
|
||||
gtk_box_pack_start (GTK_BOX (pika_tool_gui_get_vbox (tg_tool->gui)), frame,
|
||||
FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
||||
gtk_widget_show (vbox);
|
||||
|
||||
size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
|
||||
|
||||
label = generic->matrix_label = gtk_label_new (" ");
|
||||
gtk_size_group_add_widget (size_group, label);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
|
||||
pika_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
|
||||
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = generic->invalid_label = gtk_label_new (_("Invalid transform"));
|
||||
pika_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
gtk_size_group_add_widget (size_group, label);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
|
||||
|
||||
g_object_unref (size_group);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_generic_transform_tool_dialog_update (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
PikaGenericTransformTool *generic = PIKA_GENERIC_TRANSFORM_TOOL (tg_tool);
|
||||
PikaMatrix3 transform;
|
||||
gboolean transform_valid;
|
||||
|
||||
transform_valid = pika_transform_grid_tool_info_to_matrix (tg_tool,
|
||||
&transform);
|
||||
|
||||
if (transform_valid)
|
||||
{
|
||||
gchar buf[256];
|
||||
gtk_widget_show (generic->matrix_label);
|
||||
gtk_widget_hide (generic->invalid_label);
|
||||
|
||||
g_snprintf (buf, sizeof (buf), "<tt>% 11.4f\t% 11.4f\t% 11.4f\n% 11.4f\t% 11.4f"
|
||||
"\t% 11.4f\n% 11.4f\t% 11.4f\t% 11.4f</tt>",
|
||||
transform.coeff[0][0], transform.coeff[0][1], transform.coeff[0][2],
|
||||
transform.coeff[1][0], transform.coeff[1][1], transform.coeff[1][2],
|
||||
transform.coeff[2][0], transform.coeff[2][1], transform.coeff[2][2]);
|
||||
gtk_label_set_markup (GTK_LABEL (generic->matrix_label), buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_show (generic->invalid_label);
|
||||
gtk_widget_hide (generic->matrix_label);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_generic_transform_tool_prepare (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
PikaTransformTool *tr_tool = PIKA_TRANSFORM_TOOL (tg_tool);
|
||||
PikaGenericTransformTool *generic = PIKA_GENERIC_TRANSFORM_TOOL (tg_tool);
|
||||
|
||||
generic->input_points[0] = (PikaVector2) {tr_tool->x1, tr_tool->y1};
|
||||
generic->input_points[1] = (PikaVector2) {tr_tool->x2, tr_tool->y1};
|
||||
generic->input_points[2] = (PikaVector2) {tr_tool->x1, tr_tool->y2};
|
||||
generic->input_points[3] = (PikaVector2) {tr_tool->x2, tr_tool->y2};
|
||||
|
||||
memcpy (generic->output_points, generic->input_points,
|
||||
sizeof (generic->input_points));
|
||||
}
|
||||
62
app/tools/pikagenerictransformtool.h
Normal file
62
app/tools/pikagenerictransformtool.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_GENERIC_TRANSFORM_TOOL_H__
|
||||
#define __PIKA_GENERIC_TRANSFORM_TOOL_H__
|
||||
|
||||
|
||||
#include "pikatransformgridtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_GENERIC_TRANSFORM_TOOL (pika_generic_transform_tool_get_type ())
|
||||
#define PIKA_GENERIC_TRANSFORM_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_GENERIC_TRANSFORM_TOOL, PikaGenericTransformTool))
|
||||
#define PIKA_GENERIC_TRANSFORM_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_GENERIC_TRANSFORM_TOOL, PikaGenericTransformToolClass))
|
||||
#define PIKA_IS_GENERIC_TRANSFORM_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_GENERIC_TRANSFORM_TOOL))
|
||||
#define PIKA_IS_GENERIC_TRANSFORM_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_GENERIC_TRANSFORM_TOOL))
|
||||
#define PIKA_GENERIC_TRANSFORM_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_GENERIC_TRANSFORM_TOOL, PikaGenericTransformToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaGenericTransformToolClass PikaGenericTransformToolClass;
|
||||
|
||||
struct _PikaGenericTransformTool
|
||||
{
|
||||
PikaTransformGridTool parent_instance;
|
||||
|
||||
PikaVector2 input_points[4];
|
||||
PikaVector2 output_points[4];
|
||||
|
||||
GtkWidget *matrix_label;
|
||||
GtkWidget *invalid_label;
|
||||
};
|
||||
|
||||
struct _PikaGenericTransformToolClass
|
||||
{
|
||||
PikaTransformGridToolClass parent_class;
|
||||
|
||||
/* virtual functions */
|
||||
void (* info_to_points) (PikaGenericTransformTool *generic);
|
||||
};
|
||||
|
||||
|
||||
GType pika_generic_transform_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_GENERIC_TRANSFORM_TOOL_H__ */
|
||||
407
app/tools/pikagradientoptions.c
Normal file
407
app/tools/pikagradientoptions.c
Normal file
@ -0,0 +1,407 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pikadata.h"
|
||||
#include "core/pikadatafactory.h"
|
||||
#include "core/pika-gradients.h"
|
||||
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikaviewablebox.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikagradientoptions.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_OFFSET,
|
||||
PROP_GRADIENT_TYPE,
|
||||
PROP_DISTANCE_METRIC,
|
||||
PROP_SUPERSAMPLE,
|
||||
PROP_SUPERSAMPLE_DEPTH,
|
||||
PROP_SUPERSAMPLE_THRESHOLD,
|
||||
PROP_DITHER,
|
||||
PROP_INSTANT,
|
||||
PROP_MODIFY_ACTIVE
|
||||
};
|
||||
|
||||
|
||||
static void pika_gradient_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_gradient_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void gradient_options_repeat_gradient_type_notify (PikaGradientOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GtkWidget *repeat_combo);
|
||||
static void gradient_options_metric_gradient_type_notify (PikaGradientOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GtkWidget *repeat_combo);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaGradientOptions, pika_gradient_options,
|
||||
PIKA_TYPE_PAINT_OPTIONS)
|
||||
|
||||
|
||||
static void
|
||||
pika_gradient_options_class_init (PikaGradientOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_gradient_options_set_property;
|
||||
object_class->get_property = pika_gradient_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_OFFSET,
|
||||
"offset",
|
||||
_("Offset"),
|
||||
NULL,
|
||||
0.0, 100.0, 0.0,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_GRADIENT_TYPE,
|
||||
"gradient-type",
|
||||
_("Shape"),
|
||||
NULL,
|
||||
PIKA_TYPE_GRADIENT_TYPE,
|
||||
PIKA_GRADIENT_LINEAR,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_DISTANCE_METRIC,
|
||||
"distance-metric",
|
||||
_("Metric"),
|
||||
_("Metric to use for the distance calculation"),
|
||||
GEGL_TYPE_DISTANCE_METRIC,
|
||||
GEGL_DISTANCE_METRIC_EUCLIDEAN,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_SUPERSAMPLE,
|
||||
"supersample",
|
||||
_("Adaptive Supersampling"),
|
||||
NULL,
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
PIKA_CONFIG_PROP_INT (object_class, PROP_SUPERSAMPLE_DEPTH,
|
||||
"supersample-depth",
|
||||
_("Max depth"),
|
||||
NULL,
|
||||
1, 9, 3,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
PIKA_CONFIG_PROP_DOUBLE (object_class, PROP_SUPERSAMPLE_THRESHOLD,
|
||||
"supersample-threshold",
|
||||
_("Threshold"),
|
||||
NULL,
|
||||
0.0, 4.0, 0.2,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_DITHER,
|
||||
"dither",
|
||||
_("Dithering"),
|
||||
NULL,
|
||||
TRUE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_INSTANT,
|
||||
"instant",
|
||||
_("Instant mode"),
|
||||
_("Commit gradient instantly"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
|
||||
PIKA_CONFIG_PROP_BOOLEAN (object_class, PROP_MODIFY_ACTIVE,
|
||||
"modify-active",
|
||||
_("Modify active gradient"),
|
||||
_("Modify the active gradient in-place"),
|
||||
FALSE,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gradient_options_init (PikaGradientOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gradient_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaGradientOptions *options = PIKA_GRADIENT_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_OFFSET:
|
||||
options->offset = g_value_get_double (value);
|
||||
break;
|
||||
case PROP_GRADIENT_TYPE:
|
||||
options->gradient_type = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_DISTANCE_METRIC:
|
||||
options->distance_metric = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
case PROP_SUPERSAMPLE:
|
||||
options->supersample = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SUPERSAMPLE_DEPTH:
|
||||
options->supersample_depth = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_SUPERSAMPLE_THRESHOLD:
|
||||
options->supersample_threshold = g_value_get_double (value);
|
||||
break;
|
||||
|
||||
case PROP_DITHER:
|
||||
options->dither = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_INSTANT:
|
||||
options->instant = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_MODIFY_ACTIVE:
|
||||
options->modify_active = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_gradient_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaGradientOptions *options = PIKA_GRADIENT_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_OFFSET:
|
||||
g_value_set_double (value, options->offset);
|
||||
break;
|
||||
case PROP_GRADIENT_TYPE:
|
||||
g_value_set_enum (value, options->gradient_type);
|
||||
break;
|
||||
case PROP_DISTANCE_METRIC:
|
||||
g_value_set_enum (value, options->distance_metric);
|
||||
break;
|
||||
|
||||
case PROP_SUPERSAMPLE:
|
||||
g_value_set_boolean (value, options->supersample);
|
||||
break;
|
||||
case PROP_SUPERSAMPLE_DEPTH:
|
||||
g_value_set_int (value, options->supersample_depth);
|
||||
break;
|
||||
case PROP_SUPERSAMPLE_THRESHOLD:
|
||||
g_value_set_double (value, options->supersample_threshold);
|
||||
break;
|
||||
|
||||
case PROP_DITHER:
|
||||
g_value_set_boolean (value, options->dither);
|
||||
break;
|
||||
|
||||
case PROP_INSTANT:
|
||||
g_value_set_boolean (value, options->instant);
|
||||
break;
|
||||
case PROP_MODIFY_ACTIVE:
|
||||
g_value_set_boolean (value, options->modify_active);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
pika_gradient_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
PikaContext *context = PIKA_CONTEXT (tool_options);
|
||||
PikaGradientOptions *options = PIKA_GRADIENT_OPTIONS (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *vbox2;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *button;
|
||||
GtkWidget *label;
|
||||
gchar *str;
|
||||
GdkModifierType extend_mask;
|
||||
PikaGradient *gradient;
|
||||
|
||||
extend_mask = pika_get_extend_selection_mask ();
|
||||
|
||||
/* the gradient */
|
||||
button = pika_prop_gradient_box_new (NULL, PIKA_CONTEXT (tool_options),
|
||||
_("Gradient"), 2,
|
||||
"gradient-view-type",
|
||||
"gradient-view-size",
|
||||
"gradient-reverse",
|
||||
"gradient-blend-color-space",
|
||||
"pika-gradient-editor",
|
||||
_("Edit this gradient"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
/* the blend color space */
|
||||
combo = pika_prop_enum_combo_box_new (config, "gradient-blend-color-space",
|
||||
0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo),
|
||||
_("Blend Color Space"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0);
|
||||
|
||||
/* the gradient type menu */
|
||||
combo = pika_prop_enum_combo_box_new (config, "gradient-type", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Shape"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
pika_enum_combo_box_set_icon_prefix (PIKA_ENUM_COMBO_BOX (combo),
|
||||
"pika-gradient");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
||||
|
||||
/* the distance metric menu */
|
||||
combo = pika_prop_enum_combo_box_new (config, "distance-metric", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Metric"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
||||
|
||||
g_signal_connect (config, "notify::gradient-type",
|
||||
G_CALLBACK (gradient_options_metric_gradient_type_notify),
|
||||
combo);
|
||||
gradient_options_metric_gradient_type_notify (options, NULL, combo);
|
||||
|
||||
/* the repeat option */
|
||||
combo = pika_prop_enum_combo_box_new (config, "gradient-repeat", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Repeat"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
|
||||
|
||||
g_signal_connect (config, "notify::gradient-type",
|
||||
G_CALLBACK (gradient_options_repeat_gradient_type_notify),
|
||||
combo);
|
||||
gradient_options_repeat_gradient_type_notify (options, NULL, combo);
|
||||
|
||||
/* the offset scale */
|
||||
scale = pika_prop_spin_scale_new (config, "offset",
|
||||
1.0, 10.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* the dither toggle */
|
||||
button = pika_prop_check_button_new (config, "dither", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
/* supersampling options */
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
frame = pika_prop_expanding_frame_new (config, "supersample", NULL,
|
||||
vbox2, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* max depth scale */
|
||||
scale = pika_prop_spin_scale_new (config, "supersample-depth",
|
||||
1.0, 1.0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* threshold scale */
|
||||
scale = pika_prop_spin_scale_new (config, "supersample-threshold",
|
||||
0.01, 0.1, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* the instant toggle */
|
||||
str = g_strdup_printf (_("Instant mode (%s)"),
|
||||
pika_get_mod_string (extend_mask));
|
||||
|
||||
button = pika_prop_check_button_new (config, "instant", str);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
g_free (str);
|
||||
|
||||
options->instant_toggle = button;
|
||||
|
||||
/* the modify active toggle */
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
frame = pika_prop_expanding_frame_new (config, "modify-active", NULL,
|
||||
vbox2, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
options->modify_active_frame = frame;
|
||||
|
||||
label = gtk_label_new (_("The active gradient is non-writable "
|
||||
"and cannot be edited directly. "
|
||||
"Uncheck this option "
|
||||
"to edit a copy of it."));
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), label, TRUE, TRUE, 0);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_width_chars (GTK_LABEL (label), 24);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
pika_label_set_attributes (GTK_LABEL (label),
|
||||
PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
|
||||
-1);
|
||||
|
||||
options->modify_active_hint = label;
|
||||
|
||||
gradient = pika_context_get_gradient (PIKA_CONTEXT (options));
|
||||
|
||||
gtk_widget_set_sensitive (options->modify_active_frame,
|
||||
gradient !=
|
||||
pika_gradients_get_custom (context->pika));
|
||||
gtk_widget_set_visible (options->modify_active_hint,
|
||||
gradient &&
|
||||
! pika_data_is_writable (PIKA_DATA (gradient)));
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_options_repeat_gradient_type_notify (PikaGradientOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GtkWidget *repeat_combo)
|
||||
{
|
||||
gtk_widget_set_sensitive (repeat_combo,
|
||||
options->gradient_type < PIKA_GRADIENT_SHAPEBURST_ANGULAR);
|
||||
}
|
||||
|
||||
static void
|
||||
gradient_options_metric_gradient_type_notify (PikaGradientOptions *options,
|
||||
GParamSpec *pspec,
|
||||
GtkWidget *repeat_combo)
|
||||
{
|
||||
gtk_widget_set_sensitive (repeat_combo,
|
||||
options->gradient_type >= PIKA_GRADIENT_SHAPEBURST_ANGULAR &&
|
||||
options->gradient_type <= PIKA_GRADIENT_SHAPEBURST_DIMPLED);
|
||||
}
|
||||
69
app/tools/pikagradientoptions.h
Normal file
69
app/tools/pikagradientoptions.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_GRADIENT_OPTIONS_H__
|
||||
#define __PIKA_GRADIENT_OPTIONS_H__
|
||||
|
||||
|
||||
#include "paint/pikapaintoptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_GRADIENT_OPTIONS (pika_gradient_options_get_type ())
|
||||
#define PIKA_GRADIENT_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_GRADIENT_OPTIONS, PikaGradientOptions))
|
||||
#define PIKA_GRADIENT_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_GRADIENT_OPTIONS, PikaGradientOptionsClass))
|
||||
#define PIKA_IS_GRADIENT_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_GRADIENT_OPTIONS))
|
||||
#define PIKA_IS_GRADIENT_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_GRADIENT_OPTIONS))
|
||||
#define PIKA_GRADIENT_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_GRADIENT_OPTIONS, PikaGradientOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaGradientOptions PikaGradientOptions;
|
||||
typedef struct _PikaPaintOptionsClass PikaGradientOptionsClass;
|
||||
|
||||
struct _PikaGradientOptions
|
||||
{
|
||||
PikaPaintOptions paint_options;
|
||||
|
||||
gdouble offset;
|
||||
PikaGradientType gradient_type;
|
||||
GeglDistanceMetric distance_metric;
|
||||
|
||||
gboolean supersample;
|
||||
gint supersample_depth;
|
||||
gdouble supersample_threshold;
|
||||
|
||||
gboolean dither;
|
||||
|
||||
gboolean instant;
|
||||
gboolean modify_active;
|
||||
|
||||
/* options gui */
|
||||
GtkWidget *instant_toggle;
|
||||
GtkWidget *modify_active_frame;
|
||||
GtkWidget *modify_active_hint;
|
||||
};
|
||||
|
||||
|
||||
GType pika_gradient_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_gradient_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_GRADIENT_OPTIONS_H__ */
|
||||
2478
app/tools/pikagradienttool-editor.c
Normal file
2478
app/tools/pikagradienttool-editor.c
Normal file
File diff suppressed because it is too large
Load Diff
52
app/tools/pikagradienttool-editor.h
Normal file
52
app/tools/pikagradienttool-editor.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_GRADIENT_TOOL_EDITOR_H__
|
||||
#define __PIKA_GRADIENT_TOOL_EDITOR_H__
|
||||
|
||||
|
||||
void pika_gradient_tool_editor_options_notify (PikaGradientTool *gradient_tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
void pika_gradient_tool_editor_start (PikaGradientTool *gradient_tool);
|
||||
void pika_gradient_tool_editor_halt (PikaGradientTool *gradient_tool);
|
||||
|
||||
gboolean pika_gradient_tool_editor_line_changed (PikaGradientTool *gradient_tool);
|
||||
|
||||
void pika_gradient_tool_editor_fg_bg_changed (PikaGradientTool *gradient_tool);
|
||||
|
||||
void pika_gradient_tool_editor_gradient_dirty (PikaGradientTool *gradient_tool);
|
||||
|
||||
void pika_gradient_tool_editor_gradient_changed (PikaGradientTool *gradient_tool);
|
||||
|
||||
const gchar * pika_gradient_tool_editor_can_undo (PikaGradientTool *gradient_tool);
|
||||
const gchar * pika_gradient_tool_editor_can_redo (PikaGradientTool *gradient_tool);
|
||||
|
||||
gboolean pika_gradient_tool_editor_undo (PikaGradientTool *gradient_tool);
|
||||
gboolean pika_gradient_tool_editor_redo (PikaGradientTool *gradient_tool);
|
||||
|
||||
void pika_gradient_tool_editor_start_edit (PikaGradientTool *gradient_tool);
|
||||
void pika_gradient_tool_editor_end_edit (PikaGradientTool *gradient_tool,
|
||||
gboolean cancel);
|
||||
|
||||
|
||||
#endif /* __PIKA_GRADIENT_TOOL_EDITOR_H__ */
|
||||
1139
app/tools/pikagradienttool.c
Normal file
1139
app/tools/pikagradienttool.c
Normal file
File diff suppressed because it is too large
Load Diff
115
app/tools/pikagradienttool.h
Normal file
115
app/tools/pikagradienttool.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_GRADIENT_TOOL_H__
|
||||
#define __PIKA_GRADIENT_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_GRADIENT_TOOL (pika_gradient_tool_get_type ())
|
||||
#define PIKA_GRADIENT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_GRADIENT_TOOL, PikaGradientTool))
|
||||
#define PIKA_GRADIENT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_GRADIENT_TOOL, PikaGradientToolClass))
|
||||
#define PIKA_IS_GRADIENT_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_GRADIENT_TOOL))
|
||||
#define PIKA_IS_GRADIENT_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_GRADIENT_TOOL))
|
||||
#define PIKA_GRADIENT_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_GRADIENT_TOOL, PikaGradientToolClass))
|
||||
|
||||
#define PIKA_GRADIENT_TOOL_GET_OPTIONS(t) (PIKA_GRADIENT_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaGradientTool PikaGradientTool;
|
||||
typedef struct _PikaGradientToolClass PikaGradientToolClass;
|
||||
|
||||
struct _PikaGradientTool
|
||||
{
|
||||
PikaDrawTool parent_instance;
|
||||
|
||||
PikaGradient *gradient;
|
||||
PikaGradient *tentative_gradient;
|
||||
|
||||
gdouble start_x; /* starting x coord */
|
||||
gdouble start_y; /* starting y coord */
|
||||
gdouble end_x; /* ending x coord */
|
||||
gdouble end_y; /* ending y coord */
|
||||
|
||||
PikaToolWidget *widget;
|
||||
PikaToolWidget *grab_widget;
|
||||
|
||||
GeglNode *graph;
|
||||
GeglNode *render_node;
|
||||
#if 0
|
||||
GeglNode *subtract_node;
|
||||
GeglNode *divide_node;
|
||||
#endif
|
||||
GeglNode *dist_node;
|
||||
GeglBuffer *dist_buffer;
|
||||
PikaDrawableFilter *filter;
|
||||
|
||||
/* editor */
|
||||
|
||||
gint block_handlers_count;
|
||||
|
||||
gint edit_count;
|
||||
GSList *undo_stack;
|
||||
GSList *redo_stack;
|
||||
|
||||
guint flush_idle_id;
|
||||
|
||||
PikaToolGui *gui;
|
||||
GtkWidget *endpoint_editor;
|
||||
GtkWidget *endpoint_se;
|
||||
GtkWidget *endpoint_color_panel;
|
||||
GtkWidget *endpoint_type_combo;
|
||||
GtkWidget *stop_editor;
|
||||
GtkWidget *stop_se;
|
||||
GtkWidget *stop_left_color_panel;
|
||||
GtkWidget *stop_left_type_combo;
|
||||
GtkWidget *stop_right_color_panel;
|
||||
GtkWidget *stop_right_type_combo;
|
||||
GtkWidget *stop_chain_button;
|
||||
GtkWidget *midpoint_editor;
|
||||
GtkWidget *midpoint_se;
|
||||
GtkWidget *midpoint_type_combo;
|
||||
GtkWidget *midpoint_color_combo;
|
||||
GtkWidget *midpoint_new_stop_button;
|
||||
GtkWidget *midpoint_center_button;
|
||||
};
|
||||
|
||||
struct _PikaGradientToolClass
|
||||
{
|
||||
PikaDrawToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_gradient_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_gradient_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
/* protected functions */
|
||||
|
||||
void pika_gradient_tool_set_tentative_gradient (PikaGradientTool *gradient_tool,
|
||||
PikaGradient *gradient);
|
||||
|
||||
|
||||
#endif /* __PIKA_GRADIENT_TOOL_H__ */
|
||||
542
app/tools/pikaguidetool.c
Normal file
542
app/tools/pikaguidetool.c
Normal file
@ -0,0 +1,542 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikaguide.h"
|
||||
#include "core/pikaimage.h"
|
||||
#include "core/pikaimage-guides.h"
|
||||
#include "core/pikaimage-undo.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikadisplayshell.h"
|
||||
#include "display/pikadisplayshell-selection.h"
|
||||
#include "display/pikadisplayshell-transform.h"
|
||||
|
||||
#include "pikaguidetool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
#include "tool_manager.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
#define SWAP_ORIENT(orient) ((orient) == PIKA_ORIENTATION_HORIZONTAL ? \
|
||||
PIKA_ORIENTATION_VERTICAL : \
|
||||
PIKA_ORIENTATION_HORIZONTAL)
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_guide_tool_finalize (GObject *object);
|
||||
|
||||
static void pika_guide_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display);
|
||||
static void pika_guide_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_guide_tool_draw (PikaDrawTool *draw_tool);
|
||||
|
||||
static void pika_guide_tool_start (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
GList *guides,
|
||||
PikaOrientationType orientation);
|
||||
|
||||
static void pika_guide_tool_push_status (PikaGuideTool *guide_tool,
|
||||
PikaDisplay *display,
|
||||
gboolean remove_guides);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaGuideTool, pika_guide_tool, PIKA_TYPE_DRAW_TOOL)
|
||||
|
||||
#define parent_class pika_guide_tool_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_guide_tool_class_init (PikaGuideToolClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaDrawToolClass *draw_tool_class = PIKA_DRAW_TOOL_CLASS (klass);
|
||||
|
||||
object_class->finalize = pika_guide_tool_finalize;
|
||||
|
||||
tool_class->button_release = pika_guide_tool_button_release;
|
||||
tool_class->motion = pika_guide_tool_motion;
|
||||
|
||||
draw_tool_class->draw = pika_guide_tool_draw;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_init (PikaGuideTool *guide_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (guide_tool);
|
||||
|
||||
pika_tool_control_set_snap_to (tool->control, FALSE);
|
||||
pika_tool_control_set_handle_empty_image (tool->control, TRUE);
|
||||
pika_tool_control_set_tool_cursor (tool->control,
|
||||
PIKA_TOOL_CURSOR_MOVE);
|
||||
pika_tool_control_set_scroll_lock (tool->control, TRUE);
|
||||
pika_tool_control_set_precision (tool->control,
|
||||
PIKA_CURSOR_PRECISION_PIXEL_BORDER);
|
||||
|
||||
guide_tool->guides = NULL;
|
||||
guide_tool->n_guides = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_finalize (GObject *object)
|
||||
{
|
||||
PikaGuideTool *guide_tool = PIKA_GUIDE_TOOL (object);
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
g_clear_object (&guide_tool->guides[i].guide);
|
||||
|
||||
g_free (guide_tool->guides);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_button_release (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaButtonReleaseType release_type,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaGuideTool *guide_tool = PIKA_GUIDE_TOOL (tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
gint i;
|
||||
|
||||
pika_tool_pop_status (tool, display);
|
||||
|
||||
pika_tool_control_halt (tool->control);
|
||||
|
||||
pika_draw_tool_stop (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
if (release_type == PIKA_BUTTON_RELEASE_CANCEL)
|
||||
{
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuideToolGuide *guide = &guide_tool->guides[i];
|
||||
|
||||
/* custom guides are moved live */
|
||||
if (guide->custom)
|
||||
{
|
||||
pika_image_move_guide (image, guide->guide, guide->old_position,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gint n_non_custom_guides = 0;
|
||||
gboolean remove_guides = FALSE;
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuideToolGuide *guide = &guide_tool->guides[i];
|
||||
|
||||
n_non_custom_guides += ! guide->custom;
|
||||
|
||||
if (guide->position == PIKA_GUIDE_POSITION_UNDEFINED)
|
||||
{
|
||||
remove_guides = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (n_non_custom_guides > 1)
|
||||
{
|
||||
pika_image_undo_group_start (image, PIKA_UNDO_GROUP_GUIDE,
|
||||
remove_guides ?
|
||||
C_("undo-type", "Remove Guides") :
|
||||
C_("undo-type", "Move Guides"));
|
||||
}
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuideToolGuide *guide = &guide_tool->guides[i];
|
||||
|
||||
if (remove_guides)
|
||||
{
|
||||
/* removing a guide can cause other guides to be removed as well
|
||||
* (in particular, in case of symmetry guides). these guides
|
||||
* will be kept alive, since we hold a reference on them, but we
|
||||
* need to make sure that they're still part of the image.
|
||||
*/
|
||||
if (g_list_find (pika_image_get_guides (image), guide->guide))
|
||||
pika_image_remove_guide (image, guide->guide, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (guide->guide)
|
||||
{
|
||||
/* custom guides are moved live */
|
||||
if (! guide->custom)
|
||||
{
|
||||
pika_image_move_guide (image, guide->guide,
|
||||
guide->position, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (guide->orientation)
|
||||
{
|
||||
case PIKA_ORIENTATION_HORIZONTAL:
|
||||
pika_image_add_hguide (image,
|
||||
guide->position,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
case PIKA_ORIENTATION_VERTICAL:
|
||||
pika_image_add_vguide (image,
|
||||
guide->position,
|
||||
TRUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
pika_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n_non_custom_guides > 1)
|
||||
pika_image_undo_group_end (image);
|
||||
|
||||
pika_image_flush (image);
|
||||
}
|
||||
|
||||
pika_display_shell_selection_resume (shell);
|
||||
|
||||
tool_manager_pop_tool (display->pika);
|
||||
g_object_unref (guide_tool);
|
||||
|
||||
{
|
||||
PikaTool *active_tool = tool_manager_get_active (display->pika);
|
||||
|
||||
if (PIKA_IS_DRAW_TOOL (active_tool))
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (active_tool));
|
||||
|
||||
tool_manager_oper_update_active (display->pika, coords, state,
|
||||
TRUE, display);
|
||||
tool_manager_cursor_update_active (display->pika, coords, state,
|
||||
display);
|
||||
|
||||
if (PIKA_IS_DRAW_TOOL (active_tool))
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (active_tool));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_motion (PikaTool *tool,
|
||||
const PikaCoords *coords,
|
||||
guint32 time,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
|
||||
{
|
||||
PikaGuideTool *guide_tool = PIKA_GUIDE_TOOL (tool);
|
||||
PikaDisplayShell *shell = pika_display_get_shell (display);
|
||||
PikaImage *image = pika_display_get_image (display);
|
||||
gboolean remove_guides = FALSE;
|
||||
gint tx, ty;
|
||||
gint i;
|
||||
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
pika_display_shell_transform_xy (shell,
|
||||
coords->x, coords->y,
|
||||
&tx, &ty);
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuideToolGuide *guide = &guide_tool->guides[i];
|
||||
gint max_position;
|
||||
gint position;
|
||||
|
||||
if (guide->orientation == PIKA_ORIENTATION_HORIZONTAL)
|
||||
max_position = pika_image_get_height (image);
|
||||
else
|
||||
max_position = pika_image_get_width (image);
|
||||
|
||||
if (guide->orientation == PIKA_ORIENTATION_HORIZONTAL)
|
||||
guide->position = RINT (coords->y);
|
||||
else
|
||||
guide->position = RINT (coords->x);
|
||||
|
||||
position = CLAMP (guide->position, 0, max_position);
|
||||
|
||||
if (tx < 0 || tx >= shell->disp_width ||
|
||||
ty < 0 || ty >= shell->disp_height)
|
||||
{
|
||||
guide->position = PIKA_GUIDE_POSITION_UNDEFINED;
|
||||
|
||||
remove_guides = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (guide->position < 0 || guide->position > max_position)
|
||||
remove_guides = TRUE;
|
||||
}
|
||||
|
||||
/* custom guides are moved live */
|
||||
if (guide->custom)
|
||||
pika_image_move_guide (image, guide->guide, position, TRUE);
|
||||
}
|
||||
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
|
||||
pika_tool_pop_status (tool, display);
|
||||
|
||||
pika_guide_tool_push_status (guide_tool, display, remove_guides);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_draw (PikaDrawTool *draw_tool)
|
||||
{
|
||||
PikaGuideTool *guide_tool = PIKA_GUIDE_TOOL (draw_tool);
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuideToolGuide *guide = &guide_tool->guides[i];
|
||||
|
||||
if (guide->position != PIKA_GUIDE_POSITION_UNDEFINED)
|
||||
{
|
||||
/* custom guides are moved live */
|
||||
if (! guide->custom)
|
||||
{
|
||||
pika_draw_tool_add_guide (draw_tool,
|
||||
guide->orientation,
|
||||
guide->position,
|
||||
PIKA_GUIDE_STYLE_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_start (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
GList *guides,
|
||||
PikaOrientationType orientation)
|
||||
{
|
||||
PikaGuideTool *guide_tool;
|
||||
PikaTool *tool;
|
||||
|
||||
guide_tool = g_object_new (PIKA_TYPE_GUIDE_TOOL,
|
||||
"tool-info", parent_tool->tool_info,
|
||||
NULL);
|
||||
|
||||
tool = PIKA_TOOL (guide_tool);
|
||||
|
||||
pika_display_shell_selection_pause (pika_display_get_shell (display));
|
||||
|
||||
if (guides)
|
||||
{
|
||||
gint i;
|
||||
|
||||
guide_tool->n_guides = g_list_length (guides);
|
||||
guide_tool->guides = g_new (PikaGuideToolGuide, guide_tool->n_guides);
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuide *guide = guides->data;
|
||||
|
||||
guide_tool->guides[i].guide = g_object_ref (guide);
|
||||
guide_tool->guides[i].old_position = pika_guide_get_position (guide);
|
||||
guide_tool->guides[i].position = pika_guide_get_position (guide);
|
||||
guide_tool->guides[i].orientation = pika_guide_get_orientation (guide);
|
||||
guide_tool->guides[i].custom = pika_guide_is_custom (guide);
|
||||
|
||||
guides = g_list_next (guides);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
guide_tool->n_guides = 1;
|
||||
guide_tool->guides = g_new (PikaGuideToolGuide, 1);
|
||||
|
||||
guide_tool->guides[0].guide = NULL;
|
||||
guide_tool->guides[0].old_position = 0;
|
||||
guide_tool->guides[0].position = PIKA_GUIDE_POSITION_UNDEFINED;
|
||||
guide_tool->guides[0].orientation = orientation;
|
||||
guide_tool->guides[0].custom = FALSE;
|
||||
}
|
||||
|
||||
pika_tool_set_cursor (tool, display,
|
||||
PIKA_CURSOR_MOUSE,
|
||||
PIKA_TOOL_CURSOR_HAND,
|
||||
PIKA_CURSOR_MODIFIER_MOVE);
|
||||
|
||||
tool_manager_push_tool (display->pika, tool);
|
||||
|
||||
tool->display = display;
|
||||
pika_tool_control_activate (tool->control);
|
||||
|
||||
pika_draw_tool_start (PIKA_DRAW_TOOL (guide_tool), display);
|
||||
|
||||
pika_guide_tool_push_status (guide_tool, display, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_guide_tool_push_status (PikaGuideTool *guide_tool,
|
||||
PikaDisplay *display,
|
||||
gboolean remove_guides)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (guide_tool);
|
||||
|
||||
if (remove_guides)
|
||||
{
|
||||
pika_tool_push_status (tool, display,
|
||||
guide_tool->n_guides > 1 ? _("Remove Guides") :
|
||||
guide_tool->guides[0].guide ? _("Remove Guide") :
|
||||
_("Cancel Guide"));
|
||||
}
|
||||
else
|
||||
{
|
||||
PikaGuideToolGuide *guides[2] = { 0, };
|
||||
gint n_guides = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < guide_tool->n_guides; i++)
|
||||
{
|
||||
PikaGuideToolGuide *guide = &guide_tool->guides[i];
|
||||
|
||||
if (guide_tool->guides[i].guide)
|
||||
{
|
||||
if (n_guides == 0 || guide->orientation != guides[0]->orientation)
|
||||
{
|
||||
guides[n_guides++] = guide;
|
||||
|
||||
if (n_guides == 2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n_guides == 2 &&
|
||||
guides[0]->orientation == PIKA_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
PikaGuideToolGuide *temp;
|
||||
|
||||
temp = guides[0];
|
||||
guides[0] = guides[1];
|
||||
guides[1] = temp;
|
||||
}
|
||||
|
||||
if (n_guides == 1)
|
||||
{
|
||||
pika_tool_push_status_length (tool, display,
|
||||
_("Move Guide: "),
|
||||
SWAP_ORIENT (guides[0]->orientation),
|
||||
guides[0]->position -
|
||||
guides[0]->old_position,
|
||||
NULL);
|
||||
}
|
||||
else if (n_guides == 2)
|
||||
{
|
||||
pika_tool_push_status_coords (tool, display,
|
||||
PIKA_CURSOR_PRECISION_PIXEL_BORDER,
|
||||
_("Move Guides: "),
|
||||
guides[0]->position -
|
||||
guides[0]->old_position,
|
||||
", ",
|
||||
guides[1]->position -
|
||||
guides[1]->old_position,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_tool_push_status_length (tool, display,
|
||||
_("Add Guide: "),
|
||||
SWAP_ORIENT (guide_tool->guides[0].orientation),
|
||||
guide_tool->guides[0].position,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public functions */
|
||||
|
||||
void
|
||||
pika_guide_tool_start_new (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
PikaOrientationType orientation)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_TOOL (parent_tool));
|
||||
g_return_if_fail (PIKA_IS_DISPLAY (display));
|
||||
g_return_if_fail (orientation != PIKA_ORIENTATION_UNKNOWN);
|
||||
|
||||
pika_guide_tool_start (parent_tool, display,
|
||||
NULL, orientation);
|
||||
}
|
||||
|
||||
void
|
||||
pika_guide_tool_start_edit (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
PikaGuide *guide)
|
||||
{
|
||||
GList *guides = NULL;
|
||||
|
||||
g_return_if_fail (PIKA_IS_TOOL (parent_tool));
|
||||
g_return_if_fail (PIKA_IS_DISPLAY (display));
|
||||
g_return_if_fail (PIKA_IS_GUIDE (guide));
|
||||
|
||||
guides = g_list_append (guides, guide);
|
||||
|
||||
pika_guide_tool_start (parent_tool, display,
|
||||
guides, PIKA_ORIENTATION_UNKNOWN);
|
||||
|
||||
g_list_free (guides);
|
||||
}
|
||||
|
||||
void
|
||||
pika_guide_tool_start_edit_many (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
GList *guides)
|
||||
{
|
||||
g_return_if_fail (PIKA_IS_TOOL (parent_tool));
|
||||
g_return_if_fail (PIKA_IS_DISPLAY (display));
|
||||
g_return_if_fail (guides != NULL);
|
||||
|
||||
pika_guide_tool_start (parent_tool, display,
|
||||
guides, PIKA_ORIENTATION_UNKNOWN);
|
||||
}
|
||||
78
app/tools/pikaguidetool.h
Normal file
78
app/tools/pikaguidetool.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_GUIDE_TOOL_H__
|
||||
#define __PIKA_GUIDE_TOOL_H__
|
||||
|
||||
|
||||
#include "pikadrawtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_GUIDE_TOOL (pika_guide_tool_get_type ())
|
||||
#define PIKA_GUIDE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_GUIDE_TOOL, PikaGuideTool))
|
||||
#define PIKA_GUIDE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_GUIDE_TOOL, PikaGuideToolClass))
|
||||
#define PIKA_IS_GUIDE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_GUIDE_TOOL))
|
||||
#define PIKA_IS_GUIDE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_GUIDE_TOOL))
|
||||
#define PIKA_GUIDE_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_GUIDE_TOOL, PikaGuideToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaGuideToolGuide PikaGuideToolGuide;
|
||||
typedef struct _PikaGuideTool PikaGuideTool;
|
||||
typedef struct _PikaGuideToolClass PikaGuideToolClass;
|
||||
|
||||
struct _PikaGuideToolGuide
|
||||
{
|
||||
PikaGuide *guide;
|
||||
|
||||
gint old_position;
|
||||
gint position;
|
||||
PikaOrientationType orientation;
|
||||
gboolean custom;
|
||||
};
|
||||
|
||||
struct _PikaGuideTool
|
||||
{
|
||||
PikaDrawTool parent_instance;
|
||||
|
||||
PikaGuideToolGuide *guides;
|
||||
gint n_guides;
|
||||
};
|
||||
|
||||
struct _PikaGuideToolClass
|
||||
{
|
||||
PikaDrawToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_guide_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void pika_guide_tool_start_new (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
PikaOrientationType orientation);
|
||||
void pika_guide_tool_start_edit (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
PikaGuide *guide);
|
||||
void pika_guide_tool_start_edit_many (PikaTool *parent_tool,
|
||||
PikaDisplay *display,
|
||||
GList *guides);
|
||||
|
||||
|
||||
#endif /* __PIKA_GUIDE_TOOL_H__ */
|
||||
205
app/tools/pikahandletransformoptions.c
Normal file
205
app/tools/pikahandletransformoptions.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "core/pika.h"
|
||||
#include "core/pikatoolinfo.h"
|
||||
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "pikahandletransformoptions.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_HANDLE_MODE
|
||||
};
|
||||
|
||||
|
||||
static void pika_handle_transform_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_handle_transform_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaHandleTransformOptions, pika_handle_transform_options,
|
||||
PIKA_TYPE_TRANSFORM_GRID_OPTIONS)
|
||||
|
||||
#define parent_class pika_handle_transform_options_parent_class
|
||||
|
||||
|
||||
static void
|
||||
pika_handle_transform_options_class_init (PikaHandleTransformOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_handle_transform_options_set_property;
|
||||
object_class->get_property = pika_handle_transform_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_HANDLE_MODE,
|
||||
"handle-mode",
|
||||
_("Handle mode"),
|
||||
_("Handle mode"),
|
||||
PIKA_TYPE_TRANSFORM_HANDLE_MODE,
|
||||
PIKA_HANDLE_MODE_ADD_TRANSFORM,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_options_init (PikaHandleTransformOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaHandleTransformOptions *options = PIKA_HANDLE_TRANSFORM_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_HANDLE_MODE:
|
||||
options->handle_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaHandleTransformOptions *options = PIKA_HANDLE_TRANSFORM_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_HANDLE_MODE:
|
||||
g_value_set_enum (value, options->handle_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pika_handle_transform_options_gui:
|
||||
* @tool_options: a #PikaToolOptions
|
||||
*
|
||||
* Build the Transform Tool Options.
|
||||
*
|
||||
* Returns: a container holding the transform tool options
|
||||
**/
|
||||
GtkWidget *
|
||||
pika_handle_transform_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_transform_grid_options_gui (tool_options);
|
||||
GtkWidget *frame;
|
||||
GtkWidget *button;
|
||||
gint i;
|
||||
|
||||
frame = pika_prop_enum_radio_frame_new (config, "handle-mode", NULL,
|
||||
0, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* add modifier to name, add tooltip */
|
||||
button = g_object_get_data (G_OBJECT (frame), "radio-button");
|
||||
|
||||
if (GTK_IS_RADIO_BUTTON (button))
|
||||
{
|
||||
GSList *list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
|
||||
|
||||
for (i = g_slist_length (list) - 1 ; list; list = list->next, i--)
|
||||
{
|
||||
GdkModifierType shift = pika_get_extend_selection_mask ();
|
||||
GdkModifierType ctrl = pika_get_constrain_behavior_mask ();
|
||||
GdkModifierType modifier = 0;
|
||||
gchar *tooltip = "";
|
||||
gchar *tip;
|
||||
gchar *label;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case PIKA_HANDLE_MODE_ADD_TRANSFORM:
|
||||
modifier = 0;
|
||||
tooltip = _("Add handles and transform the image");
|
||||
break;
|
||||
|
||||
case PIKA_HANDLE_MODE_MOVE:
|
||||
modifier = shift;
|
||||
tooltip = _("Move transform handles");
|
||||
break;
|
||||
|
||||
case PIKA_HANDLE_MODE_REMOVE:
|
||||
modifier = ctrl;
|
||||
tooltip = _("Remove transform handles");
|
||||
break;
|
||||
}
|
||||
|
||||
if (modifier)
|
||||
{
|
||||
label = g_strdup_printf ("%s (%s)",
|
||||
gtk_button_get_label (GTK_BUTTON (list->data)),
|
||||
pika_get_mod_string (modifier));
|
||||
gtk_button_set_label (GTK_BUTTON (list->data), label);
|
||||
g_free (label);
|
||||
|
||||
tip = g_strdup_printf ("%s (%s)",
|
||||
tooltip, pika_get_mod_string (modifier));
|
||||
pika_help_set_help_data (list->data, tip, NULL);
|
||||
g_free (tip);
|
||||
}
|
||||
else
|
||||
{
|
||||
pika_help_set_help_data (list->data, tooltip, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vbox;
|
||||
}
|
||||
58
app/tools/pikahandletransformoptions.h
Normal file
58
app/tools/pikahandletransformoptions.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_HANDLE_TRANSFORM_OPTIONS_H__
|
||||
#define __PIKA_HANDLE_TRANSFORM_OPTIONS_H__
|
||||
|
||||
|
||||
#include "pikatransformgridoptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS (pika_handle_transform_options_get_type ())
|
||||
#define PIKA_HANDLE_TRANSFORM_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS, PikaHandleTransformOptions))
|
||||
#define PIKA_HANDLE_TRANSFORM_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS, PikaHandleTransformOptionsClass))
|
||||
#define PIKA_IS_HANDLE_TRANSFORM_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS))
|
||||
#define PIKA_IS_HANDLE_TRANSFORM_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS))
|
||||
#define PIKA_HANDLE_TRANSFORM_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS, PikaHandleTransformOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaHandleTransformOptions PikaHandleTransformOptions;
|
||||
typedef struct _PikaHandleTransformOptionsClass PikaHandleTransformOptionsClass;
|
||||
|
||||
struct _PikaHandleTransformOptions
|
||||
{
|
||||
PikaTransformGridOptions parent_instance;
|
||||
|
||||
PikaTransformHandleMode handle_mode;
|
||||
};
|
||||
|
||||
struct _PikaHandleTransformOptionsClass
|
||||
{
|
||||
PikaTransformGridOptionsClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_handle_transform_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * pika_handle_transform_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_HANDLE_TRANSFORM_OPTIONS_H__ */
|
||||
388
app/tools/pikahandletransformtool.c
Normal file
388
app/tools/pikahandletransformtool.c
Normal file
@ -0,0 +1,388 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikamath/pikamath.h"
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
#include "widgets/pikawidgets-utils.h"
|
||||
|
||||
#include "display/pikadisplay.h"
|
||||
#include "display/pikatoolhandlegrid.h"
|
||||
#include "display/pikatoolgui.h"
|
||||
|
||||
#include "pikahandletransformoptions.h"
|
||||
#include "pikahandletransformtool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
/* the transformation is defined by 8 points:
|
||||
*
|
||||
* 4 points on the original image and 4 corresponding points on the
|
||||
* transformed image. The first N_HANDLES points on the transformed
|
||||
* image are visible as handles.
|
||||
*
|
||||
* For these handles, the constants TRANSFORM_HANDLE_N,
|
||||
* TRANSFORM_HANDLE_S, TRANSFORM_HANDLE_E and TRANSFORM_HANDLE_W are
|
||||
* used. Actually, it makes no sense to name the handles with north,
|
||||
* south, east, and west. But this way, we don't need to define even
|
||||
* more enum constants.
|
||||
*/
|
||||
|
||||
/* index into trans_info array */
|
||||
enum
|
||||
{
|
||||
X0,
|
||||
Y0,
|
||||
X1,
|
||||
Y1,
|
||||
X2,
|
||||
Y2,
|
||||
X3,
|
||||
Y3,
|
||||
OX0,
|
||||
OY0,
|
||||
OX1,
|
||||
OY1,
|
||||
OX2,
|
||||
OY2,
|
||||
OX3,
|
||||
OY3,
|
||||
N_HANDLES
|
||||
};
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
|
||||
static void pika_handle_transform_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display);
|
||||
|
||||
static void pika_handle_transform_tool_matrix_to_info (PikaTransformGridTool *tg_tool,
|
||||
const PikaMatrix3 *transform);
|
||||
static void pika_handle_transform_tool_prepare (PikaTransformGridTool *tg_tool);
|
||||
static PikaToolWidget * pika_handle_transform_tool_get_widget (PikaTransformGridTool *tg_tool);
|
||||
static void pika_handle_transform_tool_update_widget (PikaTransformGridTool *tg_tool);
|
||||
static void pika_handle_transform_tool_widget_changed (PikaTransformGridTool *tg_tool);
|
||||
|
||||
static void pika_handle_transform_tool_info_to_points (PikaGenericTransformTool *generic);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaHandleTransformTool, pika_handle_transform_tool,
|
||||
PIKA_TYPE_GENERIC_TRANSFORM_TOOL)
|
||||
|
||||
#define parent_class pika_handle_transform_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_handle_transform_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_HANDLE_TRANSFORM_TOOL,
|
||||
PIKA_TYPE_HANDLE_TRANSFORM_OPTIONS,
|
||||
pika_handle_transform_options_gui,
|
||||
PIKA_CONTEXT_PROP_MASK_BACKGROUND,
|
||||
"pika-handle-transform-tool",
|
||||
_("Handle Transform"),
|
||||
_("Handle Transform Tool: "
|
||||
"Deform the layer, selection or path with handles"),
|
||||
N_("_Handle Transform"), "<shift>L",
|
||||
NULL, PIKA_HELP_TOOL_HANDLE_TRANSFORM,
|
||||
PIKA_ICON_TOOL_HANDLE_TRANSFORM,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_class_init (PikaHandleTransformToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaTransformToolClass *tr_class = PIKA_TRANSFORM_TOOL_CLASS (klass);
|
||||
PikaTransformGridToolClass *tg_class = PIKA_TRANSFORM_GRID_TOOL_CLASS (klass);
|
||||
PikaGenericTransformToolClass *generic_class = PIKA_GENERIC_TRANSFORM_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->modifier_key = pika_handle_transform_tool_modifier_key;
|
||||
|
||||
tg_class->matrix_to_info = pika_handle_transform_tool_matrix_to_info;
|
||||
tg_class->prepare = pika_handle_transform_tool_prepare;
|
||||
tg_class->get_widget = pika_handle_transform_tool_get_widget;
|
||||
tg_class->update_widget = pika_handle_transform_tool_update_widget;
|
||||
tg_class->widget_changed = pika_handle_transform_tool_widget_changed;
|
||||
|
||||
generic_class->info_to_points = pika_handle_transform_tool_info_to_points;
|
||||
|
||||
tr_class->undo_desc = C_("undo-type", "Handle transform");
|
||||
tr_class->progress_text = _("Handle transformation");
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_init (PikaHandleTransformTool *ht_tool)
|
||||
{
|
||||
ht_tool->saved_handle_mode = PIKA_HANDLE_MODE_ADD_TRANSFORM;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_modifier_key (PikaTool *tool,
|
||||
GdkModifierType key,
|
||||
gboolean press,
|
||||
GdkModifierType state,
|
||||
PikaDisplay *display)
|
||||
{
|
||||
PikaHandleTransformTool *ht_tool = PIKA_HANDLE_TRANSFORM_TOOL (tool);
|
||||
PikaHandleTransformOptions *options;
|
||||
GdkModifierType shift = pika_get_extend_selection_mask ();
|
||||
GdkModifierType ctrl = pika_get_constrain_behavior_mask ();
|
||||
PikaTransformHandleMode handle_mode;
|
||||
|
||||
options = PIKA_HANDLE_TRANSFORM_TOOL_GET_OPTIONS (tool);
|
||||
|
||||
handle_mode = options->handle_mode;
|
||||
|
||||
if (press)
|
||||
{
|
||||
if (key == (state & (shift | ctrl)))
|
||||
{
|
||||
/* first modifier pressed */
|
||||
ht_tool->saved_handle_mode = options->handle_mode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! (state & (shift | ctrl)))
|
||||
{
|
||||
/* last modifier released */
|
||||
handle_mode = ht_tool->saved_handle_mode;
|
||||
}
|
||||
}
|
||||
|
||||
if (state & shift)
|
||||
{
|
||||
handle_mode = PIKA_HANDLE_MODE_MOVE;
|
||||
}
|
||||
else if (state & ctrl)
|
||||
{
|
||||
handle_mode = PIKA_HANDLE_MODE_REMOVE;
|
||||
}
|
||||
|
||||
if (handle_mode != options->handle_mode)
|
||||
{
|
||||
g_object_set (options,
|
||||
"handle-mode", handle_mode,
|
||||
NULL);
|
||||
}
|
||||
|
||||
PIKA_TOOL_CLASS (parent_class)->modifier_key (tool, key, press,
|
||||
state, display);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_matrix_to_info (PikaTransformGridTool *tg_tool,
|
||||
const PikaMatrix3 *transform)
|
||||
{
|
||||
pika_matrix3_transform_point (transform,
|
||||
tg_tool->trans_info[OX0],
|
||||
tg_tool->trans_info[OY0],
|
||||
&tg_tool->trans_info[X0],
|
||||
&tg_tool->trans_info[Y0]);
|
||||
pika_matrix3_transform_point (transform,
|
||||
tg_tool->trans_info[OX1],
|
||||
tg_tool->trans_info[OY1],
|
||||
&tg_tool->trans_info[X1],
|
||||
&tg_tool->trans_info[Y1]);
|
||||
pika_matrix3_transform_point (transform,
|
||||
tg_tool->trans_info[OX2],
|
||||
tg_tool->trans_info[OY2],
|
||||
&tg_tool->trans_info[X2],
|
||||
&tg_tool->trans_info[Y2]);
|
||||
pika_matrix3_transform_point (transform,
|
||||
tg_tool->trans_info[OX3],
|
||||
tg_tool->trans_info[OY3],
|
||||
&tg_tool->trans_info[X3],
|
||||
&tg_tool->trans_info[Y3]);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_prepare (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
PikaTransformTool *tr_tool = PIKA_TRANSFORM_TOOL (tg_tool);
|
||||
|
||||
PIKA_TRANSFORM_GRID_TOOL_CLASS (parent_class)->prepare (tg_tool);
|
||||
|
||||
tg_tool->trans_info[X0] = (gdouble) tr_tool->x1;
|
||||
tg_tool->trans_info[Y0] = (gdouble) tr_tool->y1;
|
||||
tg_tool->trans_info[X1] = (gdouble) tr_tool->x2;
|
||||
tg_tool->trans_info[Y1] = (gdouble) tr_tool->y1;
|
||||
tg_tool->trans_info[X2] = (gdouble) tr_tool->x1;
|
||||
tg_tool->trans_info[Y2] = (gdouble) tr_tool->y2;
|
||||
tg_tool->trans_info[X3] = (gdouble) tr_tool->x2;
|
||||
tg_tool->trans_info[Y3] = (gdouble) tr_tool->y2;
|
||||
tg_tool->trans_info[OX0] = (gdouble) tr_tool->x1;
|
||||
tg_tool->trans_info[OY0] = (gdouble) tr_tool->y1;
|
||||
tg_tool->trans_info[OX1] = (gdouble) tr_tool->x2;
|
||||
tg_tool->trans_info[OY1] = (gdouble) tr_tool->y1;
|
||||
tg_tool->trans_info[OX2] = (gdouble) tr_tool->x1;
|
||||
tg_tool->trans_info[OY2] = (gdouble) tr_tool->y2;
|
||||
tg_tool->trans_info[OX3] = (gdouble) tr_tool->x2;
|
||||
tg_tool->trans_info[OY3] = (gdouble) tr_tool->y2;
|
||||
tg_tool->trans_info[N_HANDLES] = 0;
|
||||
}
|
||||
|
||||
static PikaToolWidget *
|
||||
pika_handle_transform_tool_get_widget (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (tg_tool);
|
||||
PikaTransformTool *tr_tool = PIKA_TRANSFORM_TOOL (tg_tool);
|
||||
PikaHandleTransformOptions *options;
|
||||
PikaDisplayShell *shell = pika_display_get_shell (tool->display);
|
||||
PikaToolWidget *widget;
|
||||
|
||||
options = PIKA_HANDLE_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
||||
|
||||
widget = pika_tool_handle_grid_new (shell,
|
||||
tr_tool->x1,
|
||||
tr_tool->y1,
|
||||
tr_tool->x2,
|
||||
tr_tool->y2);
|
||||
|
||||
g_object_set (widget,
|
||||
"n-handles", (gint) tg_tool->trans_info[N_HANDLES],
|
||||
"orig-x1", tg_tool->trans_info[OX0],
|
||||
"orig-y1", tg_tool->trans_info[OY0],
|
||||
"orig-x2", tg_tool->trans_info[OX1],
|
||||
"orig-y2", tg_tool->trans_info[OY1],
|
||||
"orig-x3", tg_tool->trans_info[OX2],
|
||||
"orig-y3", tg_tool->trans_info[OY2],
|
||||
"orig-x4", tg_tool->trans_info[OX3],
|
||||
"orig-y4", tg_tool->trans_info[OY3],
|
||||
"trans-x1", tg_tool->trans_info[X0],
|
||||
"trans-y1", tg_tool->trans_info[Y0],
|
||||
"trans-x2", tg_tool->trans_info[X1],
|
||||
"trans-y2", tg_tool->trans_info[Y1],
|
||||
"trans-x3", tg_tool->trans_info[X2],
|
||||
"trans-y3", tg_tool->trans_info[Y2],
|
||||
"trans-x4", tg_tool->trans_info[X3],
|
||||
"trans-y4", tg_tool->trans_info[Y3],
|
||||
NULL);
|
||||
|
||||
g_object_bind_property (G_OBJECT (options), "handle-mode",
|
||||
G_OBJECT (widget), "handle-mode",
|
||||
G_BINDING_SYNC_CREATE |
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_update_widget (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
PikaMatrix3 transform;
|
||||
gboolean transform_valid;
|
||||
|
||||
PIKA_TRANSFORM_GRID_TOOL_CLASS (parent_class)->update_widget (tg_tool);
|
||||
|
||||
transform_valid = pika_transform_grid_tool_info_to_matrix (tg_tool,
|
||||
&transform);
|
||||
|
||||
g_object_set (tg_tool->widget,
|
||||
"show-guides", transform_valid,
|
||||
"n-handles", (gint) tg_tool->trans_info[N_HANDLES],
|
||||
"orig-x1", tg_tool->trans_info[OX0],
|
||||
"orig-y1", tg_tool->trans_info[OY0],
|
||||
"orig-x2", tg_tool->trans_info[OX1],
|
||||
"orig-y2", tg_tool->trans_info[OY1],
|
||||
"orig-x3", tg_tool->trans_info[OX2],
|
||||
"orig-y3", tg_tool->trans_info[OY2],
|
||||
"orig-x4", tg_tool->trans_info[OX3],
|
||||
"orig-y4", tg_tool->trans_info[OY3],
|
||||
"trans-x1", tg_tool->trans_info[X0],
|
||||
"trans-y1", tg_tool->trans_info[Y0],
|
||||
"trans-x2", tg_tool->trans_info[X1],
|
||||
"trans-y2", tg_tool->trans_info[Y1],
|
||||
"trans-x3", tg_tool->trans_info[X2],
|
||||
"trans-y3", tg_tool->trans_info[Y2],
|
||||
"trans-x4", tg_tool->trans_info[X3],
|
||||
"trans-y4", tg_tool->trans_info[Y3],
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_widget_changed (PikaTransformGridTool *tg_tool)
|
||||
{
|
||||
gint n_handles;
|
||||
|
||||
g_object_get (tg_tool->widget,
|
||||
"n-handles", &n_handles,
|
||||
"orig-x1", &tg_tool->trans_info[OX0],
|
||||
"orig-y1", &tg_tool->trans_info[OY0],
|
||||
"orig-x2", &tg_tool->trans_info[OX1],
|
||||
"orig-y2", &tg_tool->trans_info[OY1],
|
||||
"orig-x3", &tg_tool->trans_info[OX2],
|
||||
"orig-y3", &tg_tool->trans_info[OY2],
|
||||
"orig-x4", &tg_tool->trans_info[OX3],
|
||||
"orig-y4", &tg_tool->trans_info[OY3],
|
||||
"trans-x1", &tg_tool->trans_info[X0],
|
||||
"trans-y1", &tg_tool->trans_info[Y0],
|
||||
"trans-x2", &tg_tool->trans_info[X1],
|
||||
"trans-y2", &tg_tool->trans_info[Y1],
|
||||
"trans-x3", &tg_tool->trans_info[X2],
|
||||
"trans-y3", &tg_tool->trans_info[Y2],
|
||||
"trans-x4", &tg_tool->trans_info[X3],
|
||||
"trans-y4", &tg_tool->trans_info[Y3],
|
||||
NULL);
|
||||
|
||||
tg_tool->trans_info[N_HANDLES] = n_handles;
|
||||
|
||||
PIKA_TRANSFORM_GRID_TOOL_CLASS (parent_class)->widget_changed (tg_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_handle_transform_tool_info_to_points (PikaGenericTransformTool *generic)
|
||||
{
|
||||
PikaTransformGridTool *tg_tool = PIKA_TRANSFORM_GRID_TOOL (generic);
|
||||
|
||||
generic->input_points[0] = (PikaVector2) {tg_tool->trans_info[OX0],
|
||||
tg_tool->trans_info[OY0]};
|
||||
generic->input_points[1] = (PikaVector2) {tg_tool->trans_info[OX1],
|
||||
tg_tool->trans_info[OY1]};
|
||||
generic->input_points[2] = (PikaVector2) {tg_tool->trans_info[OX2],
|
||||
tg_tool->trans_info[OY2]};
|
||||
generic->input_points[3] = (PikaVector2) {tg_tool->trans_info[OX3],
|
||||
tg_tool->trans_info[OY3]};
|
||||
|
||||
generic->output_points[0] = (PikaVector2) {tg_tool->trans_info[X0],
|
||||
tg_tool->trans_info[Y0]};
|
||||
generic->output_points[1] = (PikaVector2) {tg_tool->trans_info[X1],
|
||||
tg_tool->trans_info[Y1]};
|
||||
generic->output_points[2] = (PikaVector2) {tg_tool->trans_info[X2],
|
||||
tg_tool->trans_info[Y2]};
|
||||
generic->output_points[3] = (PikaVector2) {tg_tool->trans_info[X3],
|
||||
tg_tool->trans_info[Y3]};
|
||||
}
|
||||
61
app/tools/pikahandletransformtool.h
Normal file
61
app/tools/pikahandletransformtool.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_HANDLE_TRANSFORM_TOOL_H__
|
||||
#define __PIKA_HANDLE_TRANSFORM_TOOL_H__
|
||||
|
||||
|
||||
#include "pikagenerictransformtool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_HANDLE_TRANSFORM_TOOL (pika_handle_transform_tool_get_type ())
|
||||
#define PIKA_HANDLE_TRANSFORM_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_HANDLE_TRANSFORM_TOOL, PikaHandleTransformTool))
|
||||
#define PIKA_HANDLE_TRANSFORM_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_HANDLE_TRANSFORM_TOOL, PikaHandleTransformToolClass))
|
||||
#define PIKA_IS_HANDLE_TRANSFORM_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_HANDLE_TRANSFORM_TOOL))
|
||||
#define PIKA_IS_HANDLE_TRANSFORM_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_HANDLE_TRANSFORM_TOOL))
|
||||
#define PIKA_HANDLE_TRANSFORM_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_HANDLE_TRANSFORM_TOOL, PikaHandleTransformToolClass))
|
||||
|
||||
#define PIKA_HANDLE_TRANSFORM_TOOL_GET_OPTIONS(t) (PIKA_HANDLE_TRANSFORM_OPTIONS (pika_tool_get_options (PIKA_TOOL (t))))
|
||||
|
||||
|
||||
typedef struct _PikaHandleTransformTool PikaHandleTransformTool;
|
||||
typedef struct _PikaHandleTransformToolClass PikaHandleTransformToolClass;
|
||||
|
||||
struct _PikaHandleTransformTool
|
||||
{
|
||||
PikaGenericTransformTool parent_instance;
|
||||
|
||||
PikaTransformHandleMode saved_handle_mode;
|
||||
};
|
||||
|
||||
struct _PikaHandleTransformToolClass
|
||||
{
|
||||
PikaGenericTransformToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_handle_transform_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_handle_transform_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_HANDLE_TRANSFORM_TOOL_H__ */
|
||||
113
app/tools/pikahealtool.c
Normal file
113
app/tools/pikahealtool.c
Normal file
@ -0,0 +1,113 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "paint/pikasourceoptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "pikahealtool.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static GtkWidget * pika_heal_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaHealTool, pika_heal_tool, PIKA_TYPE_SOURCE_TOOL)
|
||||
|
||||
|
||||
void
|
||||
pika_heal_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_HEAL_TOOL,
|
||||
PIKA_TYPE_SOURCE_OPTIONS,
|
||||
pika_heal_options_gui,
|
||||
PIKA_PAINT_OPTIONS_CONTEXT_MASK,
|
||||
"pika-heal-tool",
|
||||
_("Healing"),
|
||||
_("Healing Tool: Heal image irregularities"),
|
||||
N_("_Heal"),
|
||||
"H",
|
||||
NULL,
|
||||
PIKA_HELP_TOOL_HEAL,
|
||||
PIKA_ICON_TOOL_HEAL,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_heal_tool_class_init (PikaHealToolClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_heal_tool_init (PikaHealTool *heal)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (heal);
|
||||
PikaPaintTool *paint_tool = PIKA_PAINT_TOOL (tool);
|
||||
PikaSourceTool *source_tool = PIKA_SOURCE_TOOL (tool);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_HEAL);
|
||||
|
||||
paint_tool->status = _("Click to heal");
|
||||
paint_tool->status_ctrl = _("%s to set a new heal source");
|
||||
|
||||
source_tool->status_paint = _("Click to heal");
|
||||
/* Translators: the translation of "Click" must be the first word */
|
||||
source_tool->status_set_source = _("Click to set a new heal source");
|
||||
source_tool->status_set_source_ctrl = _("%s to set a new heal source");
|
||||
}
|
||||
|
||||
|
||||
/* tool options stuff */
|
||||
|
||||
static GtkWidget *
|
||||
pika_heal_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *button;
|
||||
GtkWidget *combo;
|
||||
|
||||
/* the sample merged checkbox */
|
||||
button = pika_prop_check_button_new (config, "sample-merged",
|
||||
_("Sample merged"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
/* the alignment combo */
|
||||
combo = pika_prop_enum_combo_box_new (config, "align-mode", 0, 0);
|
||||
pika_int_combo_box_set_label (PIKA_INT_COMBO_BOX (combo), _("Alignment"));
|
||||
g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
57
app/tools/pikahealtool.h
Normal file
57
app/tools/pikahealtool.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_HEAL_TOOL_H__
|
||||
#define __PIKA_HEAL_TOOL_H__
|
||||
|
||||
|
||||
#include "pikasourcetool.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_HEAL_TOOL (pika_heal_tool_get_type ())
|
||||
#define PIKA_HEAL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_HEAL_TOOL, PikaHealTool))
|
||||
#define PIKA_HEAL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_HEAL_TOOL, PikaHealToolClass))
|
||||
#define PIKA_IS_HEAL_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_HEAL_TOOL))
|
||||
#define PIKA_IS_HEAL_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_HEAL_TOOL))
|
||||
#define PIKA_HEAL_TOOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_HEAL_TOOL, PikaHealToolClass))
|
||||
|
||||
|
||||
typedef struct _PikaHealTool PikaHealTool;
|
||||
typedef struct _PikaHealToolClass PikaHealToolClass;
|
||||
|
||||
struct _PikaHealTool
|
||||
{
|
||||
PikaSourceTool parent_instance;
|
||||
};
|
||||
|
||||
struct _PikaHealToolClass
|
||||
{
|
||||
PikaSourceToolClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
void pika_heal_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data);
|
||||
|
||||
GType pika_heal_tool_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_HEAL_TOOL_H__ */
|
||||
118
app/tools/pikahistogramoptions.c
Normal file
118
app/tools/pikahistogramoptions.c
Normal file
@ -0,0 +1,118 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikabase/pikabase.h"
|
||||
#include "libpikaconfig/pikaconfig.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "pikahistogramoptions.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SCALE
|
||||
};
|
||||
|
||||
|
||||
static void pika_histogram_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void pika_histogram_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaHistogramOptions, pika_histogram_options,
|
||||
PIKA_TYPE_FILTER_OPTIONS)
|
||||
|
||||
|
||||
static void
|
||||
pika_histogram_options_class_init (PikaHistogramOptionsClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = pika_histogram_options_set_property;
|
||||
object_class->get_property = pika_histogram_options_get_property;
|
||||
|
||||
PIKA_CONFIG_PROP_ENUM (object_class, PROP_SCALE,
|
||||
"histogram-scale",
|
||||
_("Histogram Scale"),
|
||||
NULL,
|
||||
PIKA_TYPE_HISTOGRAM_SCALE,
|
||||
PIKA_HISTOGRAM_SCALE_LINEAR,
|
||||
PIKA_PARAM_STATIC_STRINGS);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_histogram_options_init (PikaHistogramOptions *options)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pika_histogram_options_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaHistogramOptions *options = PIKA_HISTOGRAM_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_SCALE:
|
||||
options->scale = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pika_histogram_options_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PikaHistogramOptions *options = PIKA_HISTOGRAM_OPTIONS (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_SCALE:
|
||||
g_value_set_enum (value, options->scale);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
56
app/tools/pikahistogramoptions.h
Normal file
56
app/tools/pikahistogramoptions.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_HISTOGRAM_OPTIONS_H__
|
||||
#define __PIKA_HISTOGRAM_OPTIONS_H__
|
||||
|
||||
|
||||
#include "pikafilteroptions.h"
|
||||
|
||||
|
||||
#define PIKA_TYPE_HISTOGRAM_OPTIONS (pika_histogram_options_get_type ())
|
||||
#define PIKA_HISTOGRAM_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PIKA_TYPE_HISTOGRAM_OPTIONS, PikaHistogramOptions))
|
||||
#define PIKA_HISTOGRAM_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PIKA_TYPE_HISTOGRAM_OPTIONS, PikaHistogramOptionsClass))
|
||||
#define PIKA_IS_HISTOGRAM_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PIKA_TYPE_HISTOGRAM_OPTIONS))
|
||||
#define PIKA_IS_HISTOGRAM_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PIKA_TYPE_HISTOGRAM_OPTIONS))
|
||||
#define PIKA_HISTOGRAM_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PIKA_TYPE_HISTOGRAM_OPTIONS, PikaHistogramOptionsClass))
|
||||
|
||||
|
||||
typedef struct _PikaHistogramOptions PikaHistogramOptions;
|
||||
typedef struct _PikaHistogramOptionsClass PikaHistogramOptionsClass;
|
||||
|
||||
struct _PikaHistogramOptions
|
||||
{
|
||||
PikaFilterOptions parent_instance;
|
||||
|
||||
PikaHistogramScale scale;
|
||||
};
|
||||
|
||||
struct _PikaHistogramOptionsClass
|
||||
{
|
||||
PikaFilterOptionsClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType pika_histogram_options_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
#endif /* __PIKA_HISTOGRAM_OPTIONS_H__ */
|
||||
141
app/tools/pikainkoptions-gui.c
Normal file
141
app/tools/pikainkoptions-gui.c
Normal file
@ -0,0 +1,141 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "config/pikaconfig-utils.h"
|
||||
|
||||
#include "paint/pikainkoptions.h"
|
||||
|
||||
#include "widgets/pikablobeditor.h"
|
||||
#include "widgets/pikapropwidgets.h"
|
||||
|
||||
#include "pikainkoptions-gui.h"
|
||||
#include "pikapaintoptions-gui.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
GtkWidget *
|
||||
pika_ink_options_gui (PikaToolOptions *tool_options)
|
||||
{
|
||||
GObject *config = G_OBJECT (tool_options);
|
||||
PikaInkOptions *ink_options = PIKA_INK_OPTIONS (tool_options);
|
||||
GtkWidget *vbox = pika_paint_options_gui (tool_options);
|
||||
GtkWidget *frame;
|
||||
GtkWidget *vbox2;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *blob_box;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *editor;
|
||||
GtkSizeGroup *size_group;
|
||||
|
||||
/* adjust sliders */
|
||||
frame = pika_frame_new (_("Adjustment"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox2);
|
||||
gtk_widget_show (vbox2);
|
||||
|
||||
/* size slider */
|
||||
scale = pika_prop_spin_scale_new (config, "size",
|
||||
1.0, 2.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* angle adjust slider */
|
||||
scale = pika_prop_spin_scale_new (config, "tilt-angle",
|
||||
1.0, 10.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* sens sliders */
|
||||
frame = pika_frame_new (_("Sensitivity"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_container_add (GTK_CONTAINER (frame), vbox2);
|
||||
gtk_widget_show (vbox2);
|
||||
|
||||
/* size sens slider */
|
||||
scale = pika_prop_spin_scale_new (config, "size-sensitivity",
|
||||
0.01, 0.1, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* tilt sens slider */
|
||||
scale = pika_prop_spin_scale_new (config, "tilt-sensitivity",
|
||||
0.01, 0.1, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* velocity sens slider */
|
||||
scale = pika_prop_spin_scale_new (config, "vel-sensitivity",
|
||||
0.01, 0.1, 2);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
|
||||
/* Blob shape widgets */
|
||||
frame = pika_frame_new (_("Shape"));
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
||||
gtk_container_add (GTK_CONTAINER (frame), hbox);
|
||||
gtk_widget_show (hbox);
|
||||
|
||||
size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
|
||||
|
||||
/* Blob type radiobuttons */
|
||||
blob_box = pika_prop_enum_icon_box_new (config, "blob-type",
|
||||
"pika-shape", 0, 0);
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (blob_box),
|
||||
GTK_ORIENTATION_VERTICAL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), blob_box, FALSE, FALSE, 0);
|
||||
|
||||
gtk_size_group_add_widget (size_group, blob_box);
|
||||
g_object_unref (size_group);
|
||||
|
||||
/* Blob editor */
|
||||
frame = gtk_aspect_frame_new (NULL, 0.0, 0.5, 1.0, FALSE);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
|
||||
gtk_widget_show (frame);
|
||||
|
||||
gtk_size_group_add_widget (size_group, frame);
|
||||
|
||||
editor = pika_blob_editor_new (ink_options->blob_type,
|
||||
ink_options->blob_aspect,
|
||||
ink_options->blob_angle);
|
||||
gtk_container_add (GTK_CONTAINER (frame), editor);
|
||||
gtk_widget_show (editor);
|
||||
|
||||
pika_config_connect (config, G_OBJECT (editor), "blob-type");
|
||||
pika_config_connect (config, G_OBJECT (editor), "blob-aspect");
|
||||
pika_config_connect (config, G_OBJECT (editor), "blob-angle");
|
||||
|
||||
return vbox;
|
||||
}
|
||||
29
app/tools/pikainkoptions-gui.h
Normal file
29
app/tools/pikainkoptions-gui.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PIKA_INK_OPTIONS_GUI_H__
|
||||
#define __PIKA_INK_OPTIONS_GUI_H__
|
||||
|
||||
|
||||
GtkWidget * pika_ink_options_gui (PikaToolOptions *tool_options);
|
||||
|
||||
|
||||
#endif /* __PIKA_INK_OPTIONS_GUI_H__ */
|
||||
153
app/tools/pikainktool.c
Normal file
153
app/tools/pikainktool.c
Normal file
@ -0,0 +1,153 @@
|
||||
/* PIKA - Photo and Image Kooker Application
|
||||
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
||||
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
||||
*
|
||||
* Original copyright, applying to most contents (license remains unchanged):
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "libpikawidgets/pikawidgets.h"
|
||||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "operations/layer-modes/pika-layer-modes.h"
|
||||
|
||||
#include "paint/pikainkoptions.h"
|
||||
|
||||
#include "widgets/pikahelp-ids.h"
|
||||
|
||||
#include "pikainkoptions-gui.h"
|
||||
#include "pikainktool.h"
|
||||
#include "pikatoolcontrol.h"
|
||||
|
||||
#include "pika-intl.h"
|
||||
|
||||
|
||||
static PikaCanvasItem * pika_ink_tool_get_outline (PikaPaintTool *paint_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
static gboolean pika_ink_tool_is_alpha_only (PikaPaintTool *paint_tool,
|
||||
PikaDrawable *drawable);
|
||||
|
||||
static void pika_ink_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (PikaInkTool, pika_ink_tool, PIKA_TYPE_PAINT_TOOL)
|
||||
|
||||
#define parent_class pika_ink_tool_parent_class
|
||||
|
||||
|
||||
void
|
||||
pika_ink_tool_register (PikaToolRegisterCallback callback,
|
||||
gpointer data)
|
||||
{
|
||||
(* callback) (PIKA_TYPE_INK_TOOL,
|
||||
PIKA_TYPE_INK_OPTIONS,
|
||||
pika_ink_options_gui,
|
||||
PIKA_CONTEXT_PROP_MASK_FOREGROUND |
|
||||
PIKA_CONTEXT_PROP_MASK_BACKGROUND |
|
||||
PIKA_CONTEXT_PROP_MASK_OPACITY |
|
||||
PIKA_CONTEXT_PROP_MASK_PAINT_MODE,
|
||||
"pika-ink-tool",
|
||||
_("Ink"),
|
||||
_("Ink Tool: Calligraphy-style painting"),
|
||||
N_("In_k"), "K",
|
||||
NULL, PIKA_HELP_TOOL_INK,
|
||||
PIKA_ICON_TOOL_INK,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_ink_tool_class_init (PikaInkToolClass *klass)
|
||||
{
|
||||
PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass);
|
||||
PikaPaintToolClass *paint_tool_class = PIKA_PAINT_TOOL_CLASS (klass);
|
||||
|
||||
tool_class->options_notify = pika_ink_tool_options_notify;
|
||||
|
||||
paint_tool_class->get_outline = pika_ink_tool_get_outline;
|
||||
paint_tool_class->is_alpha_only = pika_ink_tool_is_alpha_only;
|
||||
}
|
||||
|
||||
static void
|
||||
pika_ink_tool_init (PikaInkTool *ink_tool)
|
||||
{
|
||||
PikaTool *tool = PIKA_TOOL (ink_tool);
|
||||
|
||||
pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_INK);
|
||||
pika_tool_control_set_action_pixel_size (tool->control,
|
||||
"tools-ink-blob-pixel-size-set");
|
||||
pika_tool_control_set_action_size (tool->control,
|
||||
"tools-ink-blob-size-set");
|
||||
pika_tool_control_set_action_aspect (tool->control,
|
||||
"tools-ink-blob-aspect-set");
|
||||
pika_tool_control_set_action_angle (tool->control,
|
||||
"tools-ink-blob-angle-set");
|
||||
|
||||
pika_paint_tool_enable_color_picker (PIKA_PAINT_TOOL (ink_tool),
|
||||
PIKA_COLOR_PICK_TARGET_FOREGROUND);
|
||||
}
|
||||
|
||||
static void
|
||||
pika_ink_tool_options_notify (PikaTool *tool,
|
||||
PikaToolOptions *options,
|
||||
const GParamSpec *pspec)
|
||||
{
|
||||
PIKA_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
|
||||
|
||||
if (g_strcmp0 (pspec->name, "size") == 0 &&
|
||||
PIKA_PAINT_TOOL (tool)->draw_brush)
|
||||
{
|
||||
/* This triggers a redraw of the tool pointer, especially useful
|
||||
* here when we change the pen size with on-canvas interaction.
|
||||
*/
|
||||
pika_draw_tool_pause (PIKA_DRAW_TOOL (tool));
|
||||
pika_draw_tool_resume (PIKA_DRAW_TOOL (tool));
|
||||
}
|
||||
}
|
||||
|
||||
static PikaCanvasItem *
|
||||
pika_ink_tool_get_outline (PikaPaintTool *paint_tool,
|
||||
PikaDisplay *display,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
PikaInkOptions *options = PIKA_INK_TOOL_GET_OPTIONS (paint_tool);
|
||||
|
||||
pika_paint_tool_set_draw_circle (paint_tool, TRUE,
|
||||
options->size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pika_ink_tool_is_alpha_only (PikaPaintTool *paint_tool,
|
||||
PikaDrawable *drawable)
|
||||
{
|
||||
PikaPaintOptions *paint_options = PIKA_PAINT_TOOL_GET_OPTIONS (paint_tool);
|
||||
PikaContext *context = PIKA_CONTEXT (paint_options);
|
||||
PikaLayerMode paint_mode = pika_context_get_paint_mode (context);
|
||||
|
||||
return pika_layer_mode_is_alpha_only (paint_mode);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user