LibreOffice Module forms (master) 1
richtextvclcontrol.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
22#include <svl/itemset.hxx>
23#if OSL_DEBUG_LEVEL > 0
25 #include <sfx2/filedlghelper.hxx>
26 #include <tools/urlobj.hxx>
27 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
28#endif
29#include <editeng/editeng.hxx>
30#include <editeng/editview.hxx>
31#include <editeng/editids.hrc>
32#include <svx/svxids.hrc>
33#include <osl/diagnose.h>
34#include <vcl/event.hxx>
35
36namespace frm
37{
38
40 ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener )
41 :Control( _pParent, implInitStyle( _nStyle ) )
42 {
43 implInit( _pEngine, _pTextAttribListener, _pSelectionListener );
44 }
45
46 void RichTextControl::implInit( RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener )
47 {
48 m_pImpl.reset( new RichTextControlImpl( this, _pEngine, _pTextAttribListener, _pSelectionListener ) );
49 SetCompoundControl( true );
50 }
51
53 {
55 }
56
58 {
59 m_pImpl.reset();
61 }
62
63
65 {
66 return m_pImpl->getAttributeState( _nAttributeId );
67 }
68
69
70 void RichTextControl::executeAttribute( AttributeId _nAttributeId, const SfxPoolItem* _pArgument )
71 {
72 SfxItemSet aToApplyAttributes( getView().GetEmptyItemSet() );
73 if ( !m_pImpl->executeAttribute( getView().GetAttribs(), aToApplyAttributes, _nAttributeId, _pArgument, m_pImpl->getSelectedScriptType() ) )
74 {
75 OSL_FAIL( "RichTextControl::executeAttribute: cannot handle the given attribute!" );
76 return;
77 }
78
79 applyAttributes( aToApplyAttributes );
80 }
81
82
83 void RichTextControl::applyAttributes( const SfxItemSet& _rAttributesToApply )
84 {
85 // apply
86 if ( HasChildPathFocus() )
88
89 // TODO: guard?
90 bool bOldUpdateMode = getEngine().SetUpdateLayout( false );
91
92 getView().SetAttribs( _rAttributesToApply );
93
94 getEngine().SetUpdateLayout( bOldUpdateMode );
96
97 if ( HasChildPathFocus() )
99
100 m_pImpl->updateAllAttributes();
101 // TODO: maybe we should have a list of attributes which need to be updated
102 // (the handler for the just executed attribute should know)
103 }
104
105
107 {
108 m_pImpl->enableAttributeNotification( _nAttributeId, _pListener );
109 }
110
111
113 {
114 m_pImpl->disableAttributeNotification( _nAttributeId );
115 }
116
117
119 {
120 switch ( _nSlotId )
121 {
122 case SID_ATTR_PARA_ADJUST_LEFT:
123 case SID_ATTR_PARA_ADJUST_CENTER:
124 case SID_ATTR_PARA_ADJUST_RIGHT:
125 case SID_ATTR_PARA_ADJUST_BLOCK:
126 case SID_SET_SUPER_SCRIPT:
127 case SID_SET_SUB_SCRIPT:
128 case SID_ATTR_PARA_LINESPACE_10:
129 case SID_ATTR_PARA_LINESPACE_15:
130 case SID_ATTR_PARA_LINESPACE_20:
131 case SID_ATTR_PARA_LEFT_TO_RIGHT:
132 case SID_ATTR_PARA_RIGHT_TO_LEFT:
133 case SID_TEXTDIRECTION_TOP_TO_BOTTOM:
134 case SID_TEXTDIRECTION_LEFT_TO_RIGHT:
135 case SID_ATTR_CHAR_LATIN_FONT:
136 case SID_ATTR_CHAR_LATIN_FONTHEIGHT:
137 case SID_ATTR_CHAR_LATIN_LANGUAGE:
138 case SID_ATTR_CHAR_LATIN_POSTURE:
139 case SID_ATTR_CHAR_LATIN_WEIGHT:
140 return true;
141 }
142 return false;
143 }
144
145
147 {
148 m_pImpl->layoutWindow();
149 Invalidate();
150 }
151
152
154 {
155 m_pImpl->getViewport( RichTextControlImpl::GrantAccess() )->GrabFocus();
156 }
157
158
160 {
161 if ( !( nStyle & WB_NOTABSTOP ) )
162 nStyle |= WB_TABSTOP;
163 return nStyle;
164 }
165
166
168 {
169 if ( _nStateChange == StateChangedType::Style )
170 {
172 m_pImpl->notifyStyleChanged();
173 }
174 else if ( _nStateChange == StateChangedType::Zoom )
175 {
176 m_pImpl->notifyZoomChanged();
177 }
178 else if ( _nStateChange == StateChangedType::InitShow )
179 {
180 m_pImpl->notifyInitShow();
181 }
182 Control::StateChanged( _nStateChange );
183 }
184
185
187 {
188 if ( IsWindowOrChild( _rNEvt.GetWindow() ) )
189 {
190 if ( NotifyEventType::KEYINPUT == _rNEvt.GetType() )
191 {
192 const ::KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
193
194 sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
195 bool bShift = pKeyEvent->GetKeyCode().IsShift();
196 bool bCtrl = pKeyEvent->GetKeyCode().IsMod1();
197 bool bAlt = pKeyEvent->GetKeyCode().IsMod2();
198 if ( ( KEY_TAB == nCode ) && bCtrl && !bAlt )
199 {
200 // Ctrl-Tab is used to step out of the control
201 // -> build a new key event without the Ctrl-key, and let the very base class handle it
202 vcl::KeyCode aNewCode( KEY_TAB, bShift, false, false, false );
203 ::KeyEvent aNewEvent( pKeyEvent->GetCharCode(), aNewCode );
204 Control::KeyInput( aNewEvent );
205 return true; // handled
206 }
207
208#if OSL_DEBUG_LEVEL > 0
209 if ( ( ( KEY_F12 == nCode )
210 || ( KEY_F11 == nCode )
211 )
212 && bCtrl
213 && bAlt
214 )
215 {
216 bool bLoad = KEY_F11 == nCode;
217 static struct
218 {
219 const char* pDescription;
220 const char* pExtension;
221 EETextFormat eFormat;
222 } const aExportFormats[] =
223 {
224 { "OASIS OpenDocument (*.xml)", "*.xml", EETextFormat::Xml },
225 { "HyperText Markup Language (*.html)", "*.html", EETextFormat::Html },
226 { "Rich Text format (*.rtf)", "*.rtf", EETextFormat::Rtf },
227 { "Text (*.txt)", "*.txt", EETextFormat::Text }
228 };
229
230 ::sfx2::FileDialogHelper aFP( bLoad ? css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE : css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, FileDialogFlags::NONE, GetFrameWeld() );
231
232 for (auto & aExportFormat : aExportFormats)
233 {
234 aFP.AddFilter(
235 OUString::createFromAscii( aExportFormat.pDescription ),
236 OUString::createFromAscii( aExportFormat.pExtension ) );
237 }
238 ErrCode nResult = aFP.Execute();
239 if ( nResult == ERRCODE_NONE )
240 {
241 OUString sFileName = aFP.GetPath();
242 std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream(
243 sFileName, ( bLoad ? StreamMode::READ : StreamMode::WRITE | StreamMode::TRUNC ) | StreamMode::SHARE_DENYALL
244 );
245 if ( pStream )
246 {
247 EETextFormat eFormat = EETextFormat::Xml;
248 OUString sFilter = aFP.GetCurrentFilter();
249 for (auto & aExportFormat : aExportFormats)
250 {
251 if ( sFilter.equalsAscii( aExportFormat.pDescription ) )
252 {
253 eFormat = aExportFormat.eFormat;
254 break;
255 }
256 }
257 if ( bLoad )
258 {
259 INetURLObject aURL( sFileName );
260 aURL.removeSegment();
261 getEngine().Read( *pStream, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), eFormat );
262 }
263 else
264 {
265 getEngine().Write( *pStream, eFormat );
266 }
267 }
268 }
269 return true; // handled
270 }
271#endif
272 }
273 }
274 return Control::PreNotify( _rNEvt );
275 }
276
277
279 {
280 bool bDone = false;
281 if ( _rNEvt.GetType() == NotifyEventType::COMMAND )
282 {
283 const CommandEvent& rEvent = *_rNEvt.GetCommandEvent();
284 bDone = m_pImpl->HandleCommand( rEvent );
285 }
286 return bDone || Control::EventNotify(_rNEvt);
287 }
288
289 void RichTextControl::Draw( OutputDevice* _pDev, const Point& _rPos, SystemTextColorFlags /*_nFlags*/ )
290 {
291 m_pImpl->Draw( _pDev, _rPos, _pDev->PixelToLogic(GetSizePixel()) );
292 }
293
295 {
296 return *m_pImpl->getView( RichTextControlImpl::GrantAccess() );
297 }
298
299
301 {
302 return *m_pImpl->getView( RichTextControlImpl::GrantAccess() );
303 }
304
305
307 {
308 return *m_pImpl->getEngine( RichTextControlImpl::GrantAccess() );
309 }
310
311
312 void RichTextControl::SetReadOnly( bool _bReadOnly )
313 {
314 m_pImpl->SetReadOnly( _bReadOnly );
315 }
316
317
319 {
320 return m_pImpl->IsReadOnly();
321 }
322
323
325 {
326 m_pImpl->SetBackgroundColor( );
327 }
328
329
331 {
332 m_pImpl->SetBackgroundColor( _rColor );
333 }
334
335
337 {
338 m_pImpl->SetHideInactiveSelection( _bHide );
339 }
340
341
343 {
344 return m_pImpl->GetHideInactiveSelection( );
345 }
346
347
348} // namespace frm
349
350
351/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SystemTextColorFlags
virtual bool EventNotify(NotifyEvent &rNEvt) override
virtual void StateChanged(StateChangedType nStateChange) override
virtual void dispose() override
bool SetUpdateLayout(bool bUpdate, bool bRestoring=false)
ErrCode Read(SvStream &rInput, const OUString &rBaseURL, EETextFormat, SvKeyValueIterator *pHTTPHeaderAttrs=nullptr)
void Write(SvStream &rOutput, EETextFormat)
void HideCursor(bool bDeactivate=false)
void ShowCursor(bool bGotoCursor=true, bool bForceVisCursor=true, bool bActivate=false)
void Invalidate()
void SetAttribs(const SfxItemSet &rSet)
const vcl::KeyCode & GetKeyCode() const
const KeyEvent * GetKeyEvent() const
vcl::Window * GetWindow() const
const CommandEvent * GetCommandEvent() const
NotifyEventType GetType() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
virtual void GetFocus() override
virtual void Draw(OutputDevice *_pDev, const Point &_rPos, SystemTextColorFlags _nFlags) override
RichTextControl(RichTextEngine *_pEngine, vcl::Window *_pParent, WinBits _nStyle, ITextAttributeListener *_pTextAttribListener, ITextSelectionListener *_pSelectionListener)
virtual ~RichTextControl() override
virtual void StateChanged(StateChangedType nStateChange) override
void enableAttributeNotification(AttributeId _nAttributeId, ITextAttributeListener *_pListener)
std::unique_ptr< RichTextControlImpl > m_pImpl
void SetHideInactiveSelection(bool _bHide)
void applyAttributes(const SfxItemSet &_rAttributesToApply)
const EditView & getView() const
virtual void executeAttribute(AttributeId _nAttributeId, const SfxPoolItem *_pArgument) override
virtual void Resize() override
EditEngine & getEngine() const
void disableAttributeNotification(AttributeId _nAttributeId)
disables the change notifications for a particular attribute
virtual bool EventNotify(NotifyEvent &_rNEvt) override
void SetReadOnly(bool _bReadOnly)
virtual bool PreNotify(NotifyEvent &_rNEvt) override
static bool isMappableSlot(SfxSlotId _nSlotId)
determines whether a given slot can be mapped to an aspect of an attribute of the EditEngine
static WinBits implInitStyle(WinBits nStyle)
bool GetHideInactiveSelection() const
void implInit(RichTextEngine *_pEngine, ITextAttributeListener *_pTextAttribListener, ITextSelectionListener *_pSelectionListener)
virtual void dispose() override
virtual AttributeState getState(AttributeId _nAttributeId) const override
OUString GetPath() const
void AddFilter(const OUString &rFilterName, const OUString &rExtension)
OUString GetCurrentFilter() const
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
sal_uInt16 GetCode() const
void SetStyle(WinBits nStyle)
bool HasChildPathFocus(bool bSystemWindow=false) const
WinBits GetStyle() const
virtual void KeyInput(const KeyEvent &rKEvt)
virtual bool PreNotify(NotifyEvent &rNEvt)
virtual Size GetSizePixel() const
bool IsWindowOrChild(const vcl::Window *pWindow, bool bSystemWindow=false) const
void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
weld::Window * GetFrameWeld() const
void SetCompoundControl(bool bCompound)
URL aURL
EETextFormat
#define ERRCODE_NONE
constexpr sal_uInt16 KEY_TAB
constexpr sal_uInt16 KEY_F12
constexpr sal_uInt16 KEY_F11
ListBox is a bit confusing / different from other form components, so here are a few notes:
Definition: BaseListBox.hxx:25
sal_uInt16 SfxSlotId
a SFX slot id
sal_Int32 AttributeId
the id of an attribute
StateChangedType
sal_Int64 WinBits
WinBits const WB_NOTABSTOP
WinBits const WB_TABSTOP