def macro(): ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = XSCRIPTCONTEXT.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame() # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 docwindow = docframe.getContainerWindow() # ドキュメントのウィンドウを取得。 toolkit = docwindow.getToolkit() # ツールキットを取得。 taskcreator = smgr.createInstanceWithContext('com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", Rectangle(150, 150, 200, 200)), NamedValue("FrameName", "NewFrame") # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 frame = taskcreator.createInstanceWithArguments(args) # コンテナウィンドウ付きの新しいフレームの取得。 subwindow = frame.getContainerWindow() # 新しいコンテナウィンドウを新しいフレームから取得。 frame.setTitle("New Frame") # フレームのタイトルを設定。 docframe.getFrames().append(frame) # 新しく作ったフレームを既存のフレームの階層に追加する。 controlcontainer = smgr.createInstanceWithContext("com.sun.star.awt.UnoControlContainer", ctx) # コントロールコンテナを生成。 controlcontainermodel = smgr.createInstanceWithContext("com.sun.star.awt.UnoControlContainerModel", ctx) # コントールコンテナのモデルを生成。 controlcontainermodel.setPropertyValue("BackgroundColor", -1) # 背景色。-1は何色? controlcontainer.setModel(controlcontainermodel) # コントールコンテナにモデルを設定。 controlcontainer.createPeer(toolkit, subwindow) # 新しく作ったウィンドウ内にコントロールコンテナのコントロールをツールキットで描画する。 controlcontainer.setPosSize(0, 0, 200, 200, POSSIZE) # コントロールの表示座標を設定。4つ目の引数は前の引数の意味を設定する。 frame.setComponent(controlcontainer, None) # コントロールコンテナをフレームにのコンポーネントウィンドウに設定する。今回のコントローラはNone。 label = createControl(smgr, ctx, "FixedText", 10, 0, 180, 30, ("Label", "VerticalAlign"), ("Label1", BOTTOM)) # 固定文字コントールを作成。 edit = createControl(smgr, ctx, "Edit", 10, 40, 180, 30, (), ()) # 編集枠コントロールを作成。 btn = createControl(smgr, ctx, "Button", 110, 130, 80, 35, ("DefaultButton", "Label"), (True, "btn")) # ボタンコントロールを作成。 controlcontainer.addControl("label", label) # コントロールコンテナにコントロールを名前を設定して追加。 controlcontainer.addControl("btn", btn) # コントロールコンテナにコントロールを名前を設定して追加。 controlcontainer.addControl("edit", edit) # コントロールコンテナにコントロールを名前を設定して追加。 edit.setFocus() # 編集枠コントロールにフォーカスを設定する。 btn.setActionCommand("btn") # ボタンを起動した時のコマンド名を設定する。 btn.addActionListener(BtnListener(controlcontainer, subwindow)) # ボタンにリスナーを設定。コントロールの集合を渡しておく。 subwindow.setVisible(True) # 新しく作ったウィンドウを見えるようにする。execute()メソッドはないのでノンモダルダイアログにはできない。
def XSLTTransformer(stylesheet_url, source_url, source_url_base): from com.sun.star.beans import NamedValue args = (NamedValue('StylesheetURL', stylesheet_url), NamedValue('SourceURL', source_url), NamedValue('SourceBaseURL', source_url_base)) #return css.comp.documentconversion.LibXSLTTransformer(*args) return css.comp.JAXTHelper(*args)
def _get_pdf_config_access(self): """Access the PDF configuration.""" aNamedValue = NamedValue() aNamedValue.Name = "nodepath" aNamedValue.Value = "/org.openoffice.Office.Common/Filter/PDF/Export/" xConfigurationUpdateAccess = self._config.createInstanceWithArguments("com.sun.star.configuration.ConfigurationUpdateAccess", (aNamedValue,) ) return xConfigurationUpdateAccess
def test_render_named_value(self): expected = 'Nombre: Teresa\nPaís: Portugal' template = 'Nombre: $name\nPaís: $country' data = ( NamedValue('name', 'Teresa'), NamedValue('country', 'Portugal'), ) result = self.tools.render(template, data) self.assertEqual(result, expected)
def generate1(self, xmsf, layout, doc, fileAccess, targetPath, task): # a map that contains xsl templates. the keys are the xsl file names. templates = layout.getTemplates(xmsf) self.node = doc task.advance1(True, TASK_GENERATE_XSL) # each template generates a page. for key in templates: temp = templates[key] # The target file name is like the xsl template filename # without the .xsl extension. fn = fileAccess.getPath(targetPath, key[:len(key) - 4]) args = list(range(1)) nv = NamedValue() nv.Name = "StylesheetURL" nv.Value = temp args[0] = nv arguments = list(range(1)) arguments[0] = tuple(args) self.tf = Process.createTransformer(xmsf, arguments) self.node.normalize() task.advance(True) # we want to be notfied when the processing is done... self.tf.addListener( StreamListenerProcAdapter(self, self.streamTerminatedHandler, self.streamStartedHandler, self.streamClosedHandler, self.streamErrorHandler)) # create pipe pipeout = xmsf.createInstance("com.sun.star.io.Pipe") pipein = pipeout # connect sax writer to pipe self.xSaxWriter = xmsf.createInstance( "com.sun.star.xml.sax.Writer") self.xSaxWriter.setOutputStream(pipeout) # connect pipe to transformer self.tf.setInputStream(pipein) # connect transformer to output xOutputStream = fileAccess.xInterface.openFileWrite(fn) self.tf.setOutputStream(xOutputStream) self.tf.start() while (not self.tfCompleted): pass self.tf.terminate() task.advance(True)
def generate1(self, xmsf, layout, doc, fileAccess, targetPath, task): # a map that contains xsl templates. the keys are the xsl file names. templates = layout.getTemplates(xmsf) self.node = doc task.advance1(True, TASK_GENERATE_XSL) # each template generates a page. for key in templates: temp = templates[key] # The target file name is like the xsl template filename # without the .xsl extension. fn = fileAccess.getPath(targetPath, key[:len(key) - 4]) args = list(range(1)) nv = NamedValue() nv.Name = "StylesheetURL" nv.Value = temp args[0] = nv arguments = list(range(1)) arguments[0] = tuple(args) self.tf = Process.createTransformer(xmsf, arguments) self.node.normalize() task.advance(True) # we want to be notfied when the processing is done... self.tf.addListener(StreamListenerProcAdapter(self, self.streamTerminatedHandler, self.streamStartedHandler, self.streamClosedHandler, self.streamErrorHandler)) # create pipe pipeout = xmsf.createInstance("com.sun.star.io.Pipe") pipein = pipeout # connect sax writer to pipe self.xSaxWriter = xmsf.createInstance( "com.sun.star.xml.sax.Writer" ) self.xSaxWriter.setOutputStream(pipeout) # connect pipe to transformer self.tf.setInputStream(pipein) # connect transformer to output xOutputStream = fileAccess.xInterface.openFileWrite(fn) self.tf.setOutputStream(xOutputStream) self.tf.start() while (not self.tfCompleted): pass self.tf.terminate() task.advance(True)
def macro(): ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = XSCRIPTCONTEXT.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame() # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 docwindow = docframe.getContainerWindow() # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 toolkit = docwindow.getToolkit() # ピアからツールキットを取得。 taskcreator = smgr.createInstanceWithContext('com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", Rectangle(100, 100, 530, 290)), NamedValue("FrameName", "ImageControlSample") # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 frame = taskcreator.createInstanceWithArguments(args) # コンテナウィンドウ付きの新しいフレームの取得。 window = frame.getContainerWindow() # 新しいコンテナウィンドウを新しいフレームから取得。 frame.setTitle("Image Viewer") # フレームのタイトルを設定。 docframe.getFrames().append(frame) # 新しく作ったフレームを既存のフレームの階層に追加する。 actionlistener = ActionListener(ctx, smgr, frame) # ボタンにつけるリスナー。コントロールコンテナはコントロールが追加されてから取得する。 margin_horizontal = 20 # 水平マージン margin_vertical = 13 # 垂直マージン window_width = 537 # ウィンドウ幅 window_height = 287 # ウィンドウの高さ line_height = 23 # Editコントロールやボタンコントロールなどの高さ buttonfilepick_width = 56 # ButtonFilePickボタンの幅。 buttonclose_width = 90 # ButtonCloseボタンの幅。 radiobutton_width = 120 # RadioButtonの幅。 datalabel_width = 200 # FixedText2、FixedText3の幅。 minwidth = margin_horizontal*2+radiobutton_width+buttonfilepick_width+5 # Edit1の幅>=1を幅の下限値とする。 minheight = margin_vertical*5+line_height*2+1 # ImageControlの高さ>=1を高さの下限値とする。 minsizes = minwidth, minheight # コントロールが潰れてしまうと次のリサイズの計算がおかしくなるので下限値を設定する。 editcontrol_Y = window_height-(margin_vertical+line_height)*2 # Edit1のY。頻用値を取得しておく。 imagecontrolmargins = margin_horizontal*2, margin_vertical*5+line_height*2 # ウィンドウサイズの幅高さ-イメージコントロールの幅高さを取得。 itemlistener = ItemListener(toolkit, window, imagecontrolmargins) pathsubstservice = smgr.createInstanceWithContext("com.sun.star.comp.framework.PathSubstitution", ctx) uno_path = pathsubstservice.getSubstituteVariableValue("$(prog)") # fileurlでprogramフォルダへのパスが返ってくる。 fileurl = "{}/intro.png".format(uno_path) # 画像ファイルへのfileurl imageurl = os.path.normpath(unohelper.fileUrlToSystemPath(fileurl)) # fileurlをシステム固有のパスに変換して正規化する。 controlcontainer, addControl = controlcontainerCreator(ctx, smgr, {"PositionX": 0, "PositionY": 0, "Width": window_width, "Height": window_height, "BackgroundColor": 0xF0F0F0, "PosSize": POSSIZE}) # ウィンドウに表示させるコントロールコンテナを取得。BackgroundColor: -1は不可。 imagecontrol1 = addControl("ImageControl", {"PositionX": margin_horizontal, "PositionY": margin_vertical, "Width": window_width-margin_horizontal*2, "Height": window_height-margin_vertical*5-line_height*2, "Border": 0, "ScaleImage": True, "ScaleMode": ISOTROPIC, "ImageURL": fileurl, "PosSize": POSSIZE}) edit1 = addControl("Edit", {"PositionX": margin_horizontal+radiobutton_width+2, "PositionY": editcontrol_Y, "Width": window_width-margin_horizontal*2-radiobutton_width-buttonfilepick_width-4, "Height": line_height, "Text": imageurl, "PosSize": POSSIZE}) button1 = addControl("Button", {"PositionX": window_width-margin_horizontal-buttonfilepick_width, "PositionY": editcontrol_Y, "Width": buttonfilepick_width, "Height": line_height, "Label": "~Browse", "PosSize": POSSIZE}, {"setActionCommand": "filepick" ,"addActionListener": actionlistener}) # PushButtonTypeは動かない。 radiobutton1 = addControl("RadioButton", {"PositionX": margin_horizontal, "PositionY": editcontrol_Y, "Width": radiobutton_width, "Height": line_height, "Label": "~No Scaling", "PosSize": POSSIZE}, {"addItemListener": itemlistener}) radiobutton2 = addControl("RadioButton", {"PositionX": margin_horizontal, "PositionY": editcontrol_Y+line_height+int((margin_vertical*2-line_height)/3), "Width": radiobutton_width, "Height": line_height, "Label": "~ISOTROPIC", "State": 1, "PosSize": POSSIZE}, {"addItemListener": itemlistener}) radiobutton3 = addControl("RadioButton", {"PositionX": margin_horizontal, "PositionY": editcontrol_Y+(line_height+int((margin_vertical*2-line_height)/3))*2, "Width": radiobutton_width, "Height": line_height, "Label": "~ANISOTROPIC", "PosSize": POSSIZE}, {"addItemListener": itemlistener}) imagecontrolrectangle = imagecontrol1.getPosSize() graphic = imagecontrol1.getModel().getPropertyValue("Graphic") # イメージコントロールの画像を取得。 graphicrectangle = graphic.getPropertyValue("SizePixel") # 画像のオリジナルの大きさを取得。 fixedtext1 = addControl("FixedText", {"PositionX": margin_horizontal+radiobutton_width+2, "PositionY": editcontrol_Y+line_height+int((margin_vertical*2-line_height)/3), "Width": datalabel_width, "Height": line_height, "Label": "{} x {} px Image Size".format(graphicrectangle.Width, graphicrectangle.Height), "VerticalAlign": MIDDLE, "PosSize": POSSIZE}) # デフォルトでは"VerticalAlign": TOP、になっている。 fixedtext2 = addControl("FixedText", {"PositionX": margin_horizontal+radiobutton_width+2, "PositionY": editcontrol_Y+(line_height+int((margin_vertical*2-line_height)/3))*2, "Width": datalabel_width, "Height": line_height, "Label": "{} x {} px Display Size".format(imagecontrolrectangle.Width, imagecontrolrectangle.Height), "VerticalAlign": MIDDLE, "PosSize": POSSIZE}) button2 = addControl("Button", {"PositionX": window_width-margin_horizontal-buttonclose_width, "PositionY": window_height-margin_vertical-line_height, "Width": buttonclose_width, "Height": line_height, "Label": "~Close dialog", "PosSize": POSSIZE}, {"setActionCommand": "close" ,"addActionListener": actionlistener}) # PushButtonTypeは動かない。 actionlistener.setControl(imagecontrol1, edit1, fixedtext1) # getControl()で追加するコントロールが追加されてからコントロールコンテナを取得する。 radiobuttons = radiobutton1, radiobutton2, radiobutton3 itemlistener.setControl(imagecontrol1, radiobuttons) controlcontainer.createPeer(toolkit, window) # ウィンドウにコントロールを描画。 controlcontainer.setVisible(True) # コントロールの表示。 window.setVisible(True) # ウィンドウの表示 controls = controlcontainer, imagecontrol1, edit1, button1, button2, radiobutton1, radiobutton2, radiobutton3, fixedtext1, fixedtext2 window.addWindowListener(WindowListener(controls, minsizes)) # setVisible(True)でも呼び出されるので、その後でリスナーを追加する。
def _create_frame(self, ctx, smgr, ps): self.frame = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx).createInstanceWithArguments( (NamedValue('FrameName', mytools_Mri.values.MRINAME), NamedValue('PosSize', Rectangle(*ps)))) frame = self.frame self.window = frame.getContainerWindow() desktop = smgr.createInstanceWithContext( 'com.sun.star.frame.Desktop', ctx) frame.setTitle(create_window_name(desktop)) frame.setCreator(desktop) desktop.getFrames().append(frame) return frame, self.window
def XSLTTransformer(context, stylesheet_url, source_url, source_url_base): from com.sun.star.beans import NamedValue from hwp5.plat._uno.services import css args = (NamedValue('StylesheetURL', stylesheet_url), NamedValue('SourceURL', source_url), NamedValue('SourceBaseURL', source_url_base)) select = os.environ.get('PYHWP_PLAT_UNO_XSLT', 'libxslt') logger.debug('PYHWP_PLAT_UNO_XSLT = %s', select) if select == 'jaxthelper': logger.debug('%s.xslt: using css.comp.JAXTHelper', __name__) return css.comp.JAXTHelper(context, *args) else: logger.debug('%s.xslt: using %s', __name__, 'css.comp.documentconversion.LibXSLTTransformer') return css.comp.documentconversion.LibXSLTTransformer(context, *args)
def macro(): # オートメーションではリスナーが呼ばれない、閉じるボタンでウィンドウを閉じるとLibreOfficeがクラッシュする。 ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = XSCRIPTCONTEXT.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame() # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 docwindow = docframe.getContainerWindow() # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 toolkit = docwindow.getToolkit() # ツールキットを取得。 taskcreator = smgr.createInstanceWithContext('com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", Rectangle(100, 100, 500, 500)), NamedValue("FrameName", "NewFrame") # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 frame = taskcreator.createInstanceWithArguments(args) # コンテナウィンドウ付きの新しいフレームの取得。 window = frame.getContainerWindow() # 新しいコンテナウィンドウを新しいフレームから取得。 frame.setTitle("MenuBar Example") # フレームのタイトルを設定。 docframe.getFrames().append(frame) # 新しく作ったフレームを既存のフレームの階層に追加する。 createMenu = menuCreator(ctx, smgr) items = ("~First MenuBar Item", 0),\ ("~Second MenuBar Item", 0) # メニューバーの項目。 menubar = createMenu("MenuBar", items) # メニューバーの作成。 window.setMenuBar(menubar) menulistener = MenuListener(window, menubar) items = ("First Entry", CHECKABLE+AUTOCHECK, {"checkItem": True}),\ ("First Radio Entry", RADIOCHECK+AUTOCHECK, {"enableItem": False}),\ ("Second Radio Entry", RADIOCHECK+AUTOCHECK),\ ("Third Radio Entry", RADIOCHECK+AUTOCHECK, {"checkItem": True}),\ (),\ ("Fifth Entry", CHECKABLE+AUTOCHECK),\ ("Fourth Entry", CHECKABLE+AUTOCHECK, {"checkItem": True}),\ ("Sixth Entry", 0),\ ("~Close", 0, {"setCommand": "close"}) # 追加するメニュー項目。空のタプルは区切り線。 popupmenu = createMenu("PopupMenu", items, {"addMenuListener": menulistener}) # ポップアップメニューの作成。 menubar.setPopupMenu(1, popupmenu) items = ("First Entry", CHECKABLE+AUTOCHECK, {"checkItem": True}),\ ("Second Entry", 0) popupmenu = createMenu("PopupMenu", items, {"addMenuListener": menulistener}) # ポップアップメニューの作成。 menubar.setPopupMenu(2, popupmenu) controlcontainer, addControl = controlcontainerCreator(ctx, smgr, {"PositionX": 0, "PositionY": 0, "Width": 500, "Height": 500, "PosSize": POSSIZE}) # ウィンドウに表示させるコントロールコンテナを取得。 addControl("FixedText", {"PositionX": 20, "PositionY": 20, "Width": 460, "Height": 460, "PosSize": POSSIZE, "Label": "\n".join(getStatus(menubar)), "NoLabel": True, "MultiLine": True}) menulistener.control = controlcontainer.getControl("FixedText1") # メニューリスナーにFiexedTextコントロールを渡す。 controlcontainer.createPeer(toolkit, window) # ウィンドウにコントロールを描画。 controlcontainer.setVisible(True) # コントロールの表示。 window.setVisible(True) # ウィンドウの表示。
def macro(): ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = XSCRIPTCONTEXT.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame() # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 docwindow = docframe.getContainerWindow() # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 toolkit = docwindow.getToolkit() # ピアからツールキットを取得。 taskcreator = smgr.createInstanceWithContext('com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", Rectangle(100, 100, 530, 290)), NamedValue("FrameName", "ImageControlSample") # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 frame = taskcreator.createInstanceWithArguments(args) # コンテナウィンドウ付きの新しいフレームの取得。 window = frame.getContainerWindow() # 新しいコンテナウィンドウを新しいフレームから取得。 frame.setTitle("Image Control Sample") # フレームのタイトルを設定。 docframe.getFrames().append(frame) # 新しく作ったフレームを既存のフレームの階層に追加する。 actionlistener = ActionListener(ctx, smgr, frame) # ボタンにつけるリスナー。コントロールコンテナはコントロールが追加されてから取得する。 margin_horizontal = 20 # 水平マージン margin_vertical = 13 # 垂直マージン window_width = 537 # ウィンドウ幅 window_height = 287 # ウィンドウの高さ headerlabel_height = 36 # Headerlabelの高さ。 line_height = 23 # Editコントロールやボタンコントロールの高さ buttonfilepick_width = 56 # ButtonFilePickボタンの幅。 buttonclose_width = 114 # ButtonCloseボタンの幅。 consts = margin_horizontal, margin_vertical, headerlabel_height, line_height, buttonfilepick_width, buttonclose_width # リスナーに渡す用。 pathsubstservice = smgr.createInstanceWithContext("com.sun.star.comp.framework.PathSubstitution", ctx) uno_path = pathsubstservice.getSubstituteVariableValue("$(prog)") # fileurlでprogramフォルダへのパスが返ってくる。 fileurl = "{}/intro.png".format(uno_path) # 画像ファイルへのfileurl imageurl = os.path.normpath(unohelper.fileUrlToSystemPath(fileurl)) # fileurlをシステム固有のパスに変換して正規化する。 controlcontainer, addControl = controlcontainerCreator(ctx, smgr, {"PositionX": 0, "PositionY": 0, "Width": window_width, "Height": window_height, "BackgroundColor": 0xF0F0F0, "PosSize": POSSIZE}) # ウィンドウに表示させるコントロールコンテナを取得。BackgroundColor: -1は透過色のもよう。 fixedtext1 = addControl("FixedText", {"PositionX": margin_horizontal, "PositionY": margin_vertical, "Width": window_width-margin_horizontal*2, "Height": headerlabel_height, "Label": "This code-sample demonstrates how to create an ImageControlSample within a dialog.", "MultiLine": True, "PosSize": POSSIZE}) imagecontrol1 = addControl("ImageControl", {"PositionX": margin_horizontal, "PositionY": margin_vertical*2+headerlabel_height, "Width": window_width-margin_horizontal*2, "Height": window_height-margin_vertical*5-line_height*2-headerlabel_height, "Border": 0, "ScaleImage": True, "ScaleMode": ISOTROPIC, "ImageURL": fileurl, "PosSize": POSSIZE}) # "ScaleImage": Trueで画像が歪む。 edit1 = addControl("Edit", {"PositionX": margin_horizontal, "PositionY": window_height-margin_vertical*2-line_height*2, "Width": window_width-margin_horizontal*2-buttonfilepick_width-2, "Height": line_height, "Text": imageurl, "PosSize": POSSIZE}) button1 = addControl("Button", {"PositionX": window_width-margin_horizontal-buttonfilepick_width, "PositionY": window_height-margin_vertical*2-line_height*2, "Width": buttonfilepick_width, "Height": line_height, "Label": "~Browse", "PosSize": POSSIZE}, {"setActionCommand": "filepick" ,"addActionListener": actionlistener}) # PushButtonTypeの値はEnumではエラーになる。 button2 = addControl("Button", {"PositionX": (window_width-buttonclose_width)/2, "PositionY": window_height-margin_vertical-line_height, "Width": buttonclose_width, "Height": line_height, "Label": "~Close dialog", "PosSize": POSSIZE}, {"setActionCommand": "close" ,"addActionListener": actionlistener}) # PushButtonTypeは動かない。 actionlistener.setControl(imagecontrol1, edit1) # getControl()で追加するコントロールが追加されてからコントロールコンテナを取得する。 controlcontainer.createPeer(toolkit, window) # ウィンドウにコントロールを描画。 controlcontainer.setVisible(True) # コントロールの表示。 window.setVisible(True) # ウィンドウの表示。 controls = controlcontainer, fixedtext1, imagecontrol1, edit1, button1, button2 window.addWindowListener(WindowListener(controls, consts)) # setVisible(True)でも呼び出されるので、その後で実行する。
def _insert_page(title, page_id, name, help_url, pos): if tab_type == 1: _page_model = tab_model.createTabPage(page_id) _page_model.Title = title _page_index = tab_model.getCount() tab_model.insertByIndex(_page_index, _page_model) else: # LibreOffice kind _page_model = tab_model.createInstance( "com.sun.star.awt.UnoPageModel") tab_model.insertByName("page_%s" % pos, _page_model) tab.setTabProps(pos + 1, (NamedValue("Title", title), )) _page_index = pos _page = tab.getControls()[_page_index] if use_grid: from mytools_Mri.ui.grid import _create_grid2 ctrl = _create_grid2(ctx, smgr, _page, name, help_url, pos, grid_type) else: from mytools_Mri.ui.frame import _create_edit2 ctrl = _create_edit2(_page, name, help_url) ctrl.setPosSize(0, 0, width, inner_ps.Height, PS_POSSIZE) return ctrl
def createDialog(xscriptcontext ): # 選択範囲を削除して、フレームを変更するとマウスボタン押してドラッグしている状態になったままになっている。 traceback.print_exc() # PyDevのコンソールにトレースバックを表示。stderrToServer=Trueが必須。 # ダイアログに表示する。raiseだとPythonの構文エラーはエラーダイアログがでてこないので。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 maTopx = dialogcommons.createConverters( containerwindow) # ma単位をピクセルに変換する関数を取得。 txt = traceback.format_exc() lines = txt.split("\n") # トレースバックを改行で分割。 h = 20 # FixedTextコントロールの高さ。ma単位。2行分。 dialogwidth = 380 # ウィンドウの幅。ma単位。 controlcontainerprops = { "PositionX": 20, "PositionY": 120, "Width": dialogwidth, "Height": 10, "BackgroundColor": 0xF0F0F0 } # Heightは後で設定し直す。PositionXとPositionYはTaskCreatorに渡したら0にする。 controlcontainer, addControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 mouselistener = MouseListener(xscriptcontext) controlheight = 0 # コントロールの高さ。ma単位。 subjs = [] # マウスリスナーのサブジェクトのリスト。 for i in lines[1:]: # 2行目以降イテレート。 if i: # 空行は除外。 fixedtextprops = [{ "PositionX": 0, "PositionY": controlheight, "Width": dialogwidth, "Height": h, "Label": i, "MultiLine": True, "NoLabel": True, "VerticalAlign": MIDDLE }] if i.lstrip().startswith("File "): # File から始まる行の時。 fixedtextprops[0]["TextColor"] = 0x0000FF # 文字色をblue3にする。 fixedtextprops.append({"addMouseListener": mouselistener}) fixedtextcontrol = addControl("FixedText", *fixedtextprops) subjs.append(fixedtextcontrol) # マウスリスナーをつけたコントロールに追加する。 elif not i.startswith(" "): # スペース以外から始まる時。 fixedtextprops[0]["TextColor"] = 0xFF0000 # 文字色をred3にする。 fixedtextcontrol = addControl("FixedText", *fixedtextprops) else: fixedtextcontrol = addControl("FixedText", *fixedtextprops) controlheight += h buttonprops1 = { "PositionX": 10, "PositionY": controlheight, "Width": 60, "Height": 14, "Label": "to ClipBoard" } # ボタンのプロパティ。PushButtonTypeの値はEnumではエラーになる。VerticalAlignではtextboxと高さが揃わない。 actionlistener = ActionListener(xscriptcontext, txt) # ボタンコントロールにつけるリスナー。 button1 = addControl("Button", buttonprops1, { "addActionListener": actionlistener, "setActionCommand": "copy" }) controlrectangle = button1.getPosSize( ) # コントロール間の間隔を幅はX、高さはYから取得。最後に追加したコントロールから取得。 controlcontainer.setPosSize(0, 0, 0, controlrectangle.Y + controlrectangle.Height + 10, PosSize.HEIGHT) # 最後の行からダイアログの高さを再設定。 rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 controlcontainer.setPosSize( 0, 0, 0, 0, PosSize.POS) # コントロールコンテナの位置をTaskCreatorのウィンドウの原点にする。 taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "exceptiondialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。サイズ変更は想定しない。 dialogframe.setTitle(lines[0]) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 toolkit = dialogwindow.getToolkit() # ピアからツールキットを取得。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールコンテナを描画。 controlcontainer.setVisible(True) # コントロールの表示。 dialogwindow.setVisible(True) # ウィンドウの表示。これ以降WindowListenerが発火する。 args = mouselistener, actionlistener, button1, subjs dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。
def createDialog( xscriptcontext, dialogtitle, defaultrows=None, outputcolumn=None, *, enhancedmouseevent=None, callback=None ): # dialogtitleはダイアログのデータ保存名に使うのでユニークでないといけない。defaultrowsはグリッドコントロールのデフォルトデータ。 items = ("選択行を削除", 0, {"setCommand": "delete"}),\ ("全行を削除", 0, {"setCommand": "deleteall"}),\ (),\ ("セル入力で閉じる", MenuItemStyle.CHECKABLE+MenuItemStyle.AUTOCHECK, {"checkItem": True}),\ ("オプション表示", MenuItemStyle.CHECKABLE+MenuItemStyle.AUTOCHECK, {"checkItem": False}) # グリッドコントロールにつける右クリックメニュー。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 controller = doc.getCurrentController() docframe = controller.getFrame() # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 maTopx = dialogcommons.createConverters( containerwindow) # ma単位をピクセルに変換する関数を取得。 m = 2 # コントロール間の間隔。 h = 12 # コントロール間の高さ。 txt = doc.getCurrentSelection().getString() # 選択セルの文字列を取得。 XWidth, YHeight = dialogcommons.XWidth, dialogcommons.YHeight gridprops = { "PositionX": 0, "PositionY": 0, "Width": 50, "Height": 50, "ShowRowHeader": False, "ShowColumnHeader": False, "SelectionModel": MULTI } # グリッドコントロールのプロパティ。 controlcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(gridprops), "Height": YHeight(gridprops), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。 controlcontainer, addControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 mousemotionlistener = dialogcommons.MouseMotionListener( ) # グリッドコントロールにつけるマウスが動くと発火するリスナー。 menulistener = MenuListener( mousemotionlistener ) # コンテクストメニューにつけるリスナー。mousemotionlistenerはグリッドコントロールにつけるもの。 gridpopupmenu = dialogcommons.menuCreator(ctx, smgr)( "PopupMenu", items, { "addMenuListener": menulistener, "hideDisabledEntries": False }) # 右クリックでまず呼び出すポップアップメニュー。hideDisabledEntries()が反応しない。 args = gridpopupmenu, xscriptcontext, outputcolumn, callback # gridpopupmenuは先頭でないといけない。 mouselistener = MouseListener(args) gridcontrol1 = addControl( "Grid", gridprops, { "addMouseListener": mouselistener, "addMouseMotionListener": mousemotionlistener }) # グリッドコントロールの取得。 gridmodel = gridcontrol1.getModel() # グリッドコントロールモデルの取得。 gridcolumn = gridmodel.getPropertyValue( "ColumnModel") # DefaultGridColumnModel gridcolumn.addColumn(gridcolumn.createColumn()) # 列を追加。 griddatamodel = gridmodel.getPropertyValue( "GridDataModel") # GridDataModel datarows = dialogcommons.getSavedData(doc, "GridDatarows_{}".format( dialogtitle)) # グリッドコントロールの行をconfigシートのragenameから取得する。 if datarows is None and defaultrows is not None: # 履歴がなくデフォルトdatarowsがあるときデフォルトデータを使用。 datarows = [ i if isinstance(i, (list, tuple)) else (i, ) for i in defaultrows ] # defaultrowsの要素をリストかタプルでなければタプルに変換する。 if datarows: # 行のリストが取得出来た時。 griddatamodel.addRows(("", ) * len(datarows), datarows) # グリッドに行を追加。 else: datarows = [] # Noneのままではあとで処理できないので空リストを入れる。 global DATAROWS DATAROWS = datarows # マクロの起動中グローバル変数は保持されるので毎回リセットしないといけない。 controlcontainerwindowlistener = ControlContainerWindowListener( controlcontainer) controlcontainer.addWindowListener( controlcontainerwindowlistener ) # コントロールコンテナの大きさを変更するとグリッドコントロールの大きさも変更するようにする。 textboxprops = { "PositionX": 0, "PositionY": m, "Height": h, "Text": txt } # テクストボックスコントロールのプロパティ。 checkboxprops = { "PositionY": YHeight(textboxprops, m), "Height": h, "Tabstop": False } # チェックボックスコントロールのプロパティ。 checkboxprops1, checkboxprops2 = [ checkboxprops.copy() for dummy in range(2) ] checkboxprops1.update({ "PositionX": 0, "Width": 42, "Label": "~サイズ復元", "State": 1 }) # サイズ復元はデフォルトでは有効。 checkboxprops2.update({ "PositionX": XWidth(checkboxprops1), "Width": 38, "Label": "~逐次検索", "State": 0 }) # 逐次検索はデフォルトでは無効。 buttonprops = { "PositionX": XWidth(checkboxprops2), "PositionY": YHeight(textboxprops, 4), "Width": 30, "Height": h + 2, "Label": "New" } # ボタンのプロパティ。PushButtonTypeの値はEnumではエラーになる。VerticalAlignではtextboxと高さが揃わない。 textboxprops.update({"Width": XWidth(buttonprops)}) optioncontrolcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(textboxprops), "Height": YHeight(buttonprops, 2), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 optioncontrolcontainer, optionaddControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, optioncontrolcontainerprops) # コントロールコンテナの作成。 textlistener = TextListener(xscriptcontext, controlcontainer) optionaddControl("Edit", textboxprops, {"addTextListener": textlistener}) checkboxcontrol1 = optionaddControl("CheckBox", checkboxprops1) itemlistener = ItemListener(controlcontainer) checkboxcontrol2 = optionaddControl("CheckBox", checkboxprops2, {"addItemListener": itemlistener}) args = xscriptcontext, controlcontainer actionlistener = ActionListener(args) # ボタンコントロールにつけるリスナー。 optionaddControl("Button", buttonprops, { "addActionListener": actionlistener, "setActionCommand": "enter" }) optioncontrolcontainerwindowlistener = OptionControlContainerWindowListener( optioncontrolcontainer) optioncontrolcontainer.addWindowListener( optioncontrolcontainerwindowlistener ) # コントロールコンテナの大きさを変更するとグリッドコントロールの大きさも変更するようにする。 mouselistener.optioncontrolcontainer = optioncontrolcontainer rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 if enhancedmouseevent is None: visibleareaonscreen = controller.getPropertyValue( "VisibleAreaOnScreen") rectangle.X, rectangle.Y = visibleareaonscreen.X, visibleareaonscreen.Y else: dialogpoint = dialogcommons.getDialogPoint( doc, enhancedmouseevent ) # クリックした位置のメニューバーの高さ分下の位置を取得。単位ピクセル。一部しか表示されていないセルのときはNoneが返る。 if not dialogpoint: # クリックした位置が取得出来なかった時は何もしない。 return rectangle.X, rectangle.Y = dialogpoint # クリックした位置を取得。ウィンドウタイトルを含めない座標。 taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "controldialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。 mouselistener.dialogframe = dialogframe dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 dialogframe.setTitle(dialogtitle) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 toolkit = dialogwindow.getToolkit() # ピアからツールキットを取得。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールコンテナを描画。 optioncontrolcontainer.createPeer( toolkit, dialogwindow) # ウィンドウにオプションコントロールコンテナを描画。Visibleにはしない。 frameactionlistener = dialogcommons.FrameActionListener( ) # FrameActionListener。フレームがアクティブでなくなった時に閉じるため。 dialogframe.addFrameActionListener( frameactionlistener) # FrameActionListenerをダイアログフレームに追加。 controlcontainer.setVisible(True) # コントロールの表示。 dialogwindow.setVisible(True) # ウィンドウの表示。これ以降WindowListenerが発火する。 windowlistener = WindowListener( controlcontainer, optioncontrolcontainer ) # コンテナウィンドウからコントロールコンテナを取得する方法はないはずなので、ここで渡す。WindowListenerはsetVisible(True)で呼び出される。 dialogwindow.addWindowListener(windowlistener) # コンテナウィンドウにリスナーを追加する。 menulistener.args = dialogwindow, windowlistener, mouselistener dialogstate = dialogcommons.getSavedData( doc, "dialogstate_{}".format(dialogtitle) ) # 保存データを取得。optioncontrolcontainerの表示状態は常にFalseなので保存されていない。 if dialogstate is not None: # 保存してあるダイアログの状態がある時。 for menuid in range(1, gridpopupmenu.getItemCount() + 1): # ポップアップメニューを走査する。 itemtext = gridpopupmenu.getItemText( menuid) # 文字列にはショートカットキーがついてくる。 if itemtext.startswith("セル入力で閉じる"): closecheck = dialogstate.get( "CloseCheck") # 保存してある、セル入力で閉じる、のチェックの状態を取得。 if closecheck is not None: gridpopupmenu.checkItem(menuid, closecheck) elif itemtext.startswith("オプション表示"): optioncheck = dialogstate.get( "OptionCheck") # 保存してある、オプション表示、のチェックの状態を取得。 if optioncheck is not None: gridpopupmenu.checkItem( menuid, optioncheck) # ItemIDは1から始まる。これでMenuListenerは発火しない。 if optioncheck: # チェックが付いている時MenuListenerを発火させる。 gridcontrol1.removeMouseMotionListener( mousemotionlistener) # オプション表示している時は行のハイライトはしない。 menulistener.itemSelected( MenuEvent(MenuId=menuid, Source=mouselistener.gridpopupmenu)) checkbox1sate = dialogstate.get( "CheckBox1sate") # サイズ復元、チェックボックス。キーがなければNoneが返る。 if checkbox1sate is not None: # サイズ復元、が保存されている時。 if checkbox1sate: # サイズ復元がチェックされている時。 dialogwindow.setPosSize(0, 0, dialogstate["Width"], dialogstate["Height"], PosSize.SIZE) # ウィンドウサイズを復元。 checkboxcontrol1.setState(checkbox1sate) # 状態を復元。 checkbox2sate = dialogstate.get("CheckBox2sate") # 逐語検索、チェックボックス。 if checkbox2sate is not None: # 逐語検索、が保存されている時。 if checkbox2sate: # チェックされている時逐次検索を有効にする。 refreshRows(gridcontrol1, [i for i in DATAROWS if i[0].startswith(txt) ]) # txtで始まっている行だけに絞る。txtが空文字の時はすべてTrueになる。 checkboxcontrol2.setState(checkbox2sate) # itemlistenerは発火しない。 args = doc, actionlistener, dialogwindow, windowlistener, mouselistener, menulistener, textlistener, itemlistener, controlcontainerwindowlistener, optioncontrolcontainerwindowlistener, mousemotionlistener dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。 scrollDown(gridcontrol1)
def createDialog( xscriptcontext, enhancedmouseevent, dialogtitle, formatstring=None ): # dialogtitleはダイアログのデータ保存名に使うのでユニークでないといけない。formatstringは代入セルの書式。 dateformat = "%Y/%m/%d(%a)" # 日付書式。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 dialogpoint = getDialogPoint( doc, enhancedmouseevent ) # クリックした位置のメニューバーの高さ分下の位置を取得。単位ピクセル。一部しか表示されていないセルのときはNoneが返る。 if not dialogpoint: # クリックした位置が取得出来なかった時は何もしない。 return docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 maTopx = createConverters(containerwindow) # ma単位をピクセルに変換する関数を取得。 m = 2 # コントロール間の間隔。 h = 12 # コントロールの高さ gridprops = { "PositionX": 0, "PositionY": 0, "Width": 76, "Height": 73, "ShowRowHeader": False, "ShowColumnHeader": False, "VScroll": False, "SelectionModel": SINGLE } # グリッドコントロールのプロパティ。 controlcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(gridprops), "Height": YHeight(gridprops), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 optioncontrolcontainerprops = controlcontainerprops.copy() controlcontainer, addControl = controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 items = ("セル入力で閉じる", MenuItemStyle.CHECKABLE + MenuItemStyle.AUTOCHECK, { "checkItem": True }), # グリッドコントロールのコンテクストメニュー。XMenuListenerのmenuevent.MenuIdでコードを実行する。 gridpopupmenu = menuCreator(ctx, smgr)("PopupMenu", items) # 右クリックでまず呼び出すポップアップメニュー。 args = xscriptcontext, dateformat, formatstring mouselistener = MouseListener(gridpopupmenu, args) gridcontrolwidth = gridprops[ "Width"] # gridpropsは消費されるので、グリッドコントロールの幅を取得しておく。 gridcontrol1 = addControl( "Grid", gridprops, {"addMouseListener": mouselistener}) # グリッドコントロールの取得。 gridcolumn = gridcontrol1.getModel().getPropertyValue( "ColumnModel") # DefaultGridColumnModel column0 = gridcolumn.createColumn() # 列の作成。 column0.ColumnWidth = 25 # 列幅。 gridcolumn.addColumn(column0) # 1列目を追加。 column1 = gridcolumn.createColumn() # 列の作成。 column1.ColumnWidth = gridcontrolwidth - column0.ColumnWidth # 列幅。列の合計がグリッドコントロールの幅に一致するようにする。 gridcolumn.addColumn(column1) # 2列目を追加。 numericfieldprops1 = { "PositionY": m, "Width": 24, "Height": h + 2, "Spin": True, "StrictFormat": True, "Value": 0, "ValueStep": 1, "ShowThousandsSeparator": False, "DecimalAccuracy": 0 } fixedtextprops1 = { "PositionY": m, "Width": 14, "Height": h, "Label": "週後", "VerticalAlign": MIDDLE } fixedtextprops1.update( {"PositionX": gridcontrolwidth - fixedtextprops1["Width"]}) numericfieldprops1.update({ "PositionX": fixedtextprops1["PositionX"] - numericfieldprops1["Width"] }) optioncontrolcontainerprops.update({ "PositionY": YHeight(optioncontrolcontainerprops), "Height": YHeight(numericfieldprops1, m) }) optioncontrolcontainer, optionaddControl = controlcontainerMaCreator( ctx, smgr, maTopx, optioncontrolcontainerprops) # コントロールコンテナの作成。 textlistener = TextListener(dateformat, gridcontrol1) numericfield1 = optionaddControl("NumericField", numericfieldprops1, {"addTextListener": textlistener}) optionaddControl("FixedText", fixedtextprops1) rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 rectangle.X, rectangle.Y = dialogpoint # クリックした位置を取得。ウィンドウタイトルを含めない座標。 rectangle.Height += optioncontrolcontainer.getSize().Height taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "controldialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。サイズ変更は想定しない。 mouselistener.dialogframe = dialogframe dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 dialogframe.setTitle(dialogtitle) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 toolkit = dialogwindow.getToolkit() # ピアからツールキットを取得。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールコンテナを描画。 optioncontrolcontainer.createPeer( toolkit, dialogwindow) # ウィンドウにオプションコントロールコンテナを描画。Visibleにはしない。 frameactionlistener = FrameActionListener( ) # FrameActionListener。フレームがアクティブでなくなった時に閉じるため。 dialogframe.addFrameActionListener( frameactionlistener) # FrameActionListenerをダイアログフレームに追加。 controlcontainer.setVisible(True) # コントロールの表示。 optioncontrolcontainer.setVisible(True) dialogwindow.setVisible(True) # ウィンドウの表示。これ以降WindowListenerが発火する。 numericfield1.setFocus() todayindex = 7 // 2 # 今日の日付の位置を決定。切り下げ。 col0 = [""] * 7 # 全てに空文字を挿入。 cellvalue = enhancedmouseevent.Target.getValue() # セルの値を取得。 centerday = None if cellvalue and isinstance(cellvalue, float): # セルの値がfloat型のとき。datevalueと決めつける。 functionaccess = smgr.createInstanceWithContext( "com.sun.star.sheet.FunctionAccess", ctx) # シート関数利用のため。 if cellvalue != functionaccess.callFunction("TODAY", ()): # セルの数値が今日でない時。 centerday = date(*[ int(functionaccess.callFunction(i, (cellvalue, ))) for i in ("YEAR", "MONTH", "DAY") ]) # シリアル値をシート関数で年、月、日に変換してdateオブジェクトにする。 col0[todayindex] = "基準日" if centerday is None: centerday = date.today() col0[todayindex - 1:todayindex + 2] = "昨日", "今日", "明日" # 列インデックス0に入れる文字列を取得。 addDays(gridcontrol1, dateformat, centerday, col0) # グリッドコントロールに行を入れる。 dialogstate = getSavedData( doc, "dialogstate_{}".format(dialogtitle) ) # 保存データを取得。optioncontrolcontainerの表示状態は常にFalseなので保存されていない。 if dialogstate is not None: # 保存してあるダイアログの状態がある時。 for menuid in range(1, gridpopupmenu.getItemCount() + 1): # ポップアップメニューを走査する。 itemtext = gridpopupmenu.getItemText( menuid) # 文字列にはショートカットキーがついてくる。 if itemtext.startswith("セル入力で閉じる"): closecheck = dialogstate.get( "CloseCheck") # セル入力で閉じる、のチェックがある時。 if closecheck is not None: gridpopupmenu.checkItem(menuid, closecheck) args = doc, mouselistener, controlcontainer dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。
def createDialog( xscriptcontext, enhancedmouseevent, dialogtitle, defaultrows=None ): # dialogtitleはダイアログのデータ保存名に使うのでユニークでないといけない。defaultrowsはグリッドコントロールのデフォルトデータ。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 dialogpoint = getDialogPoint( doc, enhancedmouseevent ) # クリックした位置のメニューバーの高さ分下の位置を取得。単位ピクセル。一部しか表示されていないセルのときはNoneが返る。 if not dialogpoint: # クリックした位置が取得出来なかった時は何もしない。 return txt = doc.getCurrentSelection().getString() # 選択セルの文字列を取得。 docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 toolkit = containerwindow.getToolkit() # ピアからツールキットを取得。 m = 2 # コントロール間の間隔。 h = 12 # コントロール間の高さ。 gridprops = { "PositionX": 0, "PositionY": 0, "Height": 50, "ShowRowHeader": False, "ShowColumnHeader": False, "SelectionModel": MULTI } # グリッドコントロールのプロパティ。 textboxprops = { "PositionX": 0, "PositionY": YHeight(gridprops, 2), "Height": h, "Text": txt } # テクストボックスコントロールのプロパティ。 checkboxprops = { "PositionY": YHeight(textboxprops, m), "Height": h, "Tabstop": False } # チェックボックスコントロールのプロパティ。 checkboxprops1, checkboxprops2 = [ checkboxprops.copy() for dummy in range(2) ] checkboxprops1.update({ "PositionX": 0, "Width": 42, "Label": "~サイズ復元", "State": 1 }) # サイズ復元はデフォルトでは有効。 checkboxprops2.update({ "PositionX": XWidth(checkboxprops1), "Width": 38, "Label": "~逐次検索", "State": 0 }) # 逐次検索はデフォルトでは無効。 buttonprops = { "PositionX": XWidth(checkboxprops2), "PositionY": YHeight(textboxprops, 4), "Width": 30, "Height": h + 2, "Label": "Enter" } # ボタンのプロパティ。PushButtonTypeの値はEnumではエラーになる。VerticalAlignではtextboxと高さが揃わない。 gridprops["Width"] = textboxprops["Width"] = XWidth(buttonprops) controlcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(gridprops), "Height": YHeight(buttonprops, m), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 maTopx = createConverters(containerwindow) # ma単位をピクセルに変換する関数を取得。 controlcontainer, addControl = controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 mouselistener = MouseListener(xscriptcontext) menulistener = MenuListener(controlcontainer) # コンテクストメニューにつけるリスナー。 actionlistener = ActionListener(xscriptcontext) # ボタンコントロールにつけるリスナー。 items = ("選択行を削除", 0, {"setCommand": "delete"}),\ ("全行を削除", 0, {"setCommand": "deleteall"}) # グリッドコントロールにつける右クリックメニュー。 mouselistener.gridpopupmenu = menuCreator(ctx, smgr)( "PopupMenu", items, { "addMenuListener": menulistener }) # 右クリックでまず呼び出すポップアップメニュー。 gridcontrol1 = addControl("Grid", gridprops, {"addMouseListener": mouselistener }) # グリッドコントロールの取得。gridは他のコントロールの設定に使うのでコピーを渡す。 gridmodel = gridcontrol1.getModel() # グリッドコントロールモデルの取得。 gridcolumn = gridmodel.getPropertyValue( "ColumnModel") # DefaultGridColumnModel gridcolumn.addColumn(gridcolumn.createColumn()) # 列を追加。 griddatamodel = gridmodel.getPropertyValue( "GridDataModel") # GridDataModel datarows = getSavedData(doc, "GridDatarows_{}".format( dialogtitle)) # グリッドコントロールの行をconfigシートのragenameから取得する。 if datarows is None and defaultrows is not None: # 履歴がなくデフォルトdatarowsがあるときデフォルトデータを使用。 datarows = [ i if isinstance(i, (list, tuple)) else (i, ) for i in defaultrows ] # defaultrowsの要素をリストかタプルでなければタプルに変換する。 if datarows: # 行のリストが取得出来た時。 griddatamodel.addRows(("", ) * len(datarows), datarows) # グリッドに行を追加。 global DATAROWS DATAROWS = datarows # グリッドのデータをDATAROWSに反映。 textlistener = TextListener(xscriptcontext) addControl("Edit", textboxprops, {"addTextListener": textlistener}) checkboxcontrol1 = addControl("CheckBox", checkboxprops1) itemlistener = ItemListener(textlistener) checkboxcontrol2 = addControl("CheckBox", checkboxprops2, {"addItemListener": itemlistener}) addControl("Button", buttonprops, { "addActionListener": actionlistener, "setActionCommand": "enter" }) rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 rectangle.X, rectangle.Y = dialogpoint # クリックした位置を取得。ウィンドウタイトルを含めない座標。 taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "controldialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。 dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 dialogframe.setTitle(dialogtitle) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールを描画。 dialogframe.addFrameActionListener(FrameActionListener( )) # FrameActionListenerをダイアログフレームに追加。リスナーはフレームを閉じる時に削除するようにしている。 windowlistener = WindowListener(controlcontainer) dialogwindow.addWindowListener(windowlistener) # setVisible(True)でも呼び出される。 args = doc, controlcontainer, actionlistener, dialogwindow, windowlistener, mouselistener, menulistener, textlistener, itemlistener dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。 controlcontainer.setVisible(True) # コントロールの表示。 dialogwindow.setVisible(True) # ウィンドウの表示。ここでウィンドウリスナーが発火する。 dialogstate = getSavedData( doc, "dialogstate_{}".format(dialogtitle)) # 保存データを取得。 if dialogstate is not None: # 保存してあるダイアログの状態がある時。 checkbox1sate = dialogstate.get( "CheckBox1sate") # サイズ復元、チェックボックス。キーがなければNoneが返る。 if checkbox1sate is not None: # サイズ復元、が保存されている時。 if checkbox1sate: # サイズ復元がチェックされている時。 dialogwindow.setPosSize(0, 0, dialogstate["Width"], dialogstate["Height"], PosSize.SIZE) # ウィンドウサイズを復元。 checkboxcontrol1.setState(checkbox1sate) # 状態を復元。 checkbox2sate = dialogstate.get("CheckBox2sate") # 逐語検索、チェックボックス。 if checkbox2sate is not None: # 逐語検索、が保存されている時。 if checkbox2sate: # チェックされている時逐次検索を有効にする。 refreshRows(gridcontrol1, [i for i in DATAROWS if i[0].startswith(txt) ]) # txtで始まっている行だけに絞る。txtが空文字の時はすべてTrueになる。 checkboxcontrol2.setState(checkbox2sate) # itemlistenerは発火しない。 scrollDown(gridcontrol1)
def createDialog( xscriptcontext, dialogtitle, defaultrows, *, enhancedmouseevent=None, callback=None ): # dialogtitleはダイアログのデータ保存名に使うのでユニークでないといけない。defaultrowsはグリッドコントロールのデフォルトデータ。 items = ("オプション表示", MenuItemStyle.CHECKABLE + MenuItemStyle.AUTOCHECK, { "checkItem": False }), # グリッドコントロールのコンテクストメニュー。XMenuListenerのmenuevent.MenuIdでコードを実行する。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 maTopx = dialogcommons.createConverters( containerwindow) # ma単位をピクセルに変換する関数を取得。 m = 2 # コントロール間の間隔。 h = 12 # コントロールの高さ XWidth, YHeight = dialogcommons.XWidth, dialogcommons.YHeight gridprops = { "PositionX": 0, "PositionY": 0, "Width": 50, "Height": 50, "ShowRowHeader": False, "ShowColumnHeader": False } # グリッドコントロールのプロパティ。 controlcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(gridprops), "Height": YHeight(gridprops), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 controlcontainer, addControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 mousemotionlistener = dialogcommons.MouseMotionListener() menulistener = MenuListener(mousemotionlistener) # コンテクストメニューにつけるリスナー。 gridpopupmenu = dialogcommons.menuCreator(ctx, smgr)( "PopupMenu", items, { "addMenuListener": menulistener, "hideDisabledEntries": False }) # 右クリックでまず呼び出すポップアップメニュー。hideDisabledEntries()が反応しない。 args = gridpopupmenu, xscriptcontext, callback # gridpopupmenuは先頭でないといけない。 mouselistener = MouseListener(args) gridcontrol1 = addControl( "Grid", gridprops, { "addMouseListener": mouselistener, "addMouseMotionListener": mousemotionlistener }) # グリッドコントロールの取得。 gridmodel = gridcontrol1.getModel() # グリッドコントロールモデルの取得。 gridcolumn = gridmodel.getPropertyValue( "ColumnModel") # DefaultGridColumnModel gridcolumn.addColumn(gridcolumn.createColumn()) # 列を追加。 griddatamodel = gridmodel.getPropertyValue( "GridDataModel") # GridDataModel if defaultrows is not None: # デフォルトdatarowsがあるときデフォルトデータを使用。 datarows = [ i if isinstance(i, (list, tuple)) else (i, ) for i in defaultrows ] # defaultrowsの要素をリストかタプルでなければタプルに変換する。 griddatamodel.addRows(("", ) * len(datarows), datarows) # グリッドに行を追加。 else: datarows = [] # Noneのままではあとで処理できないので空リストを入れる。 controlcontainerwindowlistener = ControlContainerWindowListener( controlcontainer) controlcontainer.addWindowListener( controlcontainerwindowlistener ) # コントロールコンテナの大きさを変更するとグリッドコントロールの大きさも変更するようにする。 checkboxprops1 = { "PositionX": 0, "PositionY": m, "Width": 46, "Height": h, "Label": "~サイズ復元", "State": 1 } # サイズ復元はデフォルトでは有効。 optioncontrolcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(checkboxprops1), "Height": YHeight(checkboxprops1, 2), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 optioncontrolcontainer, optionaddControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, optioncontrolcontainerprops) # コントロールコンテナの作成。 checkboxcontrol2 = optionaddControl("CheckBox", checkboxprops1) mouselistener.optioncontrolcontainer = optioncontrolcontainer rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 controller = doc.getCurrentController() # 現在のコントローラを取得。 if enhancedmouseevent is None: visibleareaonscreen = controller.getPropertyValue( "VisibleAreaOnScreen") rectangle.X, rectangle.Y = visibleareaonscreen.X, visibleareaonscreen.Y else: dialogpoint = dialogcommons.getDialogPoint( doc, enhancedmouseevent ) # クリックした位置のメニューバーの高さ分下の位置を取得。単位ピクセル。一部しか表示されていないセルのときはNoneが返る。 if not dialogpoint: # クリックした位置が取得出来なかった時は何もしない。 return rectangle.X, rectangle.Y = dialogpoint # クリックした位置を取得。ウィンドウタイトルを含めない座標。 taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "controldialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。 mouselistener.dialogframe = dialogframe dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 dialogframe.setTitle(dialogtitle) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 toolkit = dialogwindow.getToolkit() # ピアからツールキットを取得。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールコンテナを描画。 optioncontrolcontainer.createPeer( toolkit, dialogwindow) # ウィンドウにオプションコントロールコンテナを描画。Visibleにはしない。 frameactionlistener = dialogcommons.FrameActionListener( ) # FrameActionListener。フレームがアクティブでなくなった時に閉じるため。 dialogframe.addFrameActionListener( frameactionlistener) # FrameActionListenerをダイアログフレームに追加。 controlcontainer.setVisible(True) # コントロールの表示。 dialogwindow.setVisible(True) # ウィンドウの表示。これ以降WindowListenerが発火する。 windowlistener = WindowListener( controlcontainer, optioncontrolcontainer ) # コンテナウィンドウからコントロールコンテナを取得する方法はないはずなので、ここで渡す。WindowListenerはsetVisible(True)で呼び出される。 dialogwindow.addWindowListener(windowlistener) # コンテナウィンドウにリスナーを追加する。 menulistener.args = dialogwindow, windowlistener, mouselistener dialogstate = dialogcommons.getSavedData( doc, "dialogstate_{}".format(dialogtitle) ) # 保存データを取得。optioncontrolcontainerの表示状態は常にFalseなので保存されていない。 if dialogstate is not None: # 保存してあるダイアログの状態がある時。 for menuid in range(1, gridpopupmenu.getItemCount() + 1): # ポップアップメニューを走査する。 itemtext = gridpopupmenu.getItemText( menuid) # 文字列にはショートカットキーがついてくる。 if itemtext.startswith("オプション表示"): optioncheck = dialogstate.get( "OptionCheck") # オプション表示、のチェックがある時。 if optioncheck is not None: gridpopupmenu.checkItem( menuid, optioncheck) # ItemIDは1から始まる。これでMenuListenerは発火しない。 if optioncheck: # チェックが付いている時MenuListenerを発火させる。 menulistener.itemSelected( MenuEvent(MenuId=menuid, Source=mouselistener.gridpopupmenu)) checkbox1sate = dialogstate.get("CheckBox1sate") # サイズ復元、チェックボックス。 if checkbox1sate is not None: # サイズ復元、が保存されている時。 checkboxcontrol2.setState(checkbox1sate) # 状態を復元。 if checkbox1sate: # サイズ復元がチェックされている時。 dialogwindow.setPosSize( 0, 0, dialogstate["Width"], dialogstate["Height"], PosSize.SIZE) # ウィンドウサイズを復元。WindowListenerが発火する。 args = doc, dialogwindow, windowlistener, mouselistener, menulistener, controlcontainerwindowlistener, mousemotionlistener dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。
def macro(): ctx = XSCRIPTCONTEXT.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = XSCRIPTCONTEXT.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 docwindow = docframe.getContainerWindow() # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 toolkit = docwindow.getToolkit() # ピアからツールキットを取得。 dialog, dummy_addControl = dialogCreator( ctx, smgr, { "PositionX": 102, "PositionY": 41, "Width": 380, "Height": 380, "Title": "LibreOffice", "Name": "MyTestDialog", "Step": 0, "Moveable": True }) # "TabIndex": 0 dialogmodel = dialog.getModel() # ダイアログモデルを取得。 unomultipagemodel = dialogmodel.createInstance( "com.sun.star.awt.UnoMultiPageModel") unomultipagemodel.setPropertyValues( ("PositionX", "PositionY", "Width", "Height"), (0, 0, 150, 150)) dialogmodel.insertByName("tab", unomultipagemodel) unomultipage = dialog.getControl("tab") args = NamedValue(Name="Title", Value="TabPage1") unopagemodel = unomultipagemodel.createInstance( "com.sun.star.awt.UnoPageModel") unomultipagemodel.insertByName("TabPage1", unopagemodel) n = len(unomultipagemodel.getElementNames()) unomultipage.setTabProps(n + 1, (args, )) buttonmodel = unopagemodel.createInstance( "com.sun.star.awt.UnoControlButtonModel") buttonmodel.setPropertyValues( ("PositionX", "PositionY", "Width", "Height", "Label"), (10, 10, 30, 15, "Button1")) unopagemodel.insertByName("Button1", buttonmodel) args = NamedValue(Name="Title", Value="TabPage2") unopagemodel = unomultipagemodel.createInstance( "com.sun.star.awt.UnoPageModel") unomultipagemodel.insertByName("TabPage2", unopagemodel) n = len(unomultipagemodel.getElementNames()) unomultipage.setTabProps(n + 1, (args, )) # tabpagecontainermodel = dialogmodel.createInstance("com.sun.star.awt.tab.UnoControlTabPageContainerModel") # タブページコンテナモデルをインスタンス化。 # dialogmodel.insertByName("Tab", tabpagecontainermodel) # タブページコンテナモデルをダイアログモデルに挿入。 # tabpagecontainermodel.setPropertyValues(("PositionX", "PositionY", "Width", "Height"),(10, 10, 140, 130)) # タブページコンテナモデルの位置と大きさを設定。 # tabpage1 = tabpagecontainermodel.createTabPage(1) # タブページコンテナモデルからタブページ1を作成。 # tabpage1.Title = "TabPage1" # タブページ1のタイトルを設定。 # tabpagecontainermodel.insertByIndex(0, tabpage1) # タブページ1をタブページコンテナモデルに挿入。 # tabpagecontainer = dialog.getControl("Tab") # タブページコンテナを取得。 # # tabpagecontainer.ActiveTabPageID = 1 # タブページ1をアクティベートする。ここでunsatisfied query for interface of type com.sun.star.awt.tab.XTabPageContainer! dialog.createPeer( toolkit, docwindow ) # ダイアログを描画。親ウィンドウを渡す。ノンモダルダイアログのときはNone(デスクトップ)ではフリーズする。Stepを使うときはRoadmap以外のコントロールが追加された後にピアを作成しないとStepが重なって表示される。 # ノンモダルダイアログにするとき。 # showModelessly(ctx, smgr, docframe, dialog) # モダルダイアログにする。フレームに追加するとエラーになる。 dialog.execute() dialog.dispose()
def createDialog( xscriptcontext, enhancedmouseevent, dialogtitle, defaultrows=None ): # dialogtitleはダイアログのデータ保存名に使うのでユニークでないといけない。defaultrowsはグリッドコントロールのデフォルトデータ。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 dialogpoint = getDialogPoint( doc, enhancedmouseevent ) # クリックした位置のメニューバーの高さ分下の位置を取得。単位ピクセル。一部しか表示されていないセルのときはNoneが返る。 if not dialogpoint: # クリックした位置が取得出来なかった時は何もしない。 return docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 maTopx = createConverters(containerwindow) # ma単位をピクセルに変換する関数を取得。 m = 2 # コントロール間の間隔。 h = 12 # コントロールの高さ gridprops = { "PositionX": 0, "PositionY": 0, "Width": 50, "Height": 50, "ShowRowHeader": False, "ShowColumnHeader": False, "SelectionModel": MULTI } # グリッドコントロールのプロパティ。 controlcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(gridprops), "Height": YHeight(gridprops), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 controlcontainer, addControl = controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 menulistener = MenuListener() # コンテクストメニューにつけるリスナー。 items = ("セル入力で閉じる", MenuItemStyle.CHECKABLE+MenuItemStyle.AUTOCHECK, {"checkItem": False}),\ ("オプション表示", MenuItemStyle.CHECKABLE+MenuItemStyle.AUTOCHECK, {"checkItem": False}) # グリッドコントロールのコンテクストメニュー。XMenuListenerのmenuevent.MenuIdでコードを実行する。 gridpopupmenu = menuCreator(ctx, smgr)("PopupMenu", items, { "addMenuListener": menulistener }) # 右クリックでまず呼び出すポップアップメニュー。 mouselistener = MouseListener(xscriptcontext, gridpopupmenu) gridcontrol1 = addControl( "Grid", gridprops, {"addMouseListener": mouselistener}) # グリッドコントロールの取得。 gridmodel = gridcontrol1.getModel() # グリッドコントロールモデルの取得。 gridcolumn = gridmodel.getPropertyValue( "ColumnModel") # DefaultGridColumnModel gridcolumn.addColumn(gridcolumn.createColumn()) # 列を追加。 griddatamodel = gridmodel.getPropertyValue( "GridDataModel") # GridDataModel datarows = getSavedData(doc, "GridDatarows_{}".format( dialogtitle)) # グリッドコントロールの行をconfigシートのragenameから取得する。 if datarows is None and defaultrows is not None: # 履歴がなくデフォルトdatarowsがあるときデフォルトデータを使用。 datarows = [ i if isinstance(i, (list, tuple)) else (i, ) for i in defaultrows ] # defaultrowsの要素をリストかタプルでなければタプルに変換する。 if datarows: # 行のリストが取得出来た時。 griddatamodel.addRows(("", ) * len(datarows), datarows) # グリッドに行を追加。 else: datarows = [] # Noneのままではあとで処理できないので空リストを入れる。 controlcontainerwindowlistener = ControlContainerWindowListener( controlcontainer) controlcontainer.addWindowListener( controlcontainerwindowlistener ) # コントロールコンテナの大きさを変更するとグリッドコントロールの大きさも変更するようにする。 textboxprops = { "PositionX": 0, "PositionY": m, "Height": h } # テクストボックスコントロールのプロパティ。 checkboxprops1 = { "PositionX": 0, "PositionY": YHeight(textboxprops, m), "Width": 46, "Height": h, "Label": "~セルに追記", "State": 0 } # セルに追記はデフォルトでは無効。 buttonprops1 = { "PositionX": XWidth(checkboxprops1), "PositionY": YHeight(textboxprops, m), "Width": 18, "Height": h + 2, "Label": "上へ" } # ボタンのプロパティ。PushButtonTypeの値はEnumではエラーになる。VerticalAlignではtextboxと高さが揃わない。 buttonprops3 = { "PositionX": XWidth(buttonprops1, 2), "PositionY": YHeight(textboxprops, m), "Width": 26, "Height": h + 2, "Label": "行挿入" } checkboxprops2 = { "PositionX": 0, "PositionY": YHeight(checkboxprops1, 4), "Width": 46, "Height": h, "Label": "~サイズ復元", "State": 1 } # サイズ復元はデフォルトでは有効。 buttonprops2 = { "PositionX": XWidth(checkboxprops1), "PositionY": YHeight(buttonprops1, m * 2), "Width": 18, "Height": h + 2, "Label": "下へ" } buttonprops4 = { "PositionX": XWidth(buttonprops1, m), "PositionY": YHeight(buttonprops1, m * 2), "Width": 26, "Height": h + 2, "Label": "行削除" } textboxprops.update({"Width": XWidth(buttonprops3, m)}) # 右端のコントロールから左の余白mを除いた幅を取得。 optioncontrolcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": XWidth(textboxprops), "Height": YHeight(buttonprops2, 2), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 optioncontrolcontainer, optionaddControl = controlcontainerMaCreator( ctx, smgr, maTopx, optioncontrolcontainerprops) # コントロールコンテナの作成。 optionaddControl("Edit", textboxprops) checkboxcontrol1 = optionaddControl("CheckBox", checkboxprops1) checkboxcontrol2 = optionaddControl("CheckBox", checkboxprops2) actionlistener = ActionListener(gridcontrol1, datarows) # ボタンコントロールにつけるリスナー。 optionaddControl("Button", buttonprops1, { "addActionListener": actionlistener, "setActionCommand": "up" }) optionaddControl("Button", buttonprops2, { "addActionListener": actionlistener, "setActionCommand": "down" }) optionaddControl("Button", buttonprops3, { "addActionListener": actionlistener, "setActionCommand": "insert" }) optionaddControl("Button", buttonprops4, { "addActionListener": actionlistener, "setActionCommand": "delete" }) optioncontrolcontainerwindowlistener = OptionControlContainerWindowListener( optioncontrolcontainer) optioncontrolcontainer.addWindowListener( optioncontrolcontainerwindowlistener ) # コントロールコンテナの大きさを変更するとグリッドコントロールの大きさも変更するようにする。 mouselistener.optioncontrolcontainer = optioncontrolcontainer rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 rectangle.X, rectangle.Y = dialogpoint # クリックした位置を取得。ウィンドウタイトルを含めない座標。 taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "controldialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。 mouselistener.dialogframe = dialogframe dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 dialogframe.setTitle(dialogtitle) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 toolkit = dialogwindow.getToolkit() # ピアからツールキットを取得。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールコンテナを描画。 optioncontrolcontainer.createPeer( toolkit, dialogwindow) # ウィンドウにオプションコントロールコンテナを描画。Visibleにはしない。 frameactionlistener = FrameActionListener( ) # FrameActionListener。フレームがアクティブでなくなった時に閉じるため。 dialogframe.addFrameActionListener( frameactionlistener) # FrameActionListenerをダイアログフレームに追加。 controlcontainer.setVisible(True) # コントロールの表示。 dialogwindow.setVisible(True) # ウィンドウの表示。これ以降WindowListenerが発火する。 windowlistener = WindowListener( controlcontainer, optioncontrolcontainer ) # コンテナウィンドウからコントロールコンテナを取得する方法はないはずなので、ここで渡す。WindowListenerはsetVisible(True)で呼び出される。 dialogwindow.addWindowListener(windowlistener) # コンテナウィンドウにリスナーを追加する。 menulistener.args = dialogwindow, windowlistener dialogstate = getSavedData( doc, "dialogstate_{}".format(dialogtitle) ) # 保存データを取得。optioncontrolcontainerの表示状態は常にFalseなので保存されていない。 if dialogstate is not None: # 保存してあるダイアログの状態がある時。 for menuid in range(1, gridpopupmenu.getItemCount() + 1): # ポップアップメニューを走査する。 itemtext = gridpopupmenu.getItemText( menuid) # 文字列にはショートカットキーがついてくる。 if itemtext.startswith("セル入力で閉じる"): closecheck = dialogstate.get( "CloseCheck") # セル入力で閉じる、のチェックがある時。 if closecheck is not None: gridpopupmenu.checkItem(menuid, closecheck) elif itemtext.startswith("オプション表示"): optioncheck = dialogstate.get( "OptionCheck") # オプション表示、のチェックがある時。 if optioncheck is not None: gridpopupmenu.checkItem( menuid, optioncheck) # ItemIDは1から始まる。これでMenuListenerは発火しない。 if optioncheck: # チェックが付いている時MenuListenerを発火させる。 menulistener.itemSelected( MenuEvent(MenuId=menuid, Source=mouselistener.gridpopupmenu)) checkbox1sate = dialogstate.get( "CheckBox1sate") # セルに追記、チェックボックス。キーがなければNoneが返る。 if checkbox1sate is not None: # セルに追記、が保存されている時。 checkboxcontrol1.setState(checkbox1sate) # 状態を復元。 checkbox2sate = dialogstate.get("CheckBox2sate") # サイズ復元、チェックボックス。 if checkbox2sate is not None: # サイズ復元、が保存されている時。 checkboxcontrol2.setState(checkbox2sate) # 状態を復元。 if checkbox2sate: # サイズ復元がチェックされている時。 dialogwindow.setPosSize( 0, 0, dialogstate["Width"], dialogstate["Height"], PosSize.SIZE) # ウィンドウサイズを復元。WindowListenerが発火する。 args = doc, actionlistener, dialogwindow, windowlistener, mouselistener, menulistener, controlcontainerwindowlistener, optioncontrolcontainerwindowlistener dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。
def createDialog( enhancedmouseevent, xscriptcontext, dialogtitle, formatstring=None, outputcolumn=None, *, callback=None ): # dialogtitleはダイアログのデータ保存名に使うのでユニークでないといけない。formatstringは代入セルの書式。 ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 doc = xscriptcontext.getDocument() # マクロを起動した時のドキュメントのモデルを取得。 dialogpoint = dialogcommons.getDialogPoint( doc, enhancedmouseevent ) # クリックした位置のメニューバーの高さ分下の位置を取得。単位ピクセル。一部しか表示されていないセルのときはNoneが返る。 if not dialogpoint: # クリックした位置が取得出来なかった時は何もしない。 return docframe = doc.getCurrentController().getFrame( ) # モデル→コントローラ→フレーム、でドキュメントのフレームを取得。 containerwindow = docframe.getContainerWindow( ) # ドキュメントのウィンドウ(コンテナウィンドウ=ピア)を取得。 maTopx = dialogcommons.createConverters( containerwindow) # ma単位をピクセルに変換する関数を取得。 m = 2 # コントロール間の間隔。 h = 12 # コントロールの高さ gridprops = { "PositionX": 0, "PositionY": 0, "Width": 76, "Height": 73, "ShowRowHeader": False, "ShowColumnHeader": False, "VScroll": False, "SelectionModel": SINGLE } # グリッドコントロールのプロパティ。 controlcontainerprops = { "PositionX": 0, "PositionY": 0, "Width": dialogcommons.XWidth(gridprops), "Height": dialogcommons.YHeight(gridprops), "BackgroundColor": 0xF0F0F0 } # コントロールコンテナの基本プロパティ。幅は右端のコントロールから取得。高さはコントロール追加後に最後に設定し直す。 optioncontrolcontainerprops = controlcontainerprops.copy() controlcontainer, addControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, controlcontainerprops) # コントロールコンテナの作成。 items = ("セル入力で閉じる", MenuItemStyle.CHECKABLE + MenuItemStyle.AUTOCHECK, { "checkItem": True }), # グリッドコントロールのコンテクストメニュー。XMenuListenerのmenuevent.MenuIdでコードを実行する。 menulistener = MenuListener() # コンテクストメニューにつけるリスナー。 gridpopupmenu = dialogcommons.menuCreator(ctx, smgr)( "PopupMenu", items, { "addMenuListener": menulistener, "hideDisabledEntries": False }) # 右クリックでまず呼び出すポップアップメニュー。 mousemotionlistener = dialogcommons.MouseMotionListener() args = xscriptcontext, formatstring, outputcolumn, callback mouselistener = MouseListener(gridpopupmenu, args) gridcontrolwidth = gridprops[ "Width"] # gridpropsは消費されるので、グリッドコントロールの幅を取得しておく。 gridcontrol1 = addControl( "Grid", gridprops, { "addMouseListener": mouselistener, "addMouseMotionListener": mousemotionlistener }) # グリッドコントロールの取得。 gridcolumn = gridcontrol1.getModel().getPropertyValue( "ColumnModel") # DefaultGridColumnModel column0 = gridcolumn.createColumn() # 列の作成。 column0.ColumnWidth = 25 # 列幅。 gridcolumn.addColumn(column0) # 1列目を追加。 column1 = gridcolumn.createColumn() # 列の作成。 column1.ColumnWidth = gridcontrolwidth - column0.ColumnWidth # 列幅。列の合計がグリッドコントロールの幅に一致するようにする。 gridcolumn.addColumn(column1) # 2列目を追加。 numericfieldprops1 = { "PositionY": m, "Width": 24, "Height": h + 2, "Spin": True, "StrictFormat": True, "Value": 0, "ValueStep": -1, "ShowThousandsSeparator": False, "DecimalAccuracy": 0 } fixedtextprops1 = { "PositionY": m, "Width": 14, "Height": h, "Label": "週後", "VerticalAlign": MIDDLE } fixedtextprops1.update( {"PositionX": gridcontrolwidth - fixedtextprops1["Width"]}) numericfieldprops1.update({ "PositionX": fixedtextprops1["PositionX"] - numericfieldprops1["Width"] }) optioncontrolcontainerprops.update({ "PositionY": dialogcommons.YHeight(optioncontrolcontainerprops), "Height": dialogcommons.YHeight(numericfieldprops1, m) }) optioncontrolcontainer, optionaddControl = dialogcommons.controlcontainerMaCreator( ctx, smgr, maTopx, optioncontrolcontainerprops) # コントロールコンテナの作成。 textlistener = TextListener(gridcontrol1) numericfield1 = optionaddControl("NumericField", numericfieldprops1, {"addTextListener": textlistener}) optionaddControl("FixedText", fixedtextprops1) rectangle = controlcontainer.getPosSize( ) # コントロールコンテナのRectangle Structを取得。px単位。 rectangle.X, rectangle.Y = dialogpoint # クリックした位置を取得。ウィンドウタイトルを含めない座標。 rectangle.Height += optioncontrolcontainer.getSize().Height taskcreator = smgr.createInstanceWithContext( 'com.sun.star.frame.TaskCreator', ctx) args = NamedValue("PosSize", rectangle), NamedValue( "FrameName", "controldialog" ) # , NamedValue("MakeVisible", True) # TaskCreatorで作成するフレームのコンテナウィンドウのプロパティ。 dialogframe = taskcreator.createInstanceWithArguments( args) # コンテナウィンドウ付きの新しいフレームの取得。サイズ変更は想定しない。 mouselistener.dialogframe = dialogframe dialogwindow = dialogframe.getContainerWindow() # ダイアログのコンテナウィンドウを取得。 dialogframe.setTitle(dialogtitle) # フレームのタイトルを設定。 docframe.getFrames().append(dialogframe) # 新しく作ったフレームを既存のフレームの階層に追加する。 toolkit = dialogwindow.getToolkit() # ピアからツールキットを取得。 controlcontainer.createPeer(toolkit, dialogwindow) # ウィンドウにコントロールコンテナを描画。 optioncontrolcontainer.createPeer( toolkit, dialogwindow) # ウィンドウにオプションコントロールコンテナを描画。Visibleにはしない。 frameactionlistener = dialogcommons.FrameActionListener( ) # FrameActionListener。フレームがアクティブでなくなった時に閉じるため。 dialogframe.addFrameActionListener( frameactionlistener) # FrameActionListenerをダイアログフレームに追加。 controlcontainer.setVisible(True) # コントロールの表示。 optioncontrolcontainer.setVisible(True) dialogwindow.setVisible(True) # ウィンドウの表示。これ以降WindowListenerが発火する。 numericfield1.setFocus() todayindex = 7 // 2 # 今日の日付の位置を決定。切り下げ。 col0 = [""] * 7 # 全てに空文字を挿入。 selection = enhancedmouseevent.Target # 選択セルを取得。 datevalue = selection.getValue() # セルの値を取得。 if not datevalue > 0: # セルに日付が入っていない時。 centerdate = date.today() # 今日の日付を中央にする。 col0[todayindex - 1:todayindex + 2] = "昨日", "今日", "明日" # 列インデックス0に入れる文字列を取得。 else: # セルに日付が入っている時。 datetxt = selection.getString() # 日付文字列を取得。2018-8-5などを想定。 centerdate = date(*map(int, datetxt.split( datetxt[4]))) # 日付文字列をdateオブジェクトにして中央にする。 col0[todayindex] = "セル値" sdate, edate = None, None lowerlimit, col0min, upperlimit, col0max = None, None, None, None if selection.getCellAddress( ).Row >= journal.VARS.splittedrow: # 選択セルが固定行以下の時のみ上限と下限を指定する。 sdate, edate = journal.getDateSection() # 期首日と期末日のdateオブジェクトを取得。 if sdate: # 期首日と期末日が取得出来ている問。 if not sdate <= centerdate <= edate: # 中央値が会計期間内でない時。centerdateを変更する。 if centerdate < sdate: # 期首日より新しい取得日の時。 centerdate = sdate + timedelta( days=todayindex) # 期首日が1番上に来るようにする。 lowerlimit = 0 # 最小週数を設定。 col0 = ("期首日", *[""] * 6) else: # 期末日より古い取得日の時。 centerdate = edate - timedelta( days=todayindex) # 期末日が一番下に来るようにする。 upperlimit = 0 # 最大週数を設定。 numericfield1.setMax(0) col0 = (*[""] * 6, "期末日") if lowerlimit is None: diffmindays = (centerdate - timedelta(days=todayindex) - sdate).days # centerdateから期首日までの日数差。 lowerlimit = diffmindays // -7 # 期首日までの週数差。負数が返る。 indexmin = (7 - diffmindays % 7) % 7 # 最小週数での期首日の位置。 col0min = (*[""] * indexmin, "期首日", *[""] * (6 - indexmin)) if upperlimit is None: diffmaxdays = (edate - timedelta(days=todayindex) - centerdate).days # centerdateから期末日までの日数差。 upperlimit = -(diffmaxdays // -7) # 期末日までの週数差。 indexmax = (diffmaxdays % 7 - 1) % 7 # 最大週数での期末日の位置。 col0max = (*[""] * indexmax, "期末日", *[""] * (6 - indexmax)) numericfield1.setMin(lowerlimit) # 最小週数を設定。 numericfield1.setMax(upperlimit) # 最大週数を設定。 textlistener.colargs = col0, lowerlimit, col0min, upperlimit, col0max addDays = addDaysCreator(selection, gridcontrol1, sdate, edate) textlistener.addDays = addDays addDays(centerdate, col0) # グリッドコントロールに行を入れる。 menulistener.args = controlcontainer, mouselistener, mousemotionlistener dialogstate = dialogcommons.getSavedData( doc, "dialogstate_{}".format(dialogtitle) ) # 保存データを取得。optioncontrolcontainerの表示状態は常にFalseなので保存されていない。 if dialogstate is not None: # 保存してあるダイアログの状態がある時。 for menuid in range(1, gridpopupmenu.getItemCount() + 1): # ポップアップメニューを走査する。 itemtext = gridpopupmenu.getItemText( menuid) # 文字列にはショートカットキーがついてくる。 if itemtext.startswith("セル入力で閉じる"): closecheck = dialogstate.get( "CloseCheck") # セル入力で閉じる、のチェックがある時。 if closecheck is not None: gridpopupmenu.checkItem(menuid, closecheck) args = doc, mouselistener, controlcontainer, mousemotionlistener, menulistener dialogframe.addCloseListener( CloseListener(args)) # CloseListener。ノンモダルダイアログのリスナー削除用。
def CreateNamedValue(name, value): v = NamedValue() v.Name = name v.Value = value return v