android: Update app icon to new startcenter icon
[LibreOffice.git] / dbaccess / source / ui / control / sqledit.cxx
blob5997e5b80e1782de397f8f6d9f9f0489aadb59c7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <cassert>
24 #include <com/sun/star/beans/XMultiPropertySet.hpp>
25 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
26 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
27 #include <officecfg/Office/Common.hxx>
28 #include <editeng/eeitem.hxx>
29 #include <editeng/colritem.hxx>
30 #include <editeng/fhgtitem.hxx>
31 #include <editeng/fontitem.hxx>
32 #include <editeng/wghtitem.hxx>
33 #include <sqledit.hxx>
34 #include <cppuhelper/implbase.hxx>
35 #include <i18nlangtag/languagetag.hxx>
36 #include <svl/itempool.hxx>
37 #include <svl/itemset.hxx>
38 #include <vcl/commandevent.hxx>
39 #include <vcl/event.hxx>
40 #include <vcl/settings.hxx>
41 #include <vcl/specialchars.hxx>
42 #include <vcl/svapp.hxx>
44 using namespace dbaui;
46 class SQLEditView::ChangesListener:
47 public cppu::WeakImplHelper< css::beans::XPropertiesChangeListener >
49 public:
50 explicit ChangesListener(SQLEditView& editor): editor_(editor) {}
52 private:
53 virtual ~ChangesListener() override {}
55 virtual void SAL_CALL disposing(css::lang::EventObject const &) override
57 std::unique_lock g(editor_.m_mutex);
58 editor_.m_notifier.clear();
61 virtual void SAL_CALL propertiesChange(
62 css::uno::Sequence< css::beans::PropertyChangeEvent > const &) override
64 SolarMutexGuard g;
65 editor_.ImplSetFont();
68 SQLEditView& editor_;
71 SQLEditView::SQLEditView(std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
72 : m_xScrolledWindow(std::move(xScrolledWindow))
73 , m_aUpdateDataTimer("dbaccess SQLEditView m_aUpdateDataTimer")
74 , m_aHighlighter(HighlighterLanguage::SQL)
75 , m_bInUpdate(false)
76 , m_bDisableInternalUndo(false)
78 m_xScrolledWindow->connect_vadjustment_changed(LINK(this, SQLEditView, ScrollHdl));
81 void SQLEditView::DisableInternalUndo()
83 GetEditEngine()->EnableUndo(false);
84 m_bDisableInternalUndo = true;
87 void SQLEditView::SetItemPoolFont(SfxItemPool* pItemPool)
89 OUString sFontName(officecfg::Office::Common::Font::SourceViewFont::FontName::get().value_or(OUString()));
90 if (sFontName.isEmpty())
92 vcl::Font aTmpFont(OutputDevice::GetDefaultFont(DefaultFontType::FIXED, Application::GetSettings().GetUILanguageTag().getLanguageType(), GetDefaultFontFlags::OnlyOne));
93 sFontName = aTmpFont.GetFamilyName();
96 Size aFontSize(0, officecfg::Office::Common::Font::SourceViewFont::FontHeight::get());
97 vcl::Font aAppFont(sFontName, aFontSize);
99 pItemPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
100 "", PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
101 EE_CHAR_FONTINFO));
102 pItemPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
103 "", PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
104 EE_CHAR_FONTINFO_CJK));
105 pItemPool->SetPoolDefaultItem(SvxFontItem(aAppFont.GetFamilyType(), aAppFont.GetFamilyName(),
106 "", PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW,
107 EE_CHAR_FONTINFO_CTL));
109 pItemPool->SetPoolDefaultItem(
110 SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT));
111 pItemPool->SetPoolDefaultItem(
112 SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CJK));
113 pItemPool->SetPoolDefaultItem(
114 SvxFontHeightItem(aAppFont.GetFontHeight() * 20, 100, EE_CHAR_FONTHEIGHT_CTL));
117 void SQLEditView::makeEditEngine()
119 assert(!m_pItemPool);
120 m_pItemPool = EditEngine::CreatePool();
121 SetItemPoolFont(m_pItemPool.get());
122 m_xEditEngine.reset(new EditEngine(m_pItemPool.get()));
125 void SQLEditView::SetDrawingArea(weld::DrawingArea* pDrawingArea)
127 WeldEditView::SetDrawingArea(pDrawingArea);
129 EditEngine& rEditEngine = *GetEditEngine();
131 rEditEngine.SetDefaultHorizontalTextDirection(EEHorizontalTextDirection::L2R);
132 rEditEngine.SetModifyHdl(LINK(this, SQLEditView, ModifyHdl));
133 rEditEngine.SetStatusEventHdl(LINK(this, SQLEditView, EditStatusHdl));
135 m_aUpdateDataTimer.SetTimeout(150);
136 m_aUpdateDataTimer.SetInvokeHandler(LINK(this, SQLEditView, ImplUpdateDataHdl));
138 ImplSetFont();
140 // Listen for change of Font and Color Settings:
141 // Using "this" in ctor is a little fishy, but should work here at least as
142 // long as there are no derivations:
143 m_listener = new ChangesListener(*this);
144 css::uno::Reference< css::beans::XMultiPropertySet > n(
145 officecfg::Office::Common::Font::SourceViewFont::get(),
146 css::uno::UNO_QUERY_THROW);
148 std::unique_lock g(m_mutex);
149 m_notifier = n;
151 css::uno::Sequence< OUString > s { "FontHeight", "FontName" };
152 n->addPropertiesChangeListener(s, m_listener);
153 m_ColorConfig.AddListener(this);
156 SQLEditView::~SQLEditView()
158 css::uno::Reference< css::beans::XMultiPropertySet > n;
160 std::unique_lock g(m_mutex);
161 n = m_notifier;
163 if (n.is()) {
164 n->removePropertiesChangeListener(m_listener);
166 m_ColorConfig.RemoveListener(this);
169 void SQLEditView::SetTextAndUpdate(const OUString& rNewText)
171 SetText(rNewText);
172 UpdateData();
175 IMPL_LINK_NOARG(SQLEditView, ModifyHdl, LinkParamNone*, void)
177 if (m_bInUpdate)
178 return;
179 m_aUpdateDataTimer.Start();
182 IMPL_LINK_NOARG(SQLEditView, ImplUpdateDataHdl, Timer*, void)
184 UpdateData();
187 Color SQLEditView::GetColorValue(TokenType aToken)
189 return GetSyntaxHighlightColor(m_aColorConfig, m_aHighlighter.GetLanguage(), aToken);
192 void SQLEditView::UpdateData()
194 m_bInUpdate = true;
195 EditEngine& rEditEngine = *GetEditEngine();
197 bool bModified = rEditEngine.IsModified();
198 bool bUndoEnabled = rEditEngine.IsUndoEnabled();
199 rEditEngine.EnableUndo(false);
201 // syntax highlighting
202 for (sal_Int32 nLine=0; nLine < rEditEngine.GetParagraphCount(); ++nLine)
204 OUString aLine( rEditEngine.GetText( nLine ) );
206 ESelection aAllLine(nLine, 0, nLine, EE_TEXTPOS_ALL);
207 rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_COLOR);
208 rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT);
209 rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT_CJK);
210 rEditEngine.RemoveAttribs(aAllLine, false, EE_CHAR_WEIGHT_CTL);
212 std::vector<HighlightPortion> aPortions;
213 m_aHighlighter.getHighlightPortions( aLine, aPortions );
214 for (auto const& portion : aPortions)
216 SfxItemSet aSet(rEditEngine.GetEmptyItemSet());
217 aSet.Put(SvxColorItem(GetColorValue(portion.tokenType), EE_CHAR_COLOR));
218 rEditEngine.QuickSetAttribs(aSet, ESelection(nLine, portion.nBegin, nLine, portion.nEnd));
222 rEditEngine.ClearModifyFlag();
224 m_bInUpdate = false;
226 rEditEngine.EnableUndo(bUndoEnabled);
228 if (bModified)
229 m_aModifyLink.Call(nullptr);
231 Invalidate();
234 void SQLEditView::DoBracketHilight(sal_uInt16 nKey)
236 ESelection aCurrentPos = m_xEditView->GetSelection();
237 sal_Int32 nStartPos = aCurrentPos.nStartPos;
238 const sal_uInt32 nStartPara = aCurrentPos.nStartPara;
239 sal_uInt16 nCount = 0;
240 int nChar = -1;
242 switch (nKey)
244 case '\'': // no break
245 case '"':
247 nChar = nKey;
248 break;
250 case '}' :
252 nChar = '{';
253 break;
255 case ')':
257 nChar = '(';
258 break;
260 case ']':
262 nChar = '[';
263 break;
267 if (nChar == -1)
268 return;
270 bool bUndoEnabled = m_xEditEngine->IsUndoEnabled();
271 m_xEditEngine->EnableUndo(false);
273 sal_uInt32 nPara = nStartPara;
276 if (nPara == nStartPara && nStartPos == 0)
277 continue;
279 OUString aLine( m_xEditEngine->GetText( nPara ) );
281 if (aLine.isEmpty())
282 continue;
284 for (sal_Int32 i = (nPara==nStartPara) ? nStartPos-1 : aLine.getLength()-1; i>0; --i)
286 if (aLine[i] == nChar)
288 if (!nCount)
290 SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet());
291 aSet.Put(SvxColorItem(Color(0,0,0), EE_CHAR_COLOR));
292 aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT));
293 aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT_CJK));
294 aSet.Put(SvxWeightItem(WEIGHT_ULTRABOLD, EE_CHAR_WEIGHT_CTL));
296 m_xEditEngine->QuickSetAttribs(aSet, ESelection(nPara, i, nPara, i + 1));
297 m_xEditEngine->QuickSetAttribs(aSet, ESelection(nStartPara, nStartPos, nStartPara, nStartPos));
298 return;
300 else
301 --nCount;
303 if (aLine[i] == nKey)
304 ++nCount;
306 } while (nPara--);
308 m_xEditEngine->EnableUndo(bUndoEnabled);
311 Color SQLEditView::GetSyntaxHighlightColor(const svtools::ColorConfig& rColorConfig, HighlighterLanguage eLanguage, TokenType aToken)
313 Color aColor;
314 switch (eLanguage)
316 case HighlighterLanguage::SQL:
318 switch (aToken)
320 case TokenType::Identifier: aColor = rColorConfig.GetColorValue(svtools::SQLIDENTIFIER).nColor; break;
321 case TokenType::Number: aColor = rColorConfig.GetColorValue(svtools::SQLNUMBER).nColor; break;
322 case TokenType::String: aColor = rColorConfig.GetColorValue(svtools::SQLSTRING).nColor; break;
323 case TokenType::Operator: aColor = rColorConfig.GetColorValue(svtools::SQLOPERATOR).nColor; break;
324 case TokenType::Keywords: aColor = rColorConfig.GetColorValue(svtools::SQLKEYWORD).nColor; break;
325 case TokenType::Parameter: aColor = rColorConfig.GetColorValue(svtools::SQLPARAMETER).nColor; break;
326 case TokenType::Comment: aColor = rColorConfig.GetColorValue(svtools::SQLCOMMENT).nColor; break;
327 default: aColor = Color(0,0,0);
329 break;
331 case HighlighterLanguage::Basic:
333 switch (aToken)
335 case TokenType::Identifier: aColor = Color(255,0,0); break;
336 case TokenType::Comment: aColor = Color(0,0,45); break;
337 case TokenType::Number: aColor = Color(204,102,204); break;
338 case TokenType::String: aColor = Color(0,255,45); break;
339 case TokenType::Operator: aColor = Color(0,0,100); break;
340 case TokenType::Keywords: aColor = Color(0,0,255); break;
341 case TokenType::Error : aColor = Color(0,255,255); break;
342 default: aColor = Color(0,0,0);
344 break;
346 default: aColor = Color(0,0,0);
349 return aColor;
352 bool SQLEditView::KeyInput(const KeyEvent& rKEvt)
354 DoBracketHilight(rKEvt.GetCharCode());
356 if (m_bDisableInternalUndo)
358 KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
359 if (eFunc == KeyFuncType::UNDO || eFunc == KeyFuncType::REDO)
360 return false;
363 return WeldEditView::KeyInput(rKEvt);
366 bool SQLEditView::Command(const CommandEvent& rCEvt)
368 if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
370 ::tools::Rectangle aRect(rCEvt.GetMousePosPixel(), Size(1, 1));
371 weld::Widget* pPopupParent = GetDrawingArea();
372 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "vcl/ui/editmenu.ui"));
373 std::unique_ptr<weld::Menu> xContextMenu(xBuilder->weld_menu("menu"));
375 bool bEnableCut = true;
376 bool bEnableCopy = true;
377 bool bEnableDelete = true;
378 bool bEnablePaste = true;
379 bool bEnableSpecialChar = true;
381 EditView* pEditView = GetEditView();
383 if (!pEditView->HasSelection())
385 bEnableCut = false;
386 bEnableCopy = false;
387 bEnableDelete = false;
390 if (pEditView->IsReadOnly())
392 bEnableCut = false;
393 bEnablePaste = false;
394 bEnableDelete = false;
395 bEnableSpecialChar = false;
398 xContextMenu->set_sensitive("cut", bEnableCut);
399 xContextMenu->set_sensitive("copy", bEnableCopy);
400 xContextMenu->set_sensitive("delete", bEnableDelete);
401 xContextMenu->set_sensitive("paste", bEnablePaste);
402 xContextMenu->set_sensitive("specialchar", bEnableSpecialChar);
403 xContextMenu->set_visible("undo", false);
404 xContextMenu->set_visible("specialchar", vcl::GetGetSpecialCharsFunction() != nullptr);
406 OUString sCommand = xContextMenu->popup_at_rect(pPopupParent, aRect);
408 if (sCommand == "cut")
409 pEditView->Cut();
410 else if (sCommand == "copy")
411 pEditView->Copy();
412 else if (sCommand == "paste")
413 pEditView->Paste();
414 else if (sCommand == "delete")
415 pEditView->DeleteSelected();
416 else if (sCommand == "selectall")
418 sal_Int32 nPar = m_xEditEngine->GetParagraphCount();
419 if (nPar)
421 sal_Int32 nLen = m_xEditEngine->GetTextLen(nPar - 1);
422 pEditView->SetSelection(ESelection(0, 0, nPar - 1, nLen));
425 else if (sCommand == "specialchar")
427 OUString aChars = vcl::GetGetSpecialCharsFunction()(pPopupParent, m_xEditEngine->GetStandardFont(0));
428 if (!aChars.isEmpty())
430 pEditView->InsertText(aChars);
434 return true;
436 return WeldEditView::Command(rCEvt);
439 void SQLEditView::EditViewScrollStateChange()
441 // editengine height has changed or editview scroll pos has changed
442 SetScrollBarRange();
445 void SQLEditView::SetScrollBarRange()
447 EditEngine *pEditEngine = GetEditEngine();
448 if (!pEditEngine)
449 return;
450 if (!m_xScrolledWindow)
451 return;
452 EditView* pEditView = GetEditView();
453 if (!pEditView)
454 return;
456 int nVUpper = pEditEngine->GetTextHeight();
457 int nVCurrentDocPos = pEditView->GetVisArea().Top();
458 const Size aOut(pEditView->GetOutputArea().GetSize());
459 int nVStepIncrement = aOut.Height() * 2 / 10;
460 int nVPageIncrement = aOut.Height() * 8 / 10;
461 int nVPageSize = aOut.Height();
463 /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
464 effectively...
466 lower = gtk_adjustment_get_lower
467 upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
469 and requires that upper > lower or the deceleration animation never ends
471 nVPageSize = std::min(nVPageSize, nVUpper);
473 m_xScrolledWindow->vadjustment_configure(nVCurrentDocPos, 0, nVUpper,
474 nVStepIncrement, nVPageIncrement, nVPageSize);
477 IMPL_LINK_NOARG(SQLEditView, ScrollHdl, weld::ScrolledWindow&, void)
479 DoScroll();
482 IMPL_LINK_NOARG(SQLEditView, EditStatusHdl, EditStatus&, void)
484 Resize();
487 void SQLEditView::DoScroll()
489 if (m_xEditView)
491 auto currentDocPos = m_xEditView->GetVisArea().Top();
492 auto nDiff = currentDocPos - m_xScrolledWindow->vadjustment_get_value();
493 // we expect SetScrollBarRange callback to be triggered by Scroll
494 // to set where we ended up
495 m_xEditView->Scroll(0, nDiff);
499 void SQLEditView::ConfigurationChanged(utl::ConfigurationBroadcaster*, ConfigurationHints)
501 UpdateData();
504 void SQLEditView::ImplSetFont()
506 // see SmEditWindow::DataChanged for a similar case
507 SetItemPoolFont(m_pItemPool.get()); // change default font
508 // re-create with the new font
509 EditEngine& rEditEngine = *GetEditEngine();
510 OUString aTxt(rEditEngine.GetText());
511 rEditEngine.Clear();
512 SetTextAndUpdate(aTxt);
515 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */