1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_forms.hxx" 26 #include "richtextvclcontrol.hxx" 27 #include "richtextimplcontrol.hxx" 28 #include <svl/itempool.hxx> 29 #include <svl/itemset.hxx> 30 #include <svl/languageoptions.hxx> 31 #if OSL_DEBUG_LEVEL > 0 32 #ifndef _TOOLS_TEMPFILE_HXX 33 #include <tools/tempfile.hxx> 34 #endif 35 #ifndef _UNTOOLS_UCBSTREAMHELPER_HXX 36 #include <unotools/ucbstreamhelper.hxx> 37 #endif 38 #ifndef _SV_MSGBOX_HXX 39 #include <vcl/msgbox.hxx> 40 #endif 41 #ifndef _FILEDLGHELPER_HXX 42 #include <sfx2/filedlghelper.hxx> 43 #endif 44 #ifndef _URLOBJ_HXX 45 #include <tools/urlobj.hxx> 46 #endif 47 #include "com/sun/star/ui/dialogs/TemplateDescription.hpp" 48 #endif 49 #include <editeng/scripttypeitem.hxx> 50 #include <editeng/editeng.hxx> 51 #include <editeng/editview.hxx> 52 #include <editeng/eeitem.hxx> 53 #include <editeng/fontitem.hxx> 54 #include <editeng/fhgtitem.hxx> 55 #include <editeng/editids.hrc> 56 #include <svx/svxids.hrc> 57 #include <memory> 58 59 //........................................................................ 60 namespace frm 61 { 62 //........................................................................ 63 64 using namespace ::com::sun::star::awt; 65 66 //==================================================================== 67 //= RichTextControl 68 //==================================================================== 69 //-------------------------------------------------------------------- RichTextControl(RichTextEngine * _pEngine,Window * _pParent,WinBits _nStyle,ITextAttributeListener * _pTextAttribListener,ITextSelectionListener * _pSelectionListener)70 RichTextControl::RichTextControl( RichTextEngine* _pEngine, Window* _pParent, WinBits _nStyle, 71 ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener ) 72 :Control( _pParent, implInitStyle( _nStyle ) ) 73 ,m_pImpl( NULL ) 74 { 75 implInit( _pEngine, _pTextAttribListener, _pSelectionListener ); 76 } 77 78 //-------------------------------------------------------------------- implInit(RichTextEngine * _pEngine,ITextAttributeListener * _pTextAttribListener,ITextSelectionListener * _pSelectionListener)79 void RichTextControl::implInit( RichTextEngine* _pEngine, ITextAttributeListener* _pTextAttribListener, ITextSelectionListener* _pSelectionListener ) 80 { 81 m_pImpl = new RichTextControlImpl( this, _pEngine, _pTextAttribListener, _pSelectionListener ); 82 SetCompoundControl( sal_True ); 83 } 84 85 //-------------------------------------------------------------------- ~RichTextControl()86 RichTextControl::~RichTextControl( ) 87 { 88 delete m_pImpl; 89 } 90 91 //-------------------------------------------------------------------- getState(AttributeId _nAttributeId) const92 AttributeState RichTextControl::getState( AttributeId _nAttributeId ) const 93 { 94 return m_pImpl->getAttributeState( _nAttributeId ); 95 } 96 97 //-------------------------------------------------------------------- executeAttribute(AttributeId _nAttributeId,const SfxPoolItem * _pArgument)98 void RichTextControl::executeAttribute( AttributeId _nAttributeId, const SfxPoolItem* _pArgument ) 99 { 100 SfxItemSet aToApplyAttributes( getView().GetEmptyItemSet() ); 101 if ( !m_pImpl->executeAttribute( getView().GetAttribs(), aToApplyAttributes, _nAttributeId, _pArgument, m_pImpl->getSelectedScriptType() ) ) 102 { 103 OSL_ENSURE( sal_False, "RichTextControl::executeAttribute: cannot handle the given attribute!" ); 104 return; 105 } 106 107 applyAttributes( aToApplyAttributes ); 108 } 109 110 //-------------------------------------------------------------------- applyAttributes(const SfxItemSet & _rAttributesToApply)111 void RichTextControl::applyAttributes( const SfxItemSet& _rAttributesToApply ) 112 { 113 // apply 114 if ( HasChildPathFocus() ) 115 getView().HideCursor(); 116 117 sal_Bool bOldUpdateMode = getEngine().GetUpdateMode(); // TODO: guard? 118 getEngine().SetUpdateMode( sal_False ); 119 120 getView().SetAttribs( _rAttributesToApply ); 121 122 getEngine().SetUpdateMode( bOldUpdateMode ); 123 getView().Invalidate(); 124 125 if ( HasChildPathFocus() ) 126 getView().ShowCursor(); 127 128 m_pImpl->updateAllAttributes(); 129 // TODO: maybe we should have a list of attributes which need to be updated 130 // (the handler for the just executed attribute should know) 131 } 132 133 //-------------------------------------------------------------------- enableAttributeNotification(AttributeId _nAttributeId,ITextAttributeListener * _pListener)134 void RichTextControl::enableAttributeNotification( AttributeId _nAttributeId, ITextAttributeListener* _pListener ) 135 { 136 m_pImpl->enableAttributeNotification( _nAttributeId, _pListener ); 137 } 138 139 //-------------------------------------------------------------------- disableAttributeNotification(AttributeId _nAttributeId)140 void RichTextControl::disableAttributeNotification( AttributeId _nAttributeId ) 141 { 142 m_pImpl->disableAttributeNotification( _nAttributeId ); 143 } 144 145 //-------------------------------------------------------------------- isMappableSlot(SfxSlotId _nSlotId)146 bool RichTextControl::isMappableSlot( SfxSlotId _nSlotId ) 147 { 148 switch ( _nSlotId ) 149 { 150 case SID_ATTR_PARA_ADJUST_LEFT: 151 case SID_ATTR_PARA_ADJUST_CENTER: 152 case SID_ATTR_PARA_ADJUST_RIGHT: 153 case SID_ATTR_PARA_ADJUST_BLOCK: 154 case SID_SET_SUPER_SCRIPT: 155 case SID_SET_SUB_SCRIPT: 156 case SID_ATTR_PARA_LINESPACE_10: 157 case SID_ATTR_PARA_LINESPACE_15: 158 case SID_ATTR_PARA_LINESPACE_20: 159 case SID_ATTR_PARA_LEFT_TO_RIGHT: 160 case SID_ATTR_PARA_RIGHT_TO_LEFT: 161 case SID_TEXTDIRECTION_TOP_TO_BOTTOM: 162 case SID_TEXTDIRECTION_LEFT_TO_RIGHT: 163 case SID_ATTR_CHAR_LATIN_FONT: 164 case SID_ATTR_CHAR_LATIN_FONTHEIGHT: 165 case SID_ATTR_CHAR_LATIN_LANGUAGE: 166 case SID_ATTR_CHAR_LATIN_POSTURE: 167 case SID_ATTR_CHAR_LATIN_WEIGHT: 168 return true; 169 } 170 return false; 171 } 172 173 //-------------------------------------------------------------------- Resize()174 void RichTextControl::Resize() 175 { 176 m_pImpl->layoutWindow(); 177 Invalidate(); 178 } 179 180 //-------------------------------------------------------------------- GetFocus()181 void RichTextControl::GetFocus() 182 { 183 getViewport().GrabFocus(); 184 } 185 186 //-------------------------------------------------------------------- implInitStyle(WinBits nStyle)187 WinBits RichTextControl::implInitStyle( WinBits nStyle ) 188 { 189 if ( !( nStyle & WB_NOTABSTOP ) ) 190 nStyle |= WB_TABSTOP; 191 return nStyle; 192 } 193 194 //-------------------------------------------------------------------- StateChanged(StateChangedType _nStateChange)195 void RichTextControl::StateChanged( StateChangedType _nStateChange ) 196 { 197 if ( _nStateChange == STATE_CHANGE_STYLE ) 198 { 199 SetStyle( implInitStyle( GetStyle() ) ); 200 m_pImpl->notifyStyleChanged(); 201 } 202 else if ( _nStateChange == STATE_CHANGE_ZOOM ) 203 { 204 m_pImpl->notifyZoomChanged(); 205 } 206 else if ( _nStateChange == STATE_CHANGE_INITSHOW ) 207 { 208 m_pImpl->notifyInitShow(); 209 } 210 Control::StateChanged( _nStateChange ); 211 } 212 213 //-------------------------------------------------------------------- PreNotify(NotifyEvent & _rNEvt)214 long RichTextControl::PreNotify( NotifyEvent& _rNEvt ) 215 { 216 if ( IsWindowOrChild( _rNEvt.GetWindow() ) ) 217 { 218 if ( EVENT_KEYINPUT == _rNEvt.GetType() ) 219 { 220 const ::KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent(); 221 222 sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode(); 223 sal_Bool bShift = pKeyEvent->GetKeyCode().IsShift(); 224 sal_Bool bCtrl = pKeyEvent->GetKeyCode().IsMod1(); 225 sal_Bool bAlt = pKeyEvent->GetKeyCode().IsMod2(); 226 if ( ( KEY_TAB == nCode ) && bCtrl && !bAlt ) 227 { 228 // Ctrl-Tab is used to step out of the control 229 // -> build a new key event without the Ctrl-key, and let the very base class handle it 230 KeyCode aNewCode( KEY_TAB, bShift, sal_False, sal_False, sal_False ); 231 ::KeyEvent aNewEvent( pKeyEvent->GetCharCode(), aNewCode ); 232 Control::KeyInput( aNewEvent ); 233 return 1; // handled 234 } 235 236 #if OSL_DEBUG_LEVEL > 0 237 if ( ( ( KEY_F12 == nCode ) 238 || ( KEY_F11 == nCode ) 239 ) 240 && bCtrl 241 && bAlt 242 ) 243 { 244 bool bLoad = KEY_F11 == nCode; 245 struct 246 { 247 const sal_Char* pDescription; 248 const sal_Char* pExtension; 249 EETextFormat eFormat; 250 } aExportFormats[] = 251 { 252 { "OASIS OpenDocument (*.xml)", "*.xml", EE_FORMAT_XML }, 253 { "HyperText Markup Language (*.html)", "*.html", EE_FORMAT_HTML }, 254 { "Rich Text format (*.rtf)", "*.rtf", EE_FORMAT_RTF }, 255 { "Text (*.txt)", "*.txt", EE_FORMAT_TEXT } 256 }; 257 258 ::sfx2::FileDialogHelper aFP( bLoad ? com::sun::star::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE : com::sun::star::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION, 0, this ); 259 260 for ( size_t i = 0; i < sizeof( aExportFormats ) / sizeof( aExportFormats[ 0 ] ); ++i ) 261 { 262 aFP.AddFilter( 263 String::CreateFromAscii( aExportFormats[i].pDescription ), 264 String::CreateFromAscii( aExportFormats[i].pExtension ) ); 265 } 266 ErrCode nResult = aFP.Execute(); 267 if ( nResult == 0 ) 268 { 269 String sFileName = aFP.GetPath(); 270 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( 271 sFileName, ( bLoad ? STREAM_READ : STREAM_WRITE | STREAM_TRUNC ) | STREAM_SHARE_DENYALL 272 ); 273 if ( pStream ) 274 { 275 EETextFormat eFormat = EE_FORMAT_XML; 276 String sFilter = aFP.GetCurrentFilter(); 277 for ( size_t i = 0; i < sizeof( aExportFormats ) / sizeof( aExportFormats[ 0 ] ); ++i ) 278 { 279 if ( sFilter.EqualsAscii( aExportFormats[i].pDescription ) ) 280 { 281 eFormat = aExportFormats[i].eFormat; 282 break; 283 } 284 } 285 if ( bLoad ) 286 { 287 INetURLObject aURL( sFileName ); 288 aURL.removeSegment(); 289 getEngine().Read( *pStream, aURL.GetMainURL( INetURLObject::NO_DECODE ), eFormat ); 290 } 291 else 292 { 293 getEngine().Write( *pStream, eFormat ); 294 } 295 } 296 DELETEZ( pStream ); 297 } 298 return 1; // handled 299 } 300 #endif 301 } 302 } 303 return Control::PreNotify( _rNEvt ); 304 } 305 306 //-------------------------------------------------------------------- Notify(NotifyEvent & _rNEvt)307 long RichTextControl::Notify( NotifyEvent& _rNEvt ) 308 { 309 long nDone = 0; 310 if ( _rNEvt.GetType() == EVENT_COMMAND ) 311 { 312 const CommandEvent& rEvent = *_rNEvt.GetCommandEvent(); 313 nDone = m_pImpl->HandleCommand( rEvent ); 314 } 315 return nDone ? nDone : Control::Notify( _rNEvt ); 316 } 317 318 //-------------------------------------------------------------------- Draw(OutputDevice * _pDev,const Point & _rPos,const Size & _rSize,sal_uLong _nFlags)319 void RichTextControl::Draw( OutputDevice* _pDev, const Point& _rPos, const Size& _rSize, sal_uLong _nFlags ) 320 { 321 m_pImpl->Draw( _pDev, _rPos, _rSize, _nFlags ); 322 } 323 324 //-------------------------------------------------------------------- getView()325 EditView& RichTextControl::getView() 326 { 327 return *m_pImpl->getView( RichTextControlImpl::GrantAccess() ); 328 } 329 330 //-------------------------------------------------------------------- getView() const331 const EditView& RichTextControl::getView() const 332 { 333 return *m_pImpl->getView( RichTextControlImpl::GrantAccess() ); 334 } 335 336 //-------------------------------------------------------------------- getEngine() const337 EditEngine& RichTextControl::getEngine() const 338 { 339 return *m_pImpl->getEngine( RichTextControlImpl::GrantAccess() ); 340 } 341 342 //-------------------------------------------------------------------- getViewport() const343 Window& RichTextControl::getViewport() const 344 { 345 return *m_pImpl->getViewport( RichTextControlImpl::GrantAccess() ); 346 } 347 348 //-------------------------------------------------------------------- SetReadOnly(bool _bReadOnly)349 void RichTextControl::SetReadOnly( bool _bReadOnly ) 350 { 351 m_pImpl->SetReadOnly( _bReadOnly ); 352 } 353 354 //-------------------------------------------------------------------- IsReadOnly() const355 bool RichTextControl::IsReadOnly() const 356 { 357 return m_pImpl->IsReadOnly(); 358 } 359 360 //-------------------------------------------------------------------- SetBackgroundColor()361 void RichTextControl::SetBackgroundColor( ) 362 { 363 m_pImpl->SetBackgroundColor( ); 364 } 365 366 //-------------------------------------------------------------------- SetBackgroundColor(const Color & _rColor)367 void RichTextControl::SetBackgroundColor( const Color& _rColor ) 368 { 369 m_pImpl->SetBackgroundColor( _rColor ); 370 } 371 372 //-------------------------------------------------------------------- SetHideInactiveSelection(bool _bHide)373 void RichTextControl::SetHideInactiveSelection( bool _bHide ) 374 { 375 m_pImpl->SetHideInactiveSelection( _bHide ); 376 } 377 378 //-------------------------------------------------------------------- GetHideInactiveSelection() const379 bool RichTextControl::GetHideInactiveSelection() const 380 { 381 return m_pImpl->GetHideInactiveSelection( ); 382 } 383 384 //........................................................................ 385 } // namespace frm 386 //........................................................................ 387 388 389