1 | /* |
2 | * Copyright (C) 2015 Igalia S.L. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Library General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Library General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Library General Public License |
15 | * along with this library; see the file COPYING.LIB. If not, write to |
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "config.h" |
21 | #include "WebKitEditorState.h" |
22 | |
23 | #include "EditorState.h" |
24 | #include "WebKitEditorStatePrivate.h" |
25 | #include "WebPageProxy.h" |
26 | #include <glib/gi18n-lib.h> |
27 | #include <wtf/glib/WTFGType.h> |
28 | |
29 | using namespace WebKit; |
30 | |
31 | /** |
32 | * SECTION: WebKitEditorState |
33 | * @Short_description: Web editor state |
34 | * @Title: WebKitEditorState |
35 | * @See_also: #WebKitWebView |
36 | * |
37 | * WebKitEditorState represents the state of a #WebKitWebView editor. |
38 | * Use webkit_web_view_get_editor_state() to get the WebKitEditorState |
39 | * of a #WebKitWebView. |
40 | * |
41 | * Since: 2.10 |
42 | */ |
43 | |
44 | enum { |
45 | PROP_0, |
46 | |
47 | PROP_TYPING_ATTRIBUTES |
48 | }; |
49 | |
50 | struct _WebKitEditorStatePrivate { |
51 | WebPageProxy* page; |
52 | unsigned typingAttributes; |
53 | unsigned isCutAvailable : 1; |
54 | unsigned isCopyAvailable : 1; |
55 | unsigned isPasteAvailable : 1; |
56 | unsigned isUndoAvailable : 1; |
57 | unsigned isRedoAvailable : 1; |
58 | }; |
59 | |
60 | WEBKIT_DEFINE_TYPE(WebKitEditorState, webkit_editor_state, G_TYPE_OBJECT) |
61 | |
62 | static void webkitEditorStateGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec) |
63 | { |
64 | WebKitEditorState* editorState = WEBKIT_EDITOR_STATE(object); |
65 | |
66 | switch (propId) { |
67 | case PROP_TYPING_ATTRIBUTES: |
68 | g_value_set_uint(value, webkit_editor_state_get_typing_attributes(editorState)); |
69 | break; |
70 | default: |
71 | G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec); |
72 | } |
73 | } |
74 | |
75 | static void webkit_editor_state_class_init(WebKitEditorStateClass* editorStateClass) |
76 | { |
77 | GObjectClass* objectClass = G_OBJECT_CLASS(editorStateClass); |
78 | objectClass->get_property = webkitEditorStateGetProperty; |
79 | |
80 | /** |
81 | * WebKitEditorState:typing-attributes: |
82 | * |
83 | * Bitmask of #WebKitEditorTypingAttributes flags. |
84 | * See webkit_editor_state_get_typing_attributes() for more information. |
85 | * |
86 | * Since: 2.10 |
87 | */ |
88 | g_object_class_install_property( |
89 | objectClass, |
90 | PROP_TYPING_ATTRIBUTES, |
91 | g_param_spec_uint( |
92 | "typing-attributes" , |
93 | _("Typing Attributes" ), |
94 | _("Flags with the typing attributes" ), |
95 | 0, G_MAXUINT, 0, |
96 | WEBKIT_PARAM_READABLE)); |
97 | } |
98 | |
99 | static void webkitEditorStateSetTypingAttributes(WebKitEditorState* editorState, unsigned typingAttributes) |
100 | { |
101 | if (typingAttributes == editorState->priv->typingAttributes) |
102 | return; |
103 | |
104 | editorState->priv->typingAttributes = typingAttributes; |
105 | g_object_notify(G_OBJECT(editorState), "typing-attributes" ); |
106 | } |
107 | |
108 | WebKitEditorState* webkitEditorStateCreate(WebPageProxy& page) |
109 | { |
110 | WebKitEditorState* editorState = WEBKIT_EDITOR_STATE(g_object_new(WEBKIT_TYPE_EDITOR_STATE, nullptr)); |
111 | editorState->priv->page = &page; |
112 | webkitEditorStateChanged(editorState, page.editorState()); |
113 | return editorState; |
114 | } |
115 | |
116 | void webkitEditorStateChanged(WebKitEditorState* editorState, const EditorState& newState) |
117 | { |
118 | if (newState.isMissingPostLayoutData) |
119 | return; |
120 | |
121 | unsigned typingAttributes = WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE; |
122 | const auto& postLayoutData = newState.postLayoutData(); |
123 | if (postLayoutData.typingAttributes & AttributeBold) |
124 | typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD; |
125 | if (postLayoutData.typingAttributes & AttributeItalics) |
126 | typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC; |
127 | if (postLayoutData.typingAttributes & AttributeUnderline) |
128 | typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE; |
129 | if (postLayoutData.typingAttributes & AttributeStrikeThrough) |
130 | typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH; |
131 | |
132 | webkitEditorStateSetTypingAttributes(editorState, typingAttributes); |
133 | |
134 | editorState->priv->isCutAvailable = postLayoutData.canCut; |
135 | editorState->priv->isCopyAvailable = postLayoutData.canCopy; |
136 | editorState->priv->isPasteAvailable = postLayoutData.canPaste; |
137 | |
138 | editorState->priv->isUndoAvailable = editorState->priv->page->canUndo(); |
139 | editorState->priv->isRedoAvailable = editorState->priv->page->canRedo(); |
140 | } |
141 | |
142 | /** |
143 | * webkit_editor_state_get_typing_attributes: |
144 | * @editor_state: a #WebKitEditorState |
145 | * |
146 | * Gets the typing attributes at the current cursor position. |
147 | * If there is a selection, this returns the typing attributes |
148 | * of the selected text. Note that in case of a selection, |
149 | * typing attributes are considered active only when they are |
150 | * present throughout the selection. |
151 | * |
152 | * Returns: a bitmask of #WebKitEditorTypingAttributes flags |
153 | * |
154 | * Since: 2.10 |
155 | */ |
156 | guint webkit_editor_state_get_typing_attributes(WebKitEditorState* editorState) |
157 | { |
158 | g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE); |
159 | |
160 | return editorState->priv->typingAttributes; |
161 | } |
162 | |
163 | /** |
164 | * webkit_editor_state_is_cut_available: |
165 | * @editor_state: a #WebKitEditorState |
166 | * |
167 | * Gets whether a cut command can be issued. |
168 | * |
169 | * Returns: %TRUE if cut is currently available |
170 | * |
171 | * Since: 2.20 |
172 | */ |
173 | gboolean webkit_editor_state_is_cut_available(WebKitEditorState* editorState) |
174 | { |
175 | g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE); |
176 | |
177 | return editorState->priv->isCutAvailable; |
178 | } |
179 | |
180 | /** |
181 | * webkit_editor_state_is_copy_available: |
182 | * @editor_state: a #WebKitEditorState |
183 | * |
184 | * Gets whether a copy command can be issued. |
185 | * |
186 | * Returns: %TRUE if copy is currently available |
187 | * |
188 | * Since: 2.20 |
189 | */ |
190 | gboolean webkit_editor_state_is_copy_available(WebKitEditorState* editorState) |
191 | { |
192 | g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE); |
193 | |
194 | return editorState->priv->isCopyAvailable; |
195 | } |
196 | |
197 | /** |
198 | * webkit_editor_state_is_paste_available: |
199 | * @editor_state: a #WebKitEditorState |
200 | * |
201 | * Gets whether a paste command can be issued. |
202 | * |
203 | * Returns: %TRUE if paste is currently available |
204 | * |
205 | * Since: 2.20 |
206 | */ |
207 | gboolean webkit_editor_state_is_paste_available(WebKitEditorState* editorState) |
208 | { |
209 | g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE); |
210 | |
211 | return editorState->priv->isPasteAvailable; |
212 | } |
213 | |
214 | /** |
215 | * webkit_editor_state_is_undo_available: |
216 | * @editor_state: a #WebKitEditorState |
217 | * |
218 | * Gets whether an undo command can be issued. |
219 | * |
220 | * Returns: %TRUE if undo is currently available |
221 | * |
222 | * Since: 2.20 |
223 | */ |
224 | gboolean webkit_editor_state_is_undo_available(WebKitEditorState* editorState) |
225 | { |
226 | g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE); |
227 | |
228 | return editorState->priv->isUndoAvailable; |
229 | } |
230 | |
231 | /** |
232 | * webkit_editor_state_is_redo_available: |
233 | * @editor_state: a #WebKitEditorState |
234 | * |
235 | * Gets whether a redo command can be issued. |
236 | * |
237 | * Returns: %TRUE if redo is currently available |
238 | * |
239 | * Since: 2.20 |
240 | */ |
241 | gboolean webkit_editor_state_is_redo_available(WebKitEditorState* editorState) |
242 | { |
243 | g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE); |
244 | |
245 | return editorState->priv->isRedoAvailable; |
246 | } |
247 | |