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 20 #include <memory> 21 #include <ElementsDockingWindow.hxx> 22 23 #include <starmath.hrc> 24 #include <strings.hrc> 25 #include <smmod.hxx> 26 #include <view.hxx> 27 #include <visitors.hxx> 28 #include <document.hxx> 29 #include <node.hxx> 30 #include "uiobject.hxx" 31 #include <strings.hxx> 32 33 #include <svl/stritem.hxx> 34 #include <sfx2/dispatch.hxx> 35 #include <sfx2/sfxmodelfactory.hxx> 36 #include <vcl/event.hxx> 37 #include <vcl/help.hxx> 38 #include <vcl/settings.hxx> 39 #include <vcl/uitest/logger.hxx> 40 #include <vcl/uitest/eventdescription.hxx> 41 42 SmElement::SmElement(std::unique_ptr<SmNode>&& pNode, const OUString& aText, const OUString& aHelpText) : 43 mpNode(std::move(pNode)), 44 maText(aText), 45 maHelpText(aHelpText) 46 {} 47 48 SmElement::~SmElement() 49 {} 50 51 const std::unique_ptr<SmNode>& SmElement::getNode() 52 { 53 return mpNode; 54 } 55 56 SmElementSeparator::SmElementSeparator() : 57 SmElement(std::unique_ptr<SmNode>(), OUString(), OUString()) 58 {} 59 60 const std::pair<const char*, const char*> SmElementsControl::aUnaryBinaryOperatorsList[] = 61 { 62 {RID_PLUSX, RID_PLUSX_HELP}, {RID_MINUSX, RID_MINUSX_HELP}, 63 {RID_PLUSMINUSX, RID_PLUSMINUSX_HELP}, {RID_MINUSPLUSX, RID_MINUSPLUSX_HELP}, 64 {nullptr, nullptr}, 65 {RID_XPLUSY, RID_XPLUSY_HELP}, {RID_XMINUSY, RID_XMINUSY_HELP}, 66 {RID_XCDOTY, RID_XCDOTY_HELP}, {RID_XTIMESY, RID_XTIMESY_HELP}, 67 {RID_XSYMTIMESY, RID_XSYMTIMESY_HELP}, {RID_XOVERY, RID_XOVERY_HELP}, 68 {RID_XDIVY, RID_XDIVY_HELP}, {RID_XSYMDIVIDEY, RID_XSYMDIVIDEY_HELP}, 69 {RID_XOPLUSY, RID_XOPLUSY_HELP}, {RID_XOMINUSY, RID_XOMINUSY_HELP}, 70 {RID_XODOTY, RID_XODOTY_HELP}, {RID_XOTIMESY, RID_XOTIMESY_HELP}, 71 {RID_XODIVIDEY, RID_XODIVIDEY_HELP}, {RID_XCIRCY, RID_XCIRCY_HELP}, 72 {RID_XWIDESLASHY, RID_XWIDESLASHY_HELP}, {RID_XWIDEBSLASHY, RID_XWIDEBSLASHY_HELP}, 73 {nullptr, nullptr}, 74 {RID_NEGX, RID_NEGX_HELP}, {RID_XANDY, RID_XANDY_HELP}, {RID_XORY, RID_XORY_HELP}, 75 }; 76 77 const std::pair<const char*, const char*> SmElementsControl::aRelationsList[] = 78 { 79 {RID_XEQY, RID_XEQY_HELP}, {RID_XNEQY, RID_XNEQY_HELP}, {RID_XLTY, RID_XLTY_HELP}, 80 {RID_XLEY, RID_XLEY_HELP}, {RID_XLESLANTY, RID_XLESLANTY_HELP}, {RID_XGTY, RID_XGTY_HELP}, 81 {RID_XGEY, RID_XGEY_HELP}, {RID_XGESLANTY, RID_XGESLANTY_HELP}, 82 {RID_XLLY, RID_XLLY_HELP}, {RID_XGGY, RID_XGGY_HELP}, 83 {nullptr, nullptr}, 84 {RID_XAPPROXY, RID_XAPPROXY_HELP}, {RID_XSIMY, RID_XSIMY_HELP}, {RID_XSIMEQY, RID_XSIMEQY_HELP}, 85 {RID_XEQUIVY, RID_XEQUIVY_HELP}, {RID_XPROPY, RID_XPROPY_HELP}, {RID_XPARALLELY, RID_XPARALLELY_HELP}, 86 {RID_XORTHOY, RID_XORTHOY_HELP}, {RID_XDIVIDESY, RID_XDIVIDESY_HELP}, {RID_XNDIVIDESY, RID_XNDIVIDESY_HELP}, 87 {RID_XTOWARDY, RID_XTOWARDY_HELP}, {RID_XTRANSLY, RID_XTRANSLY_HELP}, {RID_XTRANSRY, RID_XTRANSRY_HELP}, 88 {RID_XDEFY, RID_XDEFY_HELP}, 89 {nullptr, nullptr}, 90 {RID_DLARROW, RID_DLARROW_HELP}, {RID_DLRARROW, RID_DLRARROW_HELP}, {RID_DRARROW, RID_DRARROW_HELP}, 91 {nullptr, nullptr}, 92 {RID_XPRECEDESY, RID_XPRECEDESY_HELP}, {RID_XSUCCEEDSY, RID_XSUCCEEDSY_HELP}, 93 {RID_XPRECEDESEQUALY, RID_XPRECEDESEQUALY_HELP}, {RID_XSUCCEEDSEQUALY, RID_XSUCCEEDSEQUALY_HELP}, 94 {RID_XPRECEDESEQUIVY, RID_XPRECEDESEQUIVY_HELP}, {RID_XSUCCEEDSEQUIVY, RID_XSUCCEEDSEQUIVY_HELP}, 95 {RID_XNOTPRECEDESY, RID_XNOTPRECEDESY_HELP}, {RID_XNOTSUCCEEDSY, RID_XNOTSUCCEEDSY_HELP}, 96 }; 97 98 const std::pair<const char*, const char*> SmElementsControl::aSetOperations[] = 99 { 100 {RID_XINY, RID_XINY_HELP}, {RID_XNOTINY, RID_XNOTINY_HELP}, {RID_XOWNSY, RID_XOWNSY_HELP}, 101 {nullptr, nullptr}, 102 {RID_XINTERSECTIONY, RID_XINTERSECTIONY_HELP}, {RID_XUNIONY, RID_XUNIONY_HELP}, 103 {RID_XSETMINUSY, RID_XSETMINUSY_HELP}, {RID_XSLASHY, RID_XSLASHY_HELP}, 104 {RID_XSUBSETY, RID_XSUBSETY_HELP}, {RID_XSUBSETEQY, RID_XSUBSETEQY_HELP}, 105 {RID_XSUPSETY, RID_XSUPSETY_HELP}, {RID_XSUPSETEQY, RID_XSUPSETEQY_HELP}, 106 {RID_XNSUBSETY, RID_XNSUBSETY_HELP}, {RID_XNSUBSETEQY, RID_XNSUBSETEQY_HELP}, 107 {RID_XNSUPSETY, RID_XNSUPSETY_HELP}, {RID_XNSUPSETEQY, RID_XNSUPSETEQY_HELP}, 108 {nullptr, nullptr}, 109 {RID_EMPTYSET, RID_EMPTYSET_HELP}, {RID_ALEPH, RID_ALEPH_HELP}, {RID_SETN, RID_SETN_HELP}, 110 {RID_SETZ, RID_SETZ_HELP}, {RID_SETQ, RID_SETQ_HELP}, {RID_SETR, RID_SETR_HELP}, {RID_SETC, RID_SETC_HELP} 111 }; 112 113 const std::pair<const char*, const char*> SmElementsControl::aFunctions[] = 114 { 115 {RID_ABSX, RID_ABSX_HELP}, {RID_FACTX, RID_FACTX_HELP}, {RID_SQRTX, RID_SQRTX_HELP}, 116 {RID_NROOTXY, RID_NROOTXY_HELP}, {RID_RSUPX, RID_RSUPX_HELP}, {RID_EX, RID_EX_HELP}, 117 {RID_LNX, RID_LNX_HELP}, {RID_EXPX, RID_EXPX_HELP}, {RID_LOGX, RID_LOGX_HELP}, 118 {nullptr, nullptr}, 119 {RID_SINX, RID_SINX_HELP}, {RID_COSX, RID_COSX_HELP}, {RID_TANX, RID_TANX_HELP}, {RID_COTX, RID_COTX_HELP}, 120 {RID_SINHX, RID_SINHX_HELP}, {RID_COSHX, RID_COSHX_HELP}, {RID_TANHX, RID_TANHX_HELP}, 121 {RID_COTHX, RID_COTHX_HELP}, 122 {nullptr, nullptr}, 123 {RID_ARCSINX, RID_ARCSINX_HELP}, {RID_ARCCOSX, RID_ARCCOSX_HELP}, {RID_ARCTANX, RID_ARCTANX_HELP}, 124 {RID_ARCCOTX, RID_ARCCOTX_HELP}, {RID_ARSINHX, RID_ARSINHX_HELP}, {RID_ARCOSHX, RID_ARCOSHX_HELP}, 125 {RID_ARTANHX, RID_ARTANHX_HELP}, {RID_ARCOTHX, RID_ARCOTHX_HELP} 126 }; 127 128 const std::pair<const char*, const char*> SmElementsControl::aOperators[] = 129 { 130 {RID_LIMX, RID_LIMX_HELP}, {RID_LIM_FROMX, RID_LIM_FROMX_HELP}, 131 {RID_LIM_TOX, RID_LIM_TOX_HELP}, {RID_LIM_FROMTOX, RID_LIM_FROMTOX_HELP}, 132 {nullptr, nullptr}, 133 {RID_LIMINFX, RID_LIMINFX_HELP}, {RID_LIMINF_FROMX, RID_LIMINF_FROMX_HELP}, 134 {RID_LIMINF_TOX, RID_LIMINF_TOX_HELP}, {RID_LIMINF_FROMTOX, RID_LIMINF_FROMTOX_HELP}, 135 {nullptr, nullptr}, 136 {RID_LIMSUPX, RID_LIMSUPX_HELP}, {RID_LIMSUP_FROMX, RID_LIMSUP_FROMX_HELP}, 137 {RID_LIMSUP_TOX, RID_LIMSUP_TOX_HELP}, {RID_LIMSUP_FROMTOX, RID_LIMSUP_FROMTOX_HELP}, 138 {nullptr, nullptr}, 139 {RID_SUMX, RID_SUMX_HELP}, {RID_SUM_FROMX, RID_SUM_FROMX_HELP}, 140 {RID_SUM_TOX, RID_SUM_TOX_HELP}, {RID_SUM_FROMTOX, RID_SUM_FROMTOX_HELP}, 141 {nullptr, nullptr}, 142 {RID_PRODX, RID_PRODX_HELP}, {RID_PROD_FROMX, RID_PROD_FROMX_HELP}, 143 {RID_PROD_TOX, RID_PROD_TOX_HELP}, {RID_PROD_FROMTOX, RID_PROD_FROMTOX_HELP}, 144 {nullptr, nullptr}, 145 {RID_COPRODX, RID_COPRODX_HELP}, {RID_COPROD_FROMX, RID_COPROD_FROMX_HELP}, 146 {RID_COPROD_TOX, RID_COPROD_TOX_HELP}, {RID_COPROD_FROMTOX, RID_COPROD_FROMTOX_HELP}, 147 {nullptr, nullptr}, 148 {RID_INTX, RID_INTX_HELP}, {RID_INT_FROMX, RID_INT_FROMX_HELP}, 149 {RID_INT_TOX, RID_INT_TOX_HELP}, {RID_INT_FROMTOX, RID_INT_FROMTOX_HELP}, 150 {nullptr, nullptr}, 151 {RID_IINTX, RID_IINTX_HELP}, {RID_IINT_FROMX, RID_IINT_FROMX_HELP}, 152 {RID_IINT_TOX, RID_IINT_TOX_HELP}, {RID_IINT_FROMTOX, RID_IINT_FROMTOX_HELP}, 153 {nullptr, nullptr}, 154 {RID_IIINTX, RID_IIINTX_HELP}, {RID_IIINT_FROMX, RID_IIINT_FROMX_HELP}, 155 {RID_IIINT_TOX, RID_IIINT_TOX_HELP}, {RID_IIINT_FROMTOX, RID_IIINT_FROMTOX_HELP}, 156 {nullptr, nullptr}, 157 {RID_LINTX, RID_LINTX_HELP}, {RID_LINT_FROMX, RID_LINT_FROMX_HELP}, 158 {RID_LINT_TOX, RID_LINT_TOX_HELP}, {RID_LINT_FROMTOX, RID_LINT_FROMTOX_HELP}, 159 {nullptr, nullptr}, 160 {RID_LLINTX, RID_LLINTX_HELP}, {RID_LLINT_FROMX, RID_LLINT_FROMX_HELP}, 161 {RID_LLINT_TOX, RID_LLINT_TOX_HELP}, {RID_LLINT_FROMTOX, RID_LLINT_FROMTOX_HELP}, 162 {nullptr, nullptr}, 163 {RID_LLLINTX, RID_LLLINTX_HELP}, {RID_LLLINT_FROMX, RID_LLLINT_FROMX_HELP}, 164 {RID_LLLINT_TOX, RID_LLLINT_TOX_HELP}, {RID_LLLINT_FROMTOX, RID_LLLINT_FROMTOX_HELP}, 165 }; 166 167 const std::pair<const char*, const char*> SmElementsControl::aAttributes[] = 168 { 169 {RID_ACUTEX, RID_ACUTEX_HELP}, {RID_GRAVEX, RID_GRAVEX_HELP}, {RID_BREVEX, RID_BREVEX_HELP}, 170 {RID_CIRCLEX, RID_CIRCLEX_HELP}, {RID_DOTX, RID_DOTX_HELP}, {RID_DDOTX, RID_DDOTX_HELP}, 171 {RID_DDDOTX, RID_DDDOTX_HELP}, {RID_BARX, RID_BARX_HELP}, {RID_VECX, RID_VECX_HELP}, 172 {RID_TILDEX, RID_TILDEX_HELP}, {RID_HATX, RID_HATX_HELP}, {RID_CHECKX, RID_CHECKX_HELP}, 173 {nullptr, nullptr}, 174 {RID_WIDEVECX, RID_WIDEVECX_HELP}, {RID_WIDETILDEX, RID_WIDETILDEX_HELP}, {RID_WIDEHATX, RID_WIDEHATX_HELP}, 175 {RID_OVERLINEX, RID_OVERLINEX_HELP}, {RID_UNDERLINEX, RID_UNDERLINEX_HELP}, {RID_OVERSTRIKEX, RID_OVERSTRIKEX_HELP}, 176 {nullptr, nullptr}, 177 {RID_PHANTOMX, RID_PHANTOMX_HELP}, {RID_BOLDX, RID_BOLDX_HELP}, {RID_ITALX, RID_ITALX_HELP}, 178 {RID_SIZEXY, RID_SIZEXY_HELP}, {RID_FONTXY, RID_FONTXY_HELP}, 179 {nullptr, nullptr}, 180 {RID_COLORX_BLACK, RID_COLORX_BLACK_HELP}, {RID_COLORX_BLUE, RID_COLORX_BLUE_HELP}, 181 {RID_COLORX_GREEN, RID_COLORX_GREEN_HELP}, {RID_COLORX_RED, RID_COLORX_RED_HELP}, 182 {RID_COLORX_CYAN, RID_COLORX_CYAN_HELP}, {RID_COLORX_MAGENTA, RID_COLORX_MAGENTA_HELP}, 183 {RID_COLORX_YELLOW, RID_COLORX_YELLOW_HELP}, {RID_COLORX_GRAY, RID_COLORX_GRAY_HELP}, 184 {RID_COLORX_LIME, RID_COLORX_LIME_HELP}, {RID_COLORX_MAROON, RID_COLORX_MAROON_HELP}, 185 {RID_COLORX_NAVY, RID_COLORX_NAVY_HELP}, {RID_COLORX_OLIVE, RID_COLORX_OLIVE_HELP}, 186 {RID_COLORX_PURPLE, RID_COLORX_PURPLE_HELP}, {RID_COLORX_SILVER, RID_COLORX_SILVER_HELP}, 187 {RID_COLORX_TEAL, RID_COLORX_TEAL_HELP} 188 }; 189 190 const std::pair<const char*, const char*> SmElementsControl::aBrackets[] = 191 { 192 {RID_LRGROUPX, RID_LRGROUPX_HELP}, 193 {nullptr, nullptr}, 194 {RID_LRPARENTX, RID_LRPARENTX_HELP}, {RID_LRBRACKETX, RID_LRBRACKETX_HELP}, 195 {RID_LRDBRACKETX, RID_LRDBRACKETX_HELP}, {RID_LRBRACEX, RID_LRBRACEX_HELP}, 196 {RID_LRANGLEX, RID_LRANGLEX_HELP}, {RID_LMRANGLEXY, RID_LMRANGLEXY_HELP}, 197 {RID_LRCEILX, RID_LRCEILX_HELP}, {RID_LRFLOORX, RID_LRFLOORX_HELP}, 198 {RID_LRLINEX, RID_LRLINEX_HELP}, {RID_LRDLINEX, RID_LRDLINEX_HELP}, 199 {nullptr, nullptr}, 200 {RID_SLRPARENTX, RID_SLRPARENTX_HELP}, {RID_SLRBRACKETX, RID_SLRBRACKETX_HELP}, 201 {RID_SLRDBRACKETX, RID_SLRDBRACKETX_HELP}, {RID_SLRBRACEX, RID_SLRBRACEX_HELP}, 202 {RID_SLRANGLEX, RID_SLRANGLEX_HELP}, {RID_SLMRANGLEXY, RID_SLMRANGLEXY_HELP}, 203 {RID_SLRCEILX, RID_SLRCEILX_HELP}, {RID_SLRFLOORX, RID_SLRFLOORX_HELP}, 204 {RID_SLRLINEX, RID_SLRLINEX_HELP}, {RID_SLRDLINEX, RID_SLRDLINEX_HELP}, 205 {RID_XEVALUATEDATY, RID_XEVALUATEDATY_HELP}, 206 {nullptr, nullptr}, 207 {RID_XOVERBRACEY, RID_XOVERBRACEY_HELP}, {RID_XUNDERBRACEY, RID_XUNDERBRACEY_HELP}, 208 }; 209 210 const std::pair<const char*, const char*> SmElementsControl::aFormats[] = 211 { 212 {RID_RSUPX, RID_RSUPX_HELP}, {RID_RSUBX, RID_RSUBX_HELP}, {RID_LSUPX, RID_LSUPX_HELP}, 213 {RID_LSUBX, RID_LSUBX_HELP}, {RID_CSUPX, RID_CSUPX_HELP}, {RID_CSUBX, RID_CSUBX_HELP}, 214 {nullptr, nullptr}, 215 {RID_NEWLINE, RID_NEWLINE_HELP}, {RID_SBLANK, RID_SBLANK_HELP}, {RID_BLANK, RID_BLANK_HELP}, 216 {RID_NOSPACE, RID_NOSPACE_HELP}, 217 {RID_ALIGNLX, RID_ALIGNLX_HELP}, {RID_ALIGNCX, RID_ALIGNCX_HELP}, {RID_ALIGNRX, RID_ALIGNRX_HELP}, 218 {nullptr, nullptr}, 219 {RID_BINOMXY, RID_BINOMXY_HELP}, {RID_STACK, RID_STACK_HELP}, 220 {RID_MATRIX, RID_MATRIX_HELP}, 221 }; 222 223 const std::pair<const char*, const char*> SmElementsControl::aOthers[] = 224 { 225 {RID_INFINITY, RID_INFINITY_HELP}, {RID_PARTIAL, RID_PARTIAL_HELP}, {RID_NABLA, RID_NABLA_HELP}, 226 {RID_EXISTS, RID_EXISTS_HELP}, {RID_NOTEXISTS, RID_NOTEXISTS_HELP}, {RID_FORALL, RID_FORALL_HELP}, 227 {RID_HBAR, RID_HBAR_HELP}, {RID_LAMBDABAR, RID_LAMBDABAR_HELP}, {RID_RE, RID_RE_HELP}, 228 {RID_IM, RID_IM_HELP}, {RID_WP, RID_WP_HELP}, 229 {nullptr, nullptr}, 230 {RID_LEFTARROW, RID_LEFTARROW_HELP}, {RID_RIGHTARROW, RID_RIGHTARROW_HELP}, {RID_UPARROW, RID_UPARROW_HELP}, 231 {RID_DOWNARROW, RID_DOWNARROW_HELP}, 232 {nullptr, nullptr}, 233 {RID_DOTSLOW, RID_DOTSLOW_HELP}, {RID_DOTSAXIS, RID_DOTSAXIS_HELP}, {RID_DOTSVERT, RID_DOTSVERT_HELP}, 234 {RID_DOTSUP, RID_DOTSUP_HELP}, {RID_DOTSDOWN, RID_DOTSDOWN_HELP} 235 }; 236 237 SmElementsControl::SmElementsControl(vcl::Window *pParent) 238 : Control(pParent, WB_TABSTOP) 239 , mpDocShell(new SmDocShell(SfxModelFlags::EMBEDDED_OBJECT)) 240 , mpCurrentElement(nullptr) 241 , mbVerticalMode(true) 242 , mxScroll(VclPtr<ScrollBar>::Create(this, WB_VERT)) 243 { 244 set_id("element_selector"); 245 SetMapMode( MapMode(MapUnit::Map100thMM) ); 246 SetDrawMode( DrawModeFlags::Default ); 247 SetLayoutMode( ComplexTextLayoutFlags::Default ); 248 SetDigitLanguage( LANGUAGE_ENGLISH ); 249 250 maFormat.SetBaseSize(PixelToLogic(Size(0, SmPtsTo100th_mm(12)))); 251 252 mxScroll->SetScrollHdl( LINK(this, SmElementsControl, ScrollHdl) ); 253 mxScroll->Show(); 254 } 255 256 SmElementsControl::~SmElementsControl() 257 { 258 disposeOnce(); 259 } 260 261 void SmElementsControl::dispose() 262 { 263 mpDocShell->DoClose(); 264 mxScroll.disposeAndClear(); 265 Control::dispose(); 266 } 267 268 void SmElementsControl::setVerticalMode(bool bVerticalMode) 269 { 270 mbVerticalMode = bVerticalMode; 271 } 272 273 void SmElementsControl::LayoutOrPaintContents(vcl::RenderContext *pContext) 274 { 275 bool bOldVisibleState = mxScroll->IsVisible(); 276 277 sal_Int32 nScrollbarWidth = bOldVisibleState ? GetSettings().GetStyleSettings().GetScrollBarSize() : 0; 278 279 sal_Int32 nControlWidth = GetOutputSizePixel().Width() - nScrollbarWidth; 280 sal_Int32 nControlHeight = GetOutputSizePixel().Height(); 281 282 sal_Int32 boxX = maMaxElementDimensions.Width() + 10; 283 sal_Int32 boxY = maMaxElementDimensions.Height() + 10; 284 285 sal_Int32 x = 0; 286 sal_Int32 y = -mxScroll->GetThumbPos(); 287 288 sal_Int32 perLine = 0; 289 290 if (mbVerticalMode) 291 perLine = nControlHeight / boxY; 292 else 293 perLine = nControlWidth / boxX; 294 295 if (perLine <= 0) 296 { 297 perLine = 1; 298 } 299 300 if (mbVerticalMode) 301 boxY = nControlHeight / perLine; 302 else 303 boxX = nControlWidth / perLine; 304 305 for (std::unique_ptr<SmElement> & i : maElementList) 306 { 307 SmElement* element = i.get(); 308 if (element->isSeparator()) 309 { 310 if (mbVerticalMode) 311 { 312 x += boxX; 313 y = 0; 314 315 tools::Rectangle aSelectionRectangle(x + 5 - 1, y + 5, 316 x + 5 + 1, nControlHeight - 5); 317 318 if (pContext) 319 pContext->DrawRect(PixelToLogic(aSelectionRectangle)); 320 x += 10; 321 } 322 else 323 { 324 x = 0; 325 y += boxY; 326 327 tools::Rectangle aSelectionRectangle(x + 5, y + 5 - 1, 328 nControlWidth - 5, y + 5 + 1); 329 330 if (pContext) 331 pContext->DrawRect(PixelToLogic(aSelectionRectangle)); 332 y += 10; 333 } 334 } 335 else 336 { 337 Size aSizePixel = LogicToPixel(Size(element->getNode()->GetWidth(), 338 element->getNode()->GetHeight())); 339 if (mbVerticalMode) 340 { 341 if (y + boxY > nControlHeight) 342 { 343 x += boxX; 344 y = 0; 345 } 346 } 347 else 348 { 349 if ( x + boxX > nControlWidth) 350 { 351 x = 0; 352 y += boxY; 353 } 354 } 355 356 if (mpCurrentElement == element && pContext) 357 { 358 pContext->Push(PushFlags::FILLCOLOR | PushFlags::LINECOLOR); 359 pContext->SetFillColor(Color(230, 230, 230)); 360 pContext->SetLineColor(Color(230, 230, 230)); 361 362 pContext->DrawRect(PixelToLogic(tools::Rectangle(x + 2, y + 2, x + boxX - 2, y + boxY - 2))); 363 pContext->Pop(); 364 } 365 366 Point location(x + ((boxX - aSizePixel.Width()) / 2), 367 y + ((boxY - aSizePixel.Height()) / 2)); 368 369 if (pContext) 370 SmDrawingVisitor(*pContext, PixelToLogic(location), element->getNode().get()); 371 372 element->mBoxLocation = Point(x,y); 373 element->mBoxSize = Size(boxX, boxY); 374 375 if (mbVerticalMode) 376 y += boxY; 377 else 378 x += boxX; 379 } 380 } 381 382 if (pContext) 383 return; 384 385 sal_Int32 nTotalControlHeight = y + boxY + mxScroll->GetThumbPos(); 386 387 if (nTotalControlHeight > GetOutputSizePixel().Height()) 388 { 389 mxScroll->SetRangeMax(nTotalControlHeight); 390 mxScroll->SetPosSizePixel(Point(nControlWidth, 0), Size(nScrollbarWidth, nControlHeight)); 391 mxScroll->SetVisibleSize(nControlHeight); 392 mxScroll->Show(); 393 } 394 else 395 { 396 mxScroll->SetThumbPos(0); 397 mxScroll->Hide(); 398 } 399 } 400 401 void SmElementsControl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) 402 { 403 rRenderContext.Push(); 404 LayoutOrPaintContents(&rRenderContext); 405 rRenderContext.Pop(); 406 } 407 408 void SmElementsControl::RequestHelp(const HelpEvent& rHEvt) 409 { 410 if (rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK)) 411 { 412 SmElement* pHelpElement = mpCurrentElement; 413 414 if (!rHEvt.KeyboardActivated()) 415 { 416 Point aHelpEventPos(ScreenToOutputPixel(rHEvt.GetMousePosPixel())); 417 for (std::unique_ptr<SmElement> & i : maElementList) 418 { 419 SmElement* pElement = i.get(); 420 tools::Rectangle aRect(pElement->mBoxLocation, pElement->mBoxSize); 421 if (aRect.IsInside(aHelpEventPos)) 422 { 423 pHelpElement = pElement; 424 break; 425 } 426 } 427 } 428 429 if (!pHelpElement) 430 return; 431 432 tools::Rectangle aHelpRect(pHelpElement->mBoxLocation, pHelpElement->mBoxSize); 433 Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() ); 434 aHelpRect.SetLeft( aPt.X() ); 435 aHelpRect.SetTop( aPt.Y() ); 436 aPt = OutputToScreenPixel( aHelpRect.BottomRight() ); 437 aHelpRect.SetRight( aPt.X() ); 438 aHelpRect.SetBottom( aPt.Y() ); 439 440 // get text and display it 441 OUString aStr = pHelpElement->getHelpText(); 442 if (rHEvt.GetMode() & HelpEventMode::BALLOON) 443 { 444 Help::ShowBalloon(this, aHelpRect.Center(), aHelpRect, aStr); 445 } 446 else 447 Help::ShowQuickHelp(this, aHelpRect, aStr, QuickHelpFlags::CtrlText); 448 return; 449 } 450 451 Control::RequestHelp(rHEvt); 452 } 453 454 void SmElementsControl::MouseMove( const MouseEvent& rMouseEvent ) 455 { 456 SmElement* pPrevElement = mpCurrentElement; 457 mpCurrentElement = nullptr; 458 if (rMouseEvent.IsLeaveWindow()) 459 { 460 LayoutOrPaintContents(); 461 Invalidate(); 462 return; 463 } 464 if (tools::Rectangle(Point(0, 0), GetOutputSizePixel()).IsInside(rMouseEvent.GetPosPixel())) 465 { 466 for (std::unique_ptr<SmElement> & i : maElementList) 467 { 468 SmElement* element = i.get(); 469 tools::Rectangle rect(element->mBoxLocation, element->mBoxSize); 470 if (rect.IsInside(rMouseEvent.GetPosPixel())) 471 { 472 if (pPrevElement != element) 473 { 474 mpCurrentElement = element; 475 LayoutOrPaintContents(); 476 Invalidate(); 477 return; 478 } 479 } 480 } 481 return; 482 } 483 484 Control::MouseMove(rMouseEvent); 485 } 486 487 namespace { 488 489 void collectUIInformation(const OUString& aID) 490 { 491 EventDescription aDescription; 492 aDescription.aID = aID; 493 aDescription.aParent = "element_selector"; 494 aDescription.aAction = "SELECT"; 495 aDescription.aKeyWord = "ElementUIObject"; 496 UITestLogger::getInstance().logEvent(aDescription); 497 } 498 499 } 500 501 void SmElementsControl::MouseButtonDown(const MouseEvent& rMouseEvent) 502 { 503 GrabFocus(); 504 505 if (rMouseEvent.IsLeft() && tools::Rectangle(Point(0, 0), GetOutputSizePixel()).IsInside(rMouseEvent.GetPosPixel()) && maSelectHdlLink.IsSet()) 506 { 507 sal_uInt16 nElementCount = maElementList.size(); 508 509 for (sal_uInt16 n = 0; n < nElementCount; n++) 510 { 511 std::unique_ptr<SmElement> & i = maElementList[n]; 512 SmElement* element = i.get(); 513 tools::Rectangle rect(element->mBoxLocation, element->mBoxSize); 514 if (rect.IsInside(rMouseEvent.GetPosPixel())) 515 { 516 maSelectHdlLink.Call(*element); 517 collectUIInformation(OUString::number(n)); 518 return; 519 } 520 } 521 } 522 else 523 { 524 Control::MouseButtonDown (rMouseEvent); 525 } 526 } 527 528 IMPL_LINK_NOARG( SmElementsControl, ScrollHdl, ScrollBar*, void ) 529 { 530 DoScroll(mxScroll->GetDelta()); 531 } 532 533 void SmElementsControl::DoScroll(long nDelta) 534 { 535 Point aNewPoint = mxScroll->GetPosPixel(); 536 tools::Rectangle aRect(Point(), GetOutputSize()); 537 aRect.AdjustRight( -(mxScroll->GetSizePixel().Width()) ); 538 Scroll( 0, -nDelta, aRect ); 539 mxScroll->SetPosPixel(aNewPoint); 540 LayoutOrPaintContents(); 541 Invalidate(); 542 } 543 544 void SmElementsControl::addElement(const OUString& aElementVisual, const OUString& aElementSource, const OUString& aHelpText) 545 { 546 auto pNode = SmParser().ParseExpression(aElementVisual); 547 548 pNode->Prepare(maFormat, *mpDocShell, 0); 549 pNode->SetSize(Fraction(10,8)); 550 pNode->Arrange(*this, maFormat); 551 552 Size aSizePixel = LogicToPixel(Size(pNode->GetWidth(), pNode->GetHeight()), MapMode(MapUnit::Map100thMM)); 553 if (aSizePixel.Width() > maMaxElementDimensions.Width()) { 554 maMaxElementDimensions.setWidth( aSizePixel.Width() ); 555 } 556 557 if (aSizePixel.Height() > maMaxElementDimensions.Height()) { 558 maMaxElementDimensions.setHeight( aSizePixel.Height() ); 559 } 560 561 maElementList.push_back(std::make_unique<SmElement>(std::move(pNode), aElementSource, aHelpText)); 562 } 563 564 void SmElementsControl::setElementSetId(const char* pSetId) 565 { 566 msCurrentSetId = pSetId; 567 maMaxElementDimensions = Size(); 568 build(); 569 } 570 571 void SmElementsControl::addElements(const std::pair<const char*, const char*> aElementsArray[], sal_uInt16 aElementsArraySize) 572 { 573 for (sal_uInt16 i = 0; i < aElementsArraySize ; i++) 574 { 575 const char* pElement = aElementsArray[i].first; 576 const char* pElementHelp = aElementsArray[i].second; 577 if (!pElement) { 578 maElementList.push_back(std::make_unique<SmElementSeparator>()); 579 } else { 580 OUString aElement(OUString::createFromAscii(pElement)); 581 if (aElement == RID_NEWLINE) 582 addElement(OUString(u"\u21B5"), aElement, SmResId(pElementHelp)); 583 else if (aElement == RID_SBLANK) 584 addElement("\"`\"", aElement, SmResId(pElementHelp)); 585 else if (aElement == RID_BLANK) 586 addElement("\"~\"", aElement, SmResId(pElementHelp)); 587 else if (aElement == RID_PHANTOMX) 588 addElement("\"" + SmResId(STR_HIDE) +"\"", aElement, SmResId(pElementHelp)); 589 else if (aElement == RID_BOLDX) 590 addElement("bold B", aElement, SmResId(pElementHelp)); 591 else if (aElement == RID_ITALX) 592 addElement("ital I", aElement, SmResId(pElementHelp)); 593 else if (aElement == RID_SIZEXY) 594 addElement("\"" + SmResId(STR_SIZE) + "\"", aElement, SmResId(pElementHelp)); 595 else if (aElement == RID_FONTXY) 596 addElement("\"" + SmResId(STR_FONT) + "\"", aElement, SmResId(pElementHelp)); 597 else if (aElement == RID_COLORX_BLACK) 598 addElement("color black { \"" + SmResId(STR_BLACK) + "\" }", aElement, SmResId(pElementHelp)); 599 else if (aElement == RID_COLORX_BLUE) 600 addElement("color blue { \"" + SmResId(STR_BLUE) + "\" }", aElement, SmResId(pElementHelp)); 601 else if (aElement == RID_COLORX_GREEN) 602 addElement("color green { \"" + SmResId(STR_GREEN) + "\" }", aElement, SmResId(pElementHelp)); 603 else if (aElement == RID_COLORX_RED) 604 addElement("color red { \"" + SmResId(STR_RED) + "\" }", aElement, SmResId(pElementHelp)); 605 else if (aElement == RID_COLORX_CYAN) 606 addElement("color cyan { \"" + SmResId(STR_CYAN) + "\" }", aElement, SmResId(pElementHelp)); 607 else if (aElement == RID_COLORX_MAGENTA) 608 addElement("color magenta { \"" + SmResId(STR_MAGENTA) + "\" }", aElement, SmResId(pElementHelp)); 609 else if (aElement == RID_COLORX_YELLOW) 610 addElement("color yellow { \"" + SmResId(STR_YELLOW) + "\" }", aElement, SmResId(pElementHelp)); 611 else if (aElement == RID_COLORX_GRAY) 612 addElement("color gray { \"" + SmResId(STR_GRAY) + "\" }", aElement, SmResId(pElementHelp)); 613 else if (aElement == RID_COLORX_LIME) 614 addElement("color lime { \"" + SmResId(STR_LIME) + "\" }", aElement, SmResId(pElementHelp)); 615 else if (aElement == RID_COLORX_MAROON) 616 addElement("color maroon { \"" + SmResId(STR_MAROON) + "\" }", aElement, SmResId(pElementHelp)); 617 else if (aElement == RID_COLORX_NAVY) 618 addElement("color navy { \"" + SmResId(STR_NAVY) + "\" }", aElement, SmResId(pElementHelp)); 619 else if (aElement == RID_COLORX_OLIVE) 620 addElement("color olive { \"" + SmResId(STR_OLIVE) + "\" }", aElement, SmResId(pElementHelp)); 621 else if (aElement == RID_COLORX_PURPLE) 622 addElement("color purple { \"" + SmResId(STR_PURPLE) + "\" }", aElement, SmResId(pElementHelp)); 623 else if (aElement == RID_COLORX_SILVER) 624 addElement("color silver { \"" + SmResId(STR_SILVER) + "\" }", aElement, SmResId(pElementHelp)); 625 else if (aElement == RID_COLORX_TEAL) 626 addElement("color teal { \"" + SmResId(STR_TEAL) + "\" }", aElement, SmResId(pElementHelp)); 627 else if (aElement == RID_ALIGNLX) 628 addElement("\"" + SmResId(STR_ALIGN_LEFT) + "\"", aElement, SmResId(pElementHelp)); 629 else if (aElement == RID_ALIGNCX) 630 addElement("\"" + SmResId(STR_ALIGN_CENTER) + "\"", aElement, SmResId(pElementHelp)); 631 else if (aElement == RID_ALIGNRX) 632 addElement("\"" + SmResId(STR_ALIGN_RIGHT) + "\"", aElement, SmResId(pElementHelp)); 633 634 else if (aElement == RID_SLRPARENTX) 635 addElement("left ( binom{<?>}{<?>} right ) ", aElement, SmResId(pElementHelp)); 636 else if (aElement == RID_SLRBRACKETX) 637 addElement("left [ binom{<?>}{<?>} right ] ", aElement, SmResId(pElementHelp)); 638 else if (aElement == RID_SLRDBRACKETX) 639 addElement("left ldbracket binom{<?>}{<?>} right rdbracket ", aElement, SmResId(pElementHelp)); 640 else if (aElement == RID_SLRBRACEX) 641 addElement("left lbrace binom{<?>}{<?>} right rbrace ", aElement, SmResId(pElementHelp)); 642 else if (aElement == RID_SLRANGLEX) 643 addElement("left langle binom{<?>}{<?>} right rangle ", aElement, SmResId(pElementHelp)); 644 else if (aElement == RID_SLRCEILX) 645 addElement("left lceil binom{<?>}{<?>} right rceil ", aElement, SmResId(pElementHelp)); 646 else if (aElement == RID_SLRFLOORX) 647 addElement("left lfloor binom{<?>}{<?>} right rfloor ", aElement, SmResId(pElementHelp)); 648 649 else if (aElement == RID_SLRLINEX) 650 addElement("left lline binom{<?>}{<?>} right rline ", aElement, SmResId(pElementHelp)); 651 else if (aElement == RID_SLRDLINEX) 652 addElement("left ldline binom{<?>}{<?>} right rdline ", aElement, SmResId(pElementHelp)); 653 else if (aElement == RID_SLMRANGLEXY) 654 addElement("left langle binom{<?>}{<?>} mline binom{<?>}{<?>} right rangle ", aElement, SmResId(pElementHelp)); 655 656 else if (aElement == RID_XOVERBRACEY) 657 addElement("{<?><?><?>} overbrace {<?>} ", aElement, SmResId(pElementHelp)); 658 else if (aElement == RID_XUNDERBRACEY) 659 addElement("{<?><?><?>} underbrace {<?>} ", aElement, SmResId(pElementHelp)); 660 else 661 addElement(aElement, aElement, SmResId(pElementHelp)); 662 } 663 } 664 } 665 666 void SmElementsControl::build() 667 { 668 maElementList.clear(); 669 670 if (msCurrentSetId == RID_CATEGORY_UNARY_BINARY_OPERATORS) 671 addElements(aUnaryBinaryOperatorsList, SAL_N_ELEMENTS(aUnaryBinaryOperatorsList)); 672 else if (msCurrentSetId == RID_CATEGORY_RELATIONS) 673 addElements(aRelationsList, SAL_N_ELEMENTS(aRelationsList)); 674 else if (msCurrentSetId == RID_CATEGORY_SET_OPERATIONS) 675 addElements(aSetOperations, SAL_N_ELEMENTS(aSetOperations)); 676 else if (msCurrentSetId == RID_CATEGORY_FUNCTIONS) 677 addElements(aFunctions, SAL_N_ELEMENTS(aFunctions)); 678 else if (msCurrentSetId == RID_CATEGORY_OPERATORS) 679 addElements(aOperators, SAL_N_ELEMENTS(aOperators)); 680 else if (msCurrentSetId == RID_CATEGORY_ATTRIBUTES) 681 addElements(aAttributes, SAL_N_ELEMENTS(aAttributes)); 682 else if (msCurrentSetId == RID_CATEGORY_BRACKETS) 683 addElements(aBrackets, SAL_N_ELEMENTS(aBrackets)); 684 else if (msCurrentSetId == RID_CATEGORY_FORMATS) 685 addElements(aFormats, SAL_N_ELEMENTS(aFormats)); 686 else if (msCurrentSetId == RID_CATEGORY_OTHERS) 687 addElements(aOthers, SAL_N_ELEMENTS(aOthers)); 688 else if (msCurrentSetId == RID_CATEGORY_EXAMPLES) 689 { 690 OUString aEquation = "C=%pi cdot d = 2 cdot %pi cdot r"; 691 addElement(aEquation, aEquation, ""); 692 aEquation = "E=mc^2"; 693 addElement(aEquation, aEquation, ""); 694 aEquation = "a^2 + b^2 = c^2"; 695 addElement(aEquation, aEquation, ""); 696 aEquation = "f ( x ) = sum from { { i = 0 } } to { infinity } { {f^{(i)}(0)} over {i!} x^i}"; 697 addElement(aEquation, aEquation, ""); 698 aEquation = "f ( x ) = {1} over {%sigma sqrt{2%pi} }func e^-{{(x-%mu)^2} over {2%sigma^2}}"; 699 addElement(aEquation, aEquation, ""); 700 } 701 LayoutOrPaintContents(); 702 Invalidate(); 703 } 704 705 Size SmElementsControl::GetOptimalSize() const 706 { 707 return LogicToPixel(Size(100, 100), MapMode(MapUnit::MapAppFont)); 708 } 709 710 FactoryFunction SmElementsControl::GetUITestFactory() const 711 { 712 return ElementSelectorUIObject::create; 713 } 714 715 const char* SmElementsDockingWindow::aCategories[] = { 716 RID_CATEGORY_UNARY_BINARY_OPERATORS, 717 RID_CATEGORY_RELATIONS, 718 RID_CATEGORY_SET_OPERATIONS, 719 RID_CATEGORY_FUNCTIONS, 720 RID_CATEGORY_OPERATORS, 721 RID_CATEGORY_ATTRIBUTES, 722 RID_CATEGORY_BRACKETS, 723 RID_CATEGORY_FORMATS, 724 RID_CATEGORY_OTHERS, 725 RID_CATEGORY_EXAMPLES 726 }; 727 728 SmElementsDockingWindow::SmElementsDockingWindow(SfxBindings* pInputBindings, SfxChildWindow* pChildWindow, vcl::Window* pParent) : 729 SfxDockingWindow(pInputBindings, pChildWindow, pParent, "DockingElements", 730 "modules/smath/ui/dockingelements.ui") 731 { 732 mpElementsControl = VclPtr<SmElementsControl>::Create(get<vcl::Window>("box")); 733 mpElementsControl->set_hexpand(true); 734 mpElementsControl->set_vexpand(true); 735 mpElementsControl->Show(); 736 get(mpElementListBox, "listbox"); 737 738 mpElementsControl->SetBorderStyle( WindowBorderStyle::MONO ); 739 740 mpElementListBox->SetDropDownLineCount( SAL_N_ELEMENTS(aCategories) ); 741 742 for (const char* pCategory : aCategories) 743 { 744 mpElementListBox->InsertEntry(SmResId(pCategory)); 745 } 746 747 mpElementListBox->SetSelectHdl(LINK(this, SmElementsDockingWindow, ElementSelectedHandle)); 748 mpElementListBox->SelectEntry(SmResId(RID_CATEGORY_UNARY_BINARY_OPERATORS)); 749 750 mpElementsControl->SetBackground( COL_WHITE ); 751 mpElementsControl->SetTextColor( COL_BLACK ); 752 mpElementsControl->setElementSetId(RID_CATEGORY_UNARY_BINARY_OPERATORS); 753 mpElementsControl->SetSelectHdl(LINK(this, SmElementsDockingWindow, SelectClickHandler)); 754 } 755 756 SmElementsDockingWindow::~SmElementsDockingWindow () 757 { 758 disposeOnce(); 759 } 760 761 void SmElementsDockingWindow::dispose() 762 { 763 mpElementsControl.disposeAndClear(); 764 mpElementListBox.clear(); 765 SfxDockingWindow::dispose(); 766 } 767 768 void SmElementsDockingWindow::ToggleFloatingMode() 769 { 770 SfxDockingWindow::ToggleFloatingMode(); 771 772 if (GetFloatingWindow()) 773 GetFloatingWindow()->SetMinOutputSizePixel( Size(100, 100) ); 774 775 Invalidate(); 776 } 777 778 void SmElementsDockingWindow::EndDocking( const tools::Rectangle& rReactangle, bool bFloatMode) 779 { 780 SfxDockingWindow::EndDocking(rReactangle, bFloatMode); 781 bool bVertical = ( GetAlignment() == SfxChildAlignment::TOP || GetAlignment() == SfxChildAlignment::BOTTOM ); 782 mpElementsControl->setVerticalMode(bVertical); 783 } 784 785 IMPL_LINK(SmElementsDockingWindow, SelectClickHandler, SmElement&, rElement, void) 786 { 787 SmViewShell* pViewSh = GetView(); 788 789 if (pViewSh) 790 { 791 std::unique_ptr<SfxStringItem> pInsertCommand = std::make_unique<SfxStringItem>(SID_INSERTCOMMANDTEXT, rElement.getText()); 792 pViewSh->GetViewFrame()->GetDispatcher()->ExecuteList( 793 SID_INSERTCOMMANDTEXT, SfxCallMode::RECORD, 794 { pInsertCommand.get() }); 795 } 796 } 797 798 IMPL_LINK( SmElementsDockingWindow, ElementSelectedHandle, ListBox&, rList, void) 799 { 800 for (const char* pCurrentCategory : aCategories) 801 { 802 OUString aCurrentCategoryString = SmResId(pCurrentCategory); 803 if (aCurrentCategoryString == rList.GetSelectedEntry()) 804 { 805 mpElementsControl->setElementSetId(pCurrentCategory); 806 return; 807 } 808 } 809 } 810 811 SmViewShell* SmElementsDockingWindow::GetView() 812 { 813 SfxViewShell* pView = GetBindings().GetDispatcher()->GetFrame()->GetViewShell(); 814 return dynamic_cast<SmViewShell*>( pView); 815 } 816 817 void SmElementsDockingWindow::Resize() 818 { 819 bool bVertical = ( GetAlignment() == SfxChildAlignment::TOP || GetAlignment() == SfxChildAlignment::BOTTOM ); 820 mpElementsControl->setVerticalMode(bVertical); 821 822 SfxDockingWindow::Resize(); 823 Invalidate(); 824 } 825 826 SFX_IMPL_DOCKINGWINDOW_WITHID(SmElementsDockingWindowWrapper, SID_ELEMENTSDOCKINGWINDOW); 827 828 SmElementsDockingWindowWrapper::SmElementsDockingWindowWrapper( 829 vcl::Window *pParentWindow, sal_uInt16 nId, 830 SfxBindings *pBindings, SfxChildWinInfo *pInfo) : 831 SfxChildWindow(pParentWindow, nId) 832 { 833 VclPtrInstance<SmElementsDockingWindow> pDialog(pBindings, this, pParentWindow); 834 SetWindow(pDialog); 835 pDialog->setDeferredProperties(); 836 pDialog->SetPosSizePixel(Point(0, 0), Size(300, 0)); 837 pDialog->Show(); 838 839 SetAlignment(SfxChildAlignment::LEFT); 840 841 pDialog->Initialize( pInfo ); 842 } 843 844 SmElementsDockingWindowWrapper::~SmElementsDockingWindowWrapper() 845 { 846 } 847 848 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 849
