[iOS] ASSERTION FAILURE: !isMissingPostLayoutData in WebKit::EditorState::postLayoutD...
[WebKit-https.git] / Source / WebKit / UIProcess / API / glib / WebKitEditorState.cpp
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     editorState->priv->typingAttributes = WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE;
113     webkitEditorStateChanged(editorState, page.editorState());
114     return editorState;
115 }
116
117 void webkitEditorStateChanged(WebKitEditorState* editorState, const EditorState& newState)
118 {
119     if (newState.isMissingPostLayoutData)
120         return;
121
122     unsigned typingAttributes = WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE;
123     const auto& postLayoutData = newState.postLayoutData();
124     if (postLayoutData.typingAttributes & AttributeBold)
125         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD;
126     if (postLayoutData.typingAttributes & AttributeItalics)
127         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC;
128     if (postLayoutData.typingAttributes & AttributeUnderline)
129         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE;
130     if (postLayoutData.typingAttributes & AttributeStrikeThrough)
131         typingAttributes |= WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH;
132
133     webkitEditorStateSetTypingAttributes(editorState, typingAttributes);
134
135     editorState->priv->isCutAvailable = postLayoutData.canCut;
136     editorState->priv->isCopyAvailable = postLayoutData.canCopy;
137     editorState->priv->isPasteAvailable = postLayoutData.canPaste;
138
139     editorState->priv->isUndoAvailable = editorState->priv->page->canUndo();
140     editorState->priv->isRedoAvailable = editorState->priv->page->canRedo();
141 }
142
143 /**
144  * webkit_editor_state_get_typing_attributes:
145  * @editor_state: a #WebKitEditorState
146  *
147  * Gets the typing attributes at the current cursor position.
148  * If there is a selection, this returns the typing attributes
149  * of the selected text. Note that in case of a selection,
150  * typing attributes are considered active only when they are
151  * present throughout the selection.
152  *
153  * Returns: a bitmask of #WebKitEditorTypingAttributes flags
154  *
155  * Since: 2.10
156  */
157 guint webkit_editor_state_get_typing_attributes(WebKitEditorState* editorState)
158 {
159     g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
160
161     return editorState->priv->typingAttributes;
162 }
163
164 /**
165  * webkit_editor_state_is_cut_available:
166  * @editor_state: a #WebKitEditorState
167  *
168  * Gets whether a cut command can be issued.
169  *
170  * Returns: %TRUE if cut is currently available
171  *
172  * Since: 2.20
173  */
174 gboolean webkit_editor_state_is_cut_available(WebKitEditorState* editorState)
175 {
176     g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
177
178     return editorState->priv->isCutAvailable;
179 }
180
181 /**
182  * webkit_editor_state_is_copy_available:
183  * @editor_state: a #WebKitEditorState
184  *
185  * Gets whether a copy command can be issued.
186  *
187  * Returns: %TRUE if copy is currently available
188  *
189  * Since: 2.20
190  */
191 gboolean webkit_editor_state_is_copy_available(WebKitEditorState* editorState)
192 {
193     g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
194
195     return editorState->priv->isCopyAvailable;
196 }
197
198 /**
199  * webkit_editor_state_is_paste_available:
200  * @editor_state: a #WebKitEditorState
201  *
202  * Gets whether a paste command can be issued.
203  *
204  * Returns: %TRUE if paste is currently available
205  *
206  * Since: 2.20
207  */
208 gboolean webkit_editor_state_is_paste_available(WebKitEditorState* editorState)
209 {
210     g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
211
212     return editorState->priv->isPasteAvailable;
213 }
214
215 /**
216  * webkit_editor_state_is_undo_available:
217  * @editor_state: a #WebKitEditorState
218  *
219  * Gets whether an undo command can be issued.
220  *
221  * Returns: %TRUE if undo is currently available
222  *
223  * Since: 2.20
224  */
225 gboolean webkit_editor_state_is_undo_available(WebKitEditorState* editorState)
226 {
227     g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
228
229     return editorState->priv->isUndoAvailable;
230 }
231
232 /**
233  * webkit_editor_state_is_redo_available:
234  * @editor_state: a #WebKitEditorState
235  *
236  * Gets whether a redo command can be issued.
237  *
238  * Returns: %TRUE if redo is currently available
239  *
240  * Since: 2.20
241  */
242 gboolean webkit_editor_state_is_redo_available(WebKitEditorState* editorState)
243 {
244     g_return_val_if_fail(WEBKIT_IS_EDITOR_STATE(editorState), FALSE);
245
246     return editorState->priv->isRedoAvailable;
247 }