From 57ad5b119dcff870e48e700f2ba3834c9a7c9ea4 Mon Sep 17 00:00:00 2001 From: svnadmin Date: Tue, 29 Mar 2016 01:13:13 +0000 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=88=B08.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 2196 ++ .gitignore | 1 + designer_base/.classpath | 33 + designer_base/.project | 1 + designer_base/designer_base.iml | 19 + .../src/com/fr/design/DesignModelAdapter.java | 141 + .../src/com/fr/design/DesignState.java | 73 + .../src/com/fr/design/DesignerEnvManager.java | 1795 ++ .../design/Exception/ValidationException.java | 11 + .../fr/design/ExtraDesignClassManager.java | 827 + .../src/com/fr/design/RestartHelper.java | 191 + .../actions/AllowAuthorityEditAction.java | 1 + .../com/fr/design/actions/CheckBoxAction.java | 41 + .../actions/ExitAuthorityEditAction.java | 1 + .../design/actions/HyperlinkPluginAction.java | 57 + .../fr/design/actions/JTemplateAction.java | 16 + .../src/com/fr/design/actions/MenuAction.java | 46 + .../design/actions/TableDataSourceAction.java | 84 + .../actions/TemplateComponentAction.java | 40 + .../TemplateComponentActionInterface.java | 7 + .../actions/ToggleButtonUpdateAction.java | 15 + .../design/actions/ToolbarActionManager.java | 52 + .../com/fr/design/actions/UndoableAction.java | 21 + .../com/fr/design/actions/UpdateAction.java | 402 + .../fr/design/actions/core/ActionUtils.java | 202 + .../fr/design/actions/edit/CopyAction.java | 37 + .../com/fr/design/actions/edit/CutAction.java | 39 + .../fr/design/actions/edit/PasteAction.java | 39 + .../fr/design/actions/edit/RedoAction.java | 59 + .../fr/design/actions/edit/UndoAction.java | 60 + .../file/CloseCurrentTemplateAction.java | 1 + .../actions/file/CloseTemplateAction.java | 29 + .../fr/design/actions/file/EditEnvAction.java | 22 + .../actions/file/ExitDesignerAction.java | 32 + .../fr/design/actions/file/LocalePane.java | 243 + .../actions/file/OpenRecentReportMenuDef.java | 78 + .../actions/file/OpenTemplateAction.java | 45 + .../design/actions/file/PreferenceAction.java | 46 + .../design/actions/file/PreferencePane.java | 633 + .../actions/file/SaveAsTemplateAction.java | 48 + .../actions/file/SaveTemplateAction.java | 45 + .../design/actions/file/SwitchExistEnv.java | 127 + .../design/actions/file/WebPreviewUtils.java | 95 + .../fr/design/actions/help/AboutAction.java | 50 + .../fr/design/actions/help/AboutDialog.java | 100 + .../com/fr/design/actions/help/AboutPane.java | 238 + .../design/actions/help/FeedBackAction.java | 57 + .../fr/design/actions/help/FeedBackPane.java | 350 + .../fr/design/actions/help/ForumAction.java | 75 + .../design/actions/help/SupportQQAction.java | 63 + .../design/actions/help/SystemInfoPane.java | 69 + .../design/actions/help/TutorialAction.java | 98 + .../fr/design/actions/help/WebDemoAction.java | 46 + .../actions/server/ConnectionListAction.java | 171 + .../actions/server/FunctionManagerAction.java | 79 + .../actions/server/GlobalParameterAction.java | 93 + .../actions/server/GlobalTableDataAction.java | 197 + .../actions/server/PlatformManagerAction.java | 48 + .../actions/server/PluginManagerAction.java | 52 + .../actions/server/ProcedureListAction.java | 63 + .../actions/tabledata/TableDataAction.java | 97 + .../com/fr/design/beans/BasicBeanPane.java | 39 + .../fr/design/beans/FurtherBasicBeanPane.java | 28 + .../src/com/fr/design/beans/GroupModel.java | 56 + .../design/beans/location/Absorptionline.java | 190 + .../fr/design/beans/location/MoveUtils.java | 332 + .../com/fr/design/border/UIRoundedBorder.java | 50 + .../com/fr/design/border/UITitledBorder.java | 28 + .../design/bridge/DesignToolbarProvider.java | 17 + .../fr/design/cell/FloatElementsProvider.java | 15 + .../condition/CellHighlightAddMenuDef.java | 66 + .../ConditionAttrSingleConditionPane.java | 52 + .../condition/ConditionAttributesPane.java | 133 + .../ContinuousTreeSelectionModel.java | 128 + .../condition/DSColumnLiteConditionPane.java | 200 + .../DSColumnSimpleLiteConditionPane.java | 21 + .../condition/HighLightConditionAction.java | 36 + .../design/condition/LiteConditionPane.java | 950 + .../condition/ObjectLiteConditionPane.java | 103 + .../design/condition/SingleConditionPane.java | 54 + .../src/com/fr/design/constants/KeyWords.java | 206 + .../fr/design/constants/LayoutConstants.java | 1 + .../com/fr/design/constants/UIConstants.java | 172 + .../src/com/fr/design/data/DataCreatorUI.java | 12 + .../design/data/DesignTableDataManager.java | 468 + .../fr/design/data/datapane/ChoosePane.java | 602 + .../datapane/ChoosePaneSupportFormula.java | 1 + .../design/data/datapane/DSButtonGroup.java | 48 + .../design/data/datapane/DataBaseItems.java | 49 + .../design/data/datapane/EditOrNewLabel.java | 34 + .../datapane/FlashLookLabelMouseAdapter.java | 57 + .../datapane/GlobalTableDataComboBox.java | 22 + .../datapane/GlobalTreeTableDataDictPane.java | 21 + .../fr/design/data/datapane/RefreshLabel.java | 37 + .../data/datapane/ReportTableDataPane.java | 62 + .../data/datapane/TableDataComboBox.java | 149 + .../datapane/TableDataCreatorProducer.java | 134 + .../data/datapane/TableDataListPane.java | 261 + .../datapane/TableDataNameObjectCreator.java | 178 + .../data/datapane/TableDataSourceOP.java | 236 + .../design/data/datapane/TableDataTree.java | 244 + .../datapane/TableDataTreeDragSource.java | 102 + .../data/datapane/TableDataTreePane.java | 647 + .../data/datapane/TreeTableDataComboBox.java | 87 + .../data/datapane/TreeTableDataDictPane.java | 299 + .../data/datapane/VerticalChoosePane.java | 69 + .../connect/ConnectionComboBoxPanel.java | 128 + .../datapane/connect/ConnectionListPane.java | 153 + .../connect/ConnectionManagerPane.java | 78 + .../connect/ConnectionTableProcedurePane.java | 188 + .../connect/DataConnectionAction.java | 67 + .../connect/DatabaseConnectionPane.java | 241 + .../connect/ItemEditableComboBoxPanel.java | 122 + .../data/datapane/connect/JDBCDefPane.java | 376 + .../data/datapane/connect/JNDIDefPane.java | 266 + .../datapane/preview/LoadedEventListener.java | 18 + .../data/datapane/preview/PreviewLabel.java | 37 + .../datapane/preview/PreviewTableModel.java | 212 + .../datapane/preview/PreviewTablePane.java | 482 + .../data/datapane/sqlpane/SQLEditPane.java | 1 + .../tabledata/Prepare4DataSourceChange.java | 15 + .../tabledata/ResponseDataSourceChange.java | 25 + .../StoreProcedureWorkerListener.java | 14 + .../fr/design/data/tabledata/gui/CONTENT.txt | 14 + .../fr/design/data/tabledata/gui/EXPLAN1.txt | 6 + .../fr/design/data/tabledata/gui/EXPLAN2.txt | 17 + .../tabledatapane/AbstractTableDataPane.java | 15 + .../AutoStoreProcedureTableModel.java | 156 + .../tabledatapane/ClassNameSelectPane.java | 63 + .../tabledatapane/ClassTableDataPane.java | 115 + .../tabledatapane/CustomDictModel.java | 130 + .../tabledatapane/DBTableDataPane.java | 344 + .../tabledatapane/DecoratedTableDataPane.java | 96 + .../EmbeddedTableDataDefinedPane.java | 321 + .../tabledatapane/EmbeddedTableDataPane.java | 355 + .../tabledatapane/EmbeddedTableModel.java | 103 + .../tabledatapane/FileTableDataPane.java | 997 + .../FileTableDataSmallHeightPane.java | 19 + .../tabledatapane/FileTableDataSmallPane.java | 19 + .../tabledatapane/FormatExplanationPane.java | 1 + .../GlobalMultiTDTableDataPane.java | 22 + .../GlobalTreeTableDataPane.java | 19 + .../tabledatapane/MaxMemRowCountPanel.java | 97 + .../tabledatapane/MultiTDTableDataPane.java | 405 + .../tabledatapane/OneListTableModel.java | 111 + .../tabledatapane/ProcedureDataPane.java | 381 + .../tabledatapane/ProcedureListPane.java | 148 + .../tabledatapane/ProcedureManagerPane.java | 51 + .../StoreProcedureParameterPane.java | 178 + .../StoreProcedureTableModel.java | 139 + .../tabledatapane/TableDataManagerPane.java | 92 + .../tabledatapane/TreeTableDataPane.java | 45 + .../wrapper/AbstractTableDataWrapper.java | 138 + .../wrapper/ServerTableDataWrapper.java | 57 + .../wrapper/StoreProcedureDataWrapper.java | 311 + .../wrapper/StoreProcedureNameWrapper.java | 153 + .../tabledata/wrapper/TableDataFactory.java | 189 + .../tabledata/wrapper/TableDataWrapper.java | 68 + .../wrapper/TemplateTableDataWrapper.java | 37 + .../com/fr/design/designer/EditingState.java | 13 + .../fr/design/designer/TargetComponent.java | 177 + .../src/com/fr/design/dialog/BasicDialog.java | 61 + .../src/com/fr/design/dialog/BasicPane.java | 395 + .../com/fr/design/dialog/BasicScrollPane.java | 200 + .../fr/design/dialog/DialogActionAdapter.java | 9 + .../design/dialog/DialogActionListener.java | 8 + .../fr/design/dialog/InformationWarnPane.java | 172 + .../com/fr/design/dialog/JWizardDialog.java | 368 + .../com/fr/design/dialog/JWizardPanel.java | 229 + .../com/fr/design/dialog/MultiTabPane.java | 88 + .../src/com/fr/design/dialog/UIDialog.java | 234 + .../src/com/fr/design/dialog/package.html | 8 + .../com/fr/design/editor/ValueEditorPane.java | 400 + .../design/editor/ValueEditorPaneFactory.java | 634 + .../design/editor/editor/BooleanEditor.java | 113 + .../editor/editor/ColumnIndexEditor.java | 110 + .../editor/editor/ColumnNameEditor.java | 79 + .../design/editor/editor/ColumnRowEditor.java | 74 + .../editor/editor/ColumnRowGroupEditor.java | 1 + .../editor/editor/ColumnSelectedEditor.java | 98 + .../design/editor/editor/ConstantsEditor.java | 23 + .../fr/design/editor/editor/CursorEditor.java | 42 + .../fr/design/editor/editor/DateEditor.java | 179 + .../fr/design/editor/editor/DoubleEditor.java | 46 + .../com/fr/design/editor/editor/Editor.java | 203 + .../design/editor/editor/EditorListener.java | 29 + .../fr/design/editor/editor/FloatEditor.java | 46 + .../design/editor/editor/FormulaEditor.java | 178 + .../design/editor/editor/IntegerEditor.java | 49 + .../fr/design/editor/editor/LongEditor.java | 41 + .../fr/design/editor/editor/NoneEditor.java | 54 + .../fr/design/editor/editor/NumberEditor.java | 128 + .../editor/editor/OldColumnIndexEditor.java | 163 + .../design/editor/editor/ParameterEditor.java | 64 + .../fr/design/editor/editor/TextEditor.java | 153 + .../editor/editor/WidgetNameEditor.java | 110 + .../design/editor/editor/XMLANameEditor.java | 117 + .../src/com/fr/design/event/ChangeEvent.java | 1 + .../com/fr/design/event/ChangeListener.java | 1 + .../fr/design/event/GlobalNameListener.java | 1 + .../fr/design/event/GlobalNameObserver.java | 1 + .../fr/design/event/TargetModifiedEvent.java | 19 + .../design/event/TargetModifiedListener.java | 16 + .../design/event/TemplateTreeDragSource.java | 37 + .../src/com/fr/design/event/UIObserver.java | 1 + .../fr/design/event/UIObserverListener.java | 14 + .../src/com/fr/design/extra/After.java | 11 + .../com/fr/design/extra/AppStoreBuilder.java | 19 + .../fr/design/extra/LoginCheckContext.java | 30 + .../fr/design/extra/LoginCheckListener.java | 8 + .../extra/PluginAbstractLoadingViewPane.java | 191 + .../design/extra/PluginAbstractViewPane.java | 26 + .../com/fr/design/extra/PluginConstants.java | 31 + .../fr/design/extra/PluginControlPane.java | 153 + .../design/extra/PluginDescriptionLabel.java | 23 + .../com/fr/design/extra/PluginDetailPane.java | 71 + .../fr/design/extra/PluginFromStorePane.java | 259 + .../src/com/fr/design/extra/PluginHelper.java | 298 + .../fr/design/extra/PluginInstalledPane.java | 143 + .../com/fr/design/extra/PluginListPane.java | 16 + .../fr/design/extra/PluginManagerPane.java | 63 + .../fr/design/extra/PluginSelectListener.java | 13 + .../extra/PluginStatusCheckCompletePane.java | 78 + .../src/com/fr/design/extra/PluginTask.java | 53 + .../com/fr/design/extra/PluginUpdatePane.java | 276 + .../com/fr/design/extra/PluginWebBridge.java | 177 + .../com/fr/design/extra/PluginWebPane.java | 58 + .../design/extra/PluginsReaderFromStore.java | 99 + .../src/com/fr/design/extra/Process.java | 11 + .../src/com/fr/design/extra/exe/Command.java | 11 + .../src/com/fr/design/extra/exe/Executor.java | 11 + .../extra/exe/InstallFromDiskExecutor.java | 54 + .../extra/exe/InstallOnlineExecutor.java | 54 + .../extra/exe/ModifyStatusExecutor.java | 25 + .../design/extra/exe/UninstallExecutor.java | 23 + .../extra/exe/UpdateFromDiskExecutor.java | 23 + .../extra/exe/UpdateOnlineExecutor.java | 23 + .../src/com/fr/design/extra/plugin.properties | 0 .../com/fr/design/file/FileOperations.java | 45 + .../file/FileToolbarStateChangeListener.java | 5 + .../design/file/HistoryTemplateListPane.java | 376 + .../fr/design/file/MutilTempalteTabPane.java | 1 + .../com/fr/design/file/NewTemplatePane.java | 1 + .../fr/design/file/SaveSomeTemplatePane.java | 1 + .../com/fr/design/file/TemplateTreePane.java | 307 + .../formula/AbstractNameAndDescription.java | 31 + .../formula/CustomVariableResolver.java | 22 + .../formula/DefaultUIFormulaProcessor.java | 20 + .../com/fr/design/formula/FormulaFactory.java | 29 + .../com/fr/design/formula/FormulaPane.java | 997 + .../FormulaPaneWhenReserveFormula.java | 64 + .../fr/design/formula/FunctionConstants.java | 205 + .../com/fr/design/formula/FunctionDefNAD.java | 22 + .../com/fr/design/formula/FunctionGroup.java | 7 + .../design/formula/FunctionManagerPane.java | 220 + .../com/fr/design/formula/FunctionNAD.java | 42 + .../com/fr/design/formula/JavaEditorPane.java | 287 + .../fr/design/formula/NameAndDescription.java | 10 + .../design/formula/NameAndFunctionList.java | 31 + .../formula/NameAndTypeAndFunctionList.java | 21 + .../fr/design/formula/SortFormulaPane.java | 84 + .../fr/design/formula/TinyFormulaPane.java | 140 + .../src/com/fr/design/formula/UIFormula.java | 42 + .../fr/design/formula/VariableResolver.java | 30 + .../formula/VariableResolverAdapter.java | 96 + .../fr/design/fun/CellAttributeProvider.java | 20 + .../design/fun/CellWidgetOptionProvider.java | 23 + .../com/fr/design/fun/ConnectionProvider.java | 40 + .../fr/design/fun/ExportToolBarProvider.java | 43 + .../src/com/fr/design/fun/Feedback.java | 19 + .../fun/FormElementCaseEditorProcessor.java | 24 + .../design/fun/FormWidgetOptionProvider.java | 21 + .../fr/design/fun/GlobalListenerProvider.java | 19 + .../com/fr/design/fun/HighlightProvider.java | 32 + .../com/fr/design/fun/HyperlinkProvider.java | 20 + .../design/fun/IndentationUnitProcessor.java | 31 + .../design/fun/JavaScriptActionProvider.java | 18 + .../src/com/fr/design/fun/MenuHandler.java | 76 + .../fun/ParameterWidgetOptionProvider.java | 41 + .../fr/design/fun/PresentKindProvider.java | 42 + .../com/fr/design/fun/PreviewProvider.java | 57 + .../fun/ServerTableDataDefineProvider.java | 12 + .../src/com/fr/design/fun/SubmitProvider.java | 33 + .../design/fun/TableDataCreatorProvider.java | 40 + .../design/fun/TableDataDefineProvider.java | 53 + .../fr/design/fun/TitlePlaceProcessor.java | 15 + .../fr/design/fun/ToolbarItemProvider.java | 39 + .../com/fr/design/fun/UIFormulaProcessor.java | 29 + .../impl/AbstractCellAttributeProvider.java | 14 + .../AbstractCellWidgetOptionProvider.java | 17 + .../fun/impl/AbstractConnectionProvider.java | 16 + ...bstractFormElementCaseEditorProcessor.java | 25 + .../AbstractFormWidgetOptionProvider.java | 21 + .../impl/AbstractGlobalListenerProvider.java | 15 + .../fun/impl/AbstractHighlightProvider.java | 16 + .../fun/impl/AbstractHyperlinkProvider.java | 14 + .../AbstractIndentationUnitProcessor.java | 41 + .../AbstractJavaScriptActionProvider.java | 14 + .../design/fun/impl/AbstractMenuHandler.java | 63 + ...AbstractParameterWidgetOptionProvider.java | 16 + .../fun/impl/AbstractPresentKindProvider.java | 17 + .../fun/impl/AbstractPreviewProvider.java | 41 + ...AbstractServerTableDataDefineProvider.java | 12 + .../fun/impl/AbstractSubmitProvider.java | 12 + .../impl/AbstractTableDataDefineProvider.java | 16 + .../fun/impl/AbstractTitleProcessor.java | 12 + .../design/fun/impl/AbstractToolbarItem.java | 14 + .../fun/impl/AbstractUIFormulaProcessor.java | 16 + .../src/com/fr/design/gui/UIDefaultTheme.java | 199 + .../src/com/fr/design/gui/UILookAndFeel.java | 203 + .../gui/autocomplete/AbstractCompletion.java | 153 + .../AbstractCompletionProvider.java | 245 + .../gui/autocomplete/AutoCompleteDemo.java | 142 + .../autocomplete/AutoCompleteDescWindow.java | 591 + .../autocomplete/AutoCompletePopupWindow.java | 970 + .../gui/autocomplete/AutoCompletion.java | 1344 + .../AutoCompletionStyleContext.java | 120 + .../gui/autocomplete/BasicCompletion.java | 144 + .../design/gui/autocomplete/Completion.java | 153 + .../autocomplete/CompletionCellRenderer.java | 625 + .../gui/autocomplete/CompletionListModel.java | 88 + .../gui/autocomplete/CompletionProvider.java | 213 + .../autocomplete/CompletionProviderBase.java | 261 + .../gui/autocomplete/CompletionXMLParser.java | 446 + .../design/gui/autocomplete/CompletionXml.dtd | 30 + .../DefaultCompletionProvider.java | 374 + .../autocomplete/DelegatingCellRenderer.java | 94 + .../gui/autocomplete/DescWindowCallback.java | 35 + .../fr/design/gui/autocomplete/EmptyIcon.java | 49 + .../gui/autocomplete/ExternalURLHandler.java | 46 + .../design/gui/autocomplete/FastListUI.java | 189 + .../gui/autocomplete/FunctionCompletion.java | 322 + .../LanguageAwareCompletionProvider.java | 429 + .../gui/autocomplete/LinkRedirector.java | 20 + .../gui/autocomplete/MarkupTagCompletion.java | 240 + .../autocomplete/OutlineHighlightPainter.java | 143 + .../ParameterChoicesProvider.java | 40 + .../autocomplete/ParameterizedCompletion.java | 172 + .../ParameterizedCompletionChoicesWindow.java | 301 + .../ParameterizedCompletionContext.java | 1199 + ...meterizedCompletionDescriptionToolTip.java | 204 + .../ParameterizedCompletionInsertionInfo.java | 251 + .../gui/autocomplete/ShorthandCompletion.java | 117 + .../fr/design/gui/autocomplete/SizeGrip.java | 256 + .../SortByRelevanceComparator.java | 33 + .../gui/autocomplete/TemplateCompletion.java | 363 + .../gui/autocomplete/TemplatePiece.java | 86 + .../fr/design/gui/autocomplete/TipUtil.java | 179 + .../com/fr/design/gui/autocomplete/Util.java | 323 + .../gui/autocomplete/VariableCompletion.java | 196 + .../fr/design/gui/autocomplete/arrow_left.png | Bin 0 -> 345 bytes .../design/gui/autocomplete/arrow_right.png | Bin 0 -> 349 bytes .../design/gui/autocomplete/bullet_black.png | Bin 0 -> 221 bytes .../design/gui/autocomplete/osx_sizegrip.png | Bin 0 -> 4876 bytes .../fr/design/gui/borders/UIFrameBorder.java | 583 + .../gui/borders/UIInternalFrameBorder.java | 592 + .../gui/borders/UITableHeaderBorder.java | 66 + .../borders/UITableHeaderRolloverBorder.java | 37 + .../gui/borders/UITableScrollPaneBorder.java | 37 + .../design/gui/borders/UITextFieldBorder.java | 60 + .../gui/chart/BaseChartPropertyPane.java | 25 + .../gui/chart/MiddleChartComponent.java | 25 + .../design/gui/chart/MiddleChartDialog.java | 28 + .../design/gui/columnrow/ColumnRowPane.java | 258 + .../gui/columnrow/ColumnRowVerticalPane.java | 43 + .../controlpane/AbstractNameableCreator.java | 111 + .../design/gui/controlpane/ControlPane.java | 38 + .../design/gui/controlpane/JControlPane.java | 1026 + .../gui/controlpane/NameObjectCreator.java | 54 + .../gui/controlpane/NameableCreator.java | 25 + .../gui/controlpane/NameableSelfCreator.java | 23 + .../gui/controlpane/ObjectJControlPane.java | 76 + .../controlpane/ShortCut4JControlPane.java | 16 + .../gui/controlpane/UnrepeatedNameHelper.java | 5 + .../design/gui/core/CustomWidgetOption.java | 48 + .../gui/core/UIFurtherTabComponent.java | 24 + .../design/gui/core/UISelectedComponent.java | 32 + .../fr/design/gui/core/UITabComponent.java | 35 + .../gui/core/UserDefinedWidgetOption.java | 36 + .../fr/design/gui/core/WidgetConstants.java | 78 + .../com/fr/design/gui/core/WidgetOption.java | 228 + .../design/gui/core/WidgetOptionFactory.java | 17 + .../design/gui/date/CalendarNumberField.java | 108 + .../com/fr/design/gui/date/JDateDocument.java | 329 + .../gui/date/SingleObjectComboBoxModel.java | 72 + .../fr/design/gui/date/UICalendarPanel.java | 756 + .../com/fr/design/gui/date/UIDatePicker.java | 286 + .../com/fr/design/gui/date/UIDayLabel.java | 49 + .../com/fr/design/gui/demo/ComboBoxDemo.java | 176 + .../src/com/fr/design/gui/demo/LabelDemo.java | 62 + .../src/com/fr/design/gui/demo/ListDemo.java | 42 + .../fr/design/gui/demo/LoadingPaneDemo.java | 55 + .../design/gui/demo/MultiLineTooltipDemo.java | 34 + .../design/gui/demo/SwingComponentsDemo.java | 52 + .../gui/frpane/AbstractAttrNoScrollPane.java | 162 + .../gui/frpane/AttributeChangeListener.java | 7 + .../design/gui/frpane/BaseHyperlinkGroup.java | 23 + .../design/gui/frpane/CommitTabbedPane.java | 538 + .../gui/frpane/EditingStringListPane.java | 208 + .../design/gui/frpane/HyperlinkGroupPane.java | 90 + .../design/gui/frpane/HyperlinkGroupType.java | 18 + .../fr/design/gui/frpane/ImgChoosePane.java | 122 + .../design/gui/frpane/JTreeAutoBuildPane.java | 228 + .../design/gui/frpane/JTreeControlPane.java | 270 + .../fr/design/gui/frpane/LimitedDocument.java | 46 + .../design/gui/frpane/ListenerUpdatePane.java | 48 + .../design/gui/frpane/LoadingBasicPane.java | 84 + .../gui/frpane/LoadingBasicPaneTest.java | 41 + .../gui/frpane/ObjectProperiesPane.java | 164 + .../src/com/fr/design/gui/frpane/RegPane.java | 489 + .../frpane/ReportletParameterViewPane.java | 128 + .../gui/frpane/TemplateParameterPane.java | 89 + .../fr/design/gui/frpane/TreeSettingPane.java | 215 + .../design/gui/frpane/UIAdvancedTextPane.java | 197 + .../gui/frpane/UIBasicOptionPaneUI.java | 266 + .../design/gui/frpane/UIBubbleFloatPane.java | 318 + .../fr/design/gui/frpane/UIComboBoxPane.java | 145 + .../gui/frpane/UICorrelationComboBoxPane.java | 439 + .../design/gui/frpane/UICorrelationPane.java | 409 + .../fr/design/gui/frpane/UIExtensionPane.java | 1 + .../design/gui/frpane/UINumberDragPane.java | 136 + .../design/gui/frpane/UINumberSlidePane.java | 137 + .../com/fr/design/gui/frpane/UIRadioPane.java | 107 + .../fr/design/gui/frpane/UITabbedPane.java | 122 + .../fr/design/gui/frpane/UITabbedPaneUI.java | 431 + .../com/fr/design/gui/frpane/UITextPane.java | 90 + .../fr/design/gui/frpane/UITitlePanel.java | 46 + .../fr/design/gui/frpane/UnitInputPane.java | 170 + .../design/gui/ibutton/FiveButtonLayout.java | 55 + .../design/gui/ibutton/SpecialUIButton.java | 30 + .../design/gui/ibutton/UIBasicButtonUI.java | 346 + .../com/fr/design/gui/ibutton/UIButton.java | 361 + .../fr/design/gui/ibutton/UIButtonBorder.java | 84 + .../fr/design/gui/ibutton/UIButtonGroup.java | 421 + .../com/fr/design/gui/ibutton/UIButtonUI.java | 174 + .../fr/design/gui/ibutton/UIColorButton.java | 250 + .../gui/ibutton/UICombinationButton.java | 143 + .../fr/design/gui/ibutton/UIHeadGroup.java | 190 + .../design/gui/ibutton/UIPasswordField.java | 1 + .../design/gui/ibutton/UIPreviewButton.java | 1 + .../fr/design/gui/ibutton/UIRadioButton.java | 48 + .../design/gui/ibutton/UIRadioButtonIcon.java | 328 + .../gui/ibutton/UIRadioButtonMenuItemUI.java | 67 + .../design/gui/ibutton/UIRadioButtonUI.java | 112 + .../fr/design/gui/ibutton/UITabButton.java | 181 + .../com/fr/design/gui/ibutton/UITabGroup.java | 154 + .../fr/design/gui/ibutton/UIToggleButton.java | 176 + .../gui/ibutton/UIToolButtonBorder.java | 104 + .../fr/design/gui/icheckbox/UICheckBox.java | 201 + .../design/gui/icheckbox/UICheckBoxIcon.java | 314 + .../fr/design/gui/icheckbox/UICheckBoxUI.java | 88 + .../gui/icombobox/AlignmentComboBox.java | 83 + .../design/gui/icombobox/ComboCheckBox.java | 195 + .../gui/icombobox/DictionaryComboBox.java | 61 + .../gui/icombobox/DictionaryConstants.java | 86 + .../gui/icombobox/ExtendedComboBox.java | 114 + .../gui/icombobox/ExtendedComboBoxTest.java | 34 + .../design/gui/icombobox/FRTreeComboBox.java | 596 + .../design/gui/icombobox/FilterComboBox.java | 128 + .../icombobox/FilterableComboBoxModel.java | 103 + .../gui/icombobox/FixedHeightComboBox.java | 103 + .../gui/icombobox/FunctionComboBox.java | 69 + .../fr/design/gui/icombobox/IntComboBox.java | 51 + .../fr/design/gui/icombobox/LazyComboBox.java | 212 + .../gui/icombobox/LazyComboBoxTest.java | 62 + .../fr/design/gui/icombobox/LineComboBox.java | 148 + .../gui/icombobox/ParameterComboBox.java | 87 + .../gui/icombobox/SortOrderComboBox.java | 73 + .../design/gui/icombobox/TreeComboBoxUI.java | 95 + .../gui/icombobox/UIBasicComboBoxEditor.java | 107 + .../gui/icombobox/UIBasicComboBoxUI.java | 347 + .../fr/design/gui/icombobox/UIComboBox.java | 206 + .../gui/icombobox/UIComboBoxButton.java | 278 + .../gui/icombobox/UIComboBoxEditor.java | 88 + .../gui/icombobox/UIComboBoxRenderer.java | 35 + .../fr/design/gui/icombobox/UIComboBoxUI.java | 250 + .../gui/icombobox/UIDictionaryComboBox.java | 44 + .../design/gui/icombobox/filter/Filter.java | 8 + .../icombobox/filter/LastStartWithFilter.java | 18 + .../icombobox/filter/StartsWithFilter.java | 11 + .../icombotree/CheckBoxTreeCellRenderer.java | 86 + .../icombotree/CheckBoxTreeLabel.java | 73 + .../icombotree/CheckBoxTreeNode.java | 88 + .../CheckBoxTreeNodeSelectionListener.java | 65 + .../icontainer/UIModeControlContainer.java | 458 + .../gui/icontainer/UIResizableContainer.java | 469 + .../design/gui/icontainer/UIScrollPane.java | 44 + .../gui/icontainer/UIScrollPaneBorder.java | 33 + .../design/gui/icontainer/UIScrollPaneUI.java | 57 + .../icontainer/UITableScrollPaneBorder.java | 38 + .../gui/icontainer/UIVerticalScrollPane.java | 1 + .../com/fr/design/gui/ilable/ActionLabel.java | 87 + .../design/gui/ilable/BoldFontTextLabel.java | 36 + .../fr/design/gui/ilable/FRExplainLabel.java | 24 + .../fr/design/gui/ilable/MultilineLabel.java | 75 + .../src/com/fr/design/gui/ilable/UILabel.java | 61 + .../fr/design/gui/ilist/ArrayListModel.java | 24 + .../com/fr/design/gui/ilist/CheckBoxList.java | 311 + .../gui/ilist/DefaultListCellEditor.java | 50 + .../com/fr/design/gui/ilist/JNameEdList.java | 395 + .../fr/design/gui/ilist/ListCellEditor.java | 8 + .../fr/design/gui/ilist/ListModelElement.java | 1 + .../gui/ilist/ModNameActionListener.java | 11 + .../com/fr/design/gui/ilist/QuickList.java | 41 + .../fr/design/gui/ilist/TableViewList.java | 278 + .../src/com/fr/design/gui/ilist/UIList.java | 80 + .../design/gui/imenu/UIBasicMenuItemUI.java | 1095 + .../fr/design/gui/imenu/UIBasicMenuUI.java | 689 + .../design/gui/imenu/UICheckBoxMenuItem.java | 29 + .../com/fr/design/gui/imenu/UIListPopup.java | 183 + .../src/com/fr/design/gui/imenu/UIMenu.java | 57 + .../com/fr/design/gui/imenu/UIMenuBar.java | 29 + .../com/fr/design/gui/imenu/UIMenuBarUI.java | 33 + .../fr/design/gui/imenu/UIMenuHighLight.java | 25 + .../com/fr/design/gui/imenu/UIMenuItem.java | 107 + .../src/com/fr/design/gui/imenu/UIMenuUI.java | 83 + .../com/fr/design/gui/imenu/UIPopupMenu.java | 34 + .../design/gui/imenu/UIPopupMenuBorder.java | 62 + .../gui/imenu/UIPopupMenuSeparatorUI.java | 31 + .../com/fr/design/gui/imenu/UIScrollMenu.java | 312 + .../fr/design/gui/imenu/UIScrollMenuDemo.java | 71 + .../design/gui/imenu/UIScrollPopUpMenu.java | 221 + .../gui/imenutable/UIMenuNameableCreator.java | 65 + .../fr/design/gui/imenutable/UIMenuTable.java | 240 + .../gui/imenutable/UIMenuTableDataModel.java | 119 + .../design/gui/imenutable/UIMenuTableUI.java | 124 + .../gui/ipasswordfield/UIPassWordField.java | 35 + .../fr/design/gui/ipoppane/PopupHider.java | 5 + .../gui/iprogressbar/AutoProgressBar.java | 50 + .../gui/iprogressbar/FRProgressBar.java | 43 + .../gui/iprogressbar/MonitorCancelWork.java | 12 + .../gui/iprogressbar/UIProgressBarBorder.java | 67 + .../gui/iprogressbar/UIProgressBarUI.java | 409 + .../gui/iscrollbar/UIBasicScrollBarUI.java | 348 + .../fr/design/gui/iscrollbar/UISBChooser.java | 452 + .../fr/design/gui/iscrollbar/UIScrollBar.java | 50 + .../design/gui/iscrollbar/UIScrollBarUI.java | 1333 + .../design/gui/iscrollbar/UIScrollButton.java | 236 + .../com/fr/design/gui/islider/UISlider.java | 37 + .../design/gui/ispinner/UIBasicSpinner.java | 86 + .../com/fr/design/gui/ispinner/UISpinner.java | 350 + .../gui/ispinner/UISpinnerButtonUI.java | 146 + .../fr/design/gui/ispinner/UISpinnerUI.java | 275 + .../design/gui/ispinner/UpperCaseSpinner.java | 132 + .../isplitpanedivider/UISplitPaneDivider.java | 275 + .../gui/isplitpanedivider/UISplitPaneUI.java | 33 + .../gui/itable/AbstractPropertyTable.java | 248 + .../fr/design/gui/itable/GroupRenderer.java | 50 + .../fr/design/gui/itable/HeaderRenderer.java | 60 + .../fr/design/gui/itable/PropertyGroup.java | 58 + .../fr/design/gui/itable/SortableJTable.java | 10 + .../com/fr/design/gui/itable/TableSorter.java | 498 + .../fr/design/gui/itable/UIBasicTableUI.java | 40 + .../design/gui/itable/UIComponentTable.java | 35 + .../gui/itable/UIDefaultTableCellEditor.java | 1 + .../fr/design/gui/itable/UISelectTable.java | 108 + .../src/com/fr/design/gui/itable/UITable.java | 388 + .../gui/itable/UITableComponentModel.java | 23 + .../design/gui/itable/UITableDataModel.java | 146 + .../fr/design/gui/itable/UITableEditor.java | 1 + .../design/gui/itable/UITableNoOptionUI.java | 25 + .../com/fr/design/gui/itable/UITableUI.java | 225 + .../gui/itableeditorpane/ActionStyle.java | 16 + .../itableeditorpane/ParameterTableModel.java | 258 + .../itableeditorpane/UIArrayTableModel.java | 74 + .../itableeditorpane/UITableEditAction.java | 8 + .../itableeditorpane/UITableEditorLoader.java | 12 + .../itableeditorpane/UITableEditorPane.java | 148 + .../itableeditorpane/UITableModelAdapter.java | 330 + .../gui/itabpane/TitleChangeListener.java | 6 + .../design/gui/itabpane/UITabPaneCreator.java | 44 + .../gui/itabpane/UITabsHeaderIconPane.java | 264 + .../gui/itextarea/DescriptionTextArea.java | 27 + .../gui/itextarea/FRExplainTextArea.java | 66 + .../fr/design/gui/itextarea/UITextArea.java | 131 + .../fr/design/gui/itextarea/UITextAreaUI.java | 56 + .../gui/itextfield/AutoCompletionDemo.java | 76 + .../gui/itextfield/CompletionFilter.java | 8 + .../itextfield/DefaultCompletionFilter.java | 28 + .../design/gui/itextfield/EditTextField.java | 55 + .../design/gui/itextfield/FRGraphics2D.java | 397 + .../gui/itextfield/PlaceholderTextField.java | 54 + .../fr/design/gui/itextfield/TextFieldUI.java | 53 + .../gui/itextfield/UIAutoCompletionField.java | 280 + .../gui/itextfield/UIGridTextField.java | 1 + .../design/gui/itextfield/UINumberField.java | 250 + .../gui/itextfield/UISearchTextField.java | 1 + .../fr/design/gui/itextfield/UITextField.java | 210 + .../design/gui/itextfield/UITextFieldUI.java | 77 + .../design/gui/itoolbar/UILargeToolbar.java | 18 + .../design/gui/itoolbar/UIToolBarBorder.java | 106 + .../gui/itoolbar/UIToolBarSeparatorUI.java | 98 + .../fr/design/gui/itoolbar/UIToolBarUI.java | 124 + .../com/fr/design/gui/itoolbar/UIToolbar.java | 37 + .../design/gui/itooltip/MultiLineToolTip.java | 10 + .../gui/itooltip/MultiLineToolTipUI.java | 84 + .../com/fr/design/gui/itooltip/UIToolTip.java | 88 + .../design/gui/itooltip/UIToolTipBorder.java | 44 + .../fr/design/gui/itooltip/UIToolTipUI.java | 118 + .../src/com/fr/design/gui/itree/UITreeUI.java | 40 + .../gui/itree/checkboxtree/CheckBoxTree.java | 464 + .../CheckBoxTreeCellRenderer.java | 134 + .../CheckBoxTreeSelectionModel.java | 483 + .../gui/itree/checkboxtree/NullLabel.java | 86 + .../gui/itree/checkboxtree/NullPanel.java | 79 + .../checkboxtree/NullTristateCheckBox.java | 77 + .../itree/checkboxtree/TristateCheckBox.java | 307 + .../gui/itree/filetree/AbstractFileTree.java | 105 + .../gui/itree/filetree/ClassFileTree.java | 63 + .../gui/itree/filetree/EnvFileTree.java | 366 + .../gui/itree/filetree/FileComparator.java | 23 + .../gui/itree/filetree/FileDirectoryNode.java | 56 + .../itree/filetree/FileNodeComparator.java | 78 + .../gui/itree/filetree/FileTreeIcon.java | 274 + .../design/gui/itree/filetree/JFileTree.java | 324 + .../gui/itree/filetree/ReportletPane.java | 136 + .../design/gui/itree/filetree/RootFile.java | 28 + .../gui/itree/filetree/TemplateFileTree.java | 69 + .../ExpandMutableTreeNode.java | 78 + .../refreshabletree/RefreshableJTree.java | 281 + .../refreshabletree/RefreshableJTreeTest.java | 85 + .../refreshabletree/TreeDataCardPane.java | 55 + .../itree/refreshabletree/TreeNodePane.java | 46 + .../itree/refreshabletree/TreeRootPane.java | 83 + .../itree/refreshabletree/UserObjectOP.java | 33 + .../UserObjectRefreshJTree.java | 167 + .../loader/ChildrenLoaderFactory.java | 17 + .../loader/ChildrenNodesLoader.java | 29 + .../gui/style/AbstractBasicStylePane.java | 29 + .../fr/design/gui/style/AlignmentPane.java | 390 + .../gui/style/BackgroundNoImagePane.java | 44 + .../fr/design/gui/style/BackgroundPane.java | 148 + .../gui/style/BackgroundSpecialPane.java | 54 + .../com/fr/design/gui/style/BorderPane.java | 206 + .../DefaultIndentationUnitProcessor.java | 36 + .../com/fr/design/gui/style/FRFontPane.java | 394 + .../com/fr/design/gui/style/FormatPane.java | 401 + .../design/gui/style/FormatePaneNumField.java | 44 + .../com/fr/design/gui/style/GradientPane.java | 123 + .../fr/design/gui/style/NumberDragBar.java | 224 + .../design/gui/syntax/io/DocumentReader.java | 218 + .../design/gui/syntax/io/UnicodeReader.java | 270 + .../design/gui/syntax/io/UnicodeWriter.java | 258 + .../com/fr/design/gui/syntax/io/package.html | 5 + .../gui/syntax/print/RPrintUtilities.java | 530 + .../fr/design/gui/syntax/print/package.html | 5 + .../AbstractJFlexCTokenMaker.java | 243 + .../AbstractJFlexTokenMaker.java | 52 + .../rsyntaxtextarea/AbstractTokenMaker.java | 67 + .../AbstractTokenMakerFactory.java | 134 + .../rsyntaxtextarea/ActiveLineRangeEvent.java | 68 + .../ActiveLineRangeListener.java | 44 + .../ChangeableColorHighlightPainter.java | 67 + .../rsyntaxtextarea/CodeTemplateManager.java | 389 + .../DefaultOccurrenceMarker.java | 55 + .../rsyntaxtextarea/DefaultTokenFactory.java | 137 + .../DefaultTokenMakerFactory.java | 75 + .../rsyntaxtextarea/DefaultTokenPainter.java | 268 + .../ui/rsyntaxtextarea/DocumentRange.java | 153 + .../syntax/ui/rsyntaxtextarea/ErrorStrip.java | 843 + .../ui/rsyntaxtextarea/ErrorStrip.properties | 3 + .../rsyntaxtextarea/ErrorStrip_ar.properties | 3 + .../rsyntaxtextarea/ErrorStrip_de.properties | 3 + .../rsyntaxtextarea/ErrorStrip_es.properties | 3 + .../rsyntaxtextarea/ErrorStrip_fr.properties | 3 + .../rsyntaxtextarea/ErrorStrip_hu.properties | 3 + .../rsyntaxtextarea/ErrorStrip_in.properties | 3 + .../rsyntaxtextarea/ErrorStrip_it.properties | 3 + .../rsyntaxtextarea/ErrorStrip_ja.properties | 3 + .../rsyntaxtextarea/ErrorStrip_ko.properties | 3 + .../rsyntaxtextarea/ErrorStrip_nl.properties | 3 + .../rsyntaxtextarea/ErrorStrip_pl.properties | 3 + .../ErrorStrip_pt_BR.properties | 3 + .../rsyntaxtextarea/ErrorStrip_ru.properties | 3 + .../rsyntaxtextarea/ErrorStrip_tr.properties | 3 + .../ErrorStrip_zh_CN.properties | 3 + .../ErrorStrip_zh_TW.properties | 3 + .../ui/rsyntaxtextarea/FileFileLocation.java | 121 + .../ui/rsyntaxtextarea/FileLocation.java | 141 + .../FoldingAwareIconRowHeader.java | 248 + .../ui/rsyntaxtextarea/LinkGenerator.java | 50 + .../rsyntaxtextarea/LinkGeneratorResult.java | 53 + .../MarkOccurrencesHighlightPainter.java | 139 + .../MarkOccurrencesSupport.java | 316 + .../ui/rsyntaxtextarea/OccurrenceMarker.java | 38 + .../ui/rsyntaxtextarea/ParserManager.java | 745 + .../rsyntaxtextarea/PopupWindowDecorator.java | 68 + .../syntax/ui/rsyntaxtextarea/RSTAView.java | 62 + .../ui/rsyntaxtextarea/RSyntaxDocument.java | 639 + .../ui/rsyntaxtextarea/RSyntaxTextArea.java | 3128 ++ .../RSyntaxTextArea.properties | 14 + .../RSyntaxTextAreaDefaultInputMap.java | 77 + .../RSyntaxTextAreaEditorKit.java | 1943 ++ .../RSyntaxTextAreaHighlighter.java | 275 + .../ui/rsyntaxtextarea/RSyntaxTextAreaUI.java | 265 + .../RSyntaxTextArea_ar.properties | 14 + .../RSyntaxTextArea_de.properties | 14 + .../RSyntaxTextArea_es.properties | 14 + .../RSyntaxTextArea_fr.properties | 14 + .../RSyntaxTextArea_hu.properties | 14 + .../RSyntaxTextArea_in.properties | 14 + .../RSyntaxTextArea_it.properties | 14 + .../RSyntaxTextArea_ja.properties | 14 + .../RSyntaxTextArea_ko.properties | 14 + .../RSyntaxTextArea_nl.properties | 14 + .../RSyntaxTextArea_pl.properties | 15 + .../RSyntaxTextArea_pt_BR.properties | 14 + .../RSyntaxTextArea_ru.properties | 14 + .../RSyntaxTextArea_tr.properties | 14 + .../RSyntaxTextArea_zh_CN.properties | 14 + .../RSyntaxTextArea_zh_TW.properties | 14 + .../ui/rsyntaxtextarea/RSyntaxUtilities.java | 1310 + .../syntax/ui/rsyntaxtextarea/RTfToText.java | 229 + .../ui/rsyntaxtextarea/RtfGenerator.java | 479 + .../ui/rsyntaxtextarea/RtfTransferable.java | 91 + .../SelectRegionLinkGeneratorResult.java | 59 + .../SquiggleUnderlineHighlightPainter.java | 120 + .../gui/syntax/ui/rsyntaxtextarea/Style.java | 196 + .../ui/rsyntaxtextarea/SyntaxConstants.java | 264 + .../ui/rsyntaxtextarea/SyntaxScheme.java | 715 + .../syntax/ui/rsyntaxtextarea/SyntaxView.java | 1008 + .../ui/rsyntaxtextarea/TextEditorPane.java | 711 + .../gui/syntax/ui/rsyntaxtextarea/Theme.java | 847 + .../gui/syntax/ui/rsyntaxtextarea/Token.java | 566 + .../ui/rsyntaxtextarea/TokenFactory.java | 67 + .../syntax/ui/rsyntaxtextarea/TokenImpl.java | 836 + .../ui/rsyntaxtextarea/TokenIterator.java | 91 + .../syntax/ui/rsyntaxtextarea/TokenMaker.java | 170 + .../ui/rsyntaxtextarea/TokenMakerBase.java | 300 + .../ui/rsyntaxtextarea/TokenMakerFactory.java | 124 + .../syntax/ui/rsyntaxtextarea/TokenMap.java | 277 + .../ui/rsyntaxtextarea/TokenOrientedView.java | 61 + .../ui/rsyntaxtextarea/TokenPainter.java | 96 + .../syntax/ui/rsyntaxtextarea/TokenTypes.java | 85 + .../syntax/ui/rsyntaxtextarea/TokenUtils.java | 166 + .../ui/rsyntaxtextarea/URLFileLocation.java | 160 + .../VisibleWhitespaceTokenPainter.java | 191 + .../ui/rsyntaxtextarea/WrappedSyntaxView.java | 1418 + .../rsyntaxtextarea/WrappedSyntaxView2.java | 157 + .../rsyntaxtextarea/XmlOccurrenceMarker.java | 187 + .../focusabletip/FocusableTip.java | 346 + .../focusabletip/FocusableTip.properties | 1 + .../focusabletip/FocusableTip_ar.properties | 1 + .../focusabletip/FocusableTip_de.properties | 1 + .../focusabletip/FocusableTip_es.properties | 1 + .../focusabletip/FocusableTip_fr.properties | 1 + .../focusabletip/FocusableTip_hu.properties | 1 + .../focusabletip/FocusableTip_in.properties | 1 + .../focusabletip/FocusableTip_it.properties | 1 + .../focusabletip/FocusableTip_ja.properties | 1 + .../focusabletip/FocusableTip_ko.properties | 1 + .../focusabletip/FocusableTip_nl.properties | 1 + .../focusabletip/FocusableTip_pl.properties | 1 + .../FocusableTip_pt_BR.properties | 1 + .../focusabletip/FocusableTip_ru.properties | 1 + .../focusabletip/FocusableTip_tr.properties | 1 + .../FocusableTip_zh_CN.properties | 1 + .../FocusableTip_zh_TW.properties | 1 + .../focusabletip/SizeGrip.java | 255 + .../rsyntaxtextarea/focusabletip/TipUtil.java | 235 + .../focusabletip/TipWindow.java | 341 + .../focusabletip/osx_sizegrip.png | Bin 0 -> 4876 bytes .../rsyntaxtextarea/focusabletip/package.html | 5 + .../folding/CurlyFoldParser.java | 317 + .../ui/rsyntaxtextarea/folding/Fold.java | 567 + .../folding/FoldCollapser.java | 106 + .../rsyntaxtextarea/folding/FoldManager.java | 707 + .../rsyntaxtextarea/folding/FoldParser.java | 41 + .../folding/FoldParserManager.java | 124 + .../ui/rsyntaxtextarea/folding/FoldType.java | 59 + .../folding/HtmlFoldParser.java | 403 + .../folding/JsonFoldParser.java | 161 + .../folding/LatexFoldParser.java | 108 + .../folding/LispFoldParser.java | 35 + .../folding/NsisFoldParser.java | 156 + .../folding/XmlFoldParser.java | 148 + .../ui/rsyntaxtextarea/folding/package.html | 5 + .../modes/AbstractMarkupTokenMaker.java | 56 + .../modes/ActionScriptTokenMaker.flex | 500 + .../modes/ActionScriptTokenMaker.java | 2074 ++ .../modes/AssemblerX86TokenMaker.flex | 1037 + .../modes/AssemblerX86TokenMaker.java | 1870 ++ .../modes/BBCodeTokenMaker.flex | 273 + .../modes/BBCodeTokenMaker.java | 729 + .../modes/CPlusPlusTokenMaker.flex | 671 + .../modes/CPlusPlusTokenMaker.java | 2322 ++ .../rsyntaxtextarea/modes/CSSTokenMaker.flex | 414 + .../rsyntaxtextarea/modes/CSSTokenMaker.java | 979 + .../modes/CSharpTokenMaker.flex | 519 + .../modes/CSharpTokenMaker.java | 1603 + .../ui/rsyntaxtextarea/modes/CTokenMaker.flex | 645 + .../ui/rsyntaxtextarea/modes/CTokenMaker.java | 2075 ++ .../modes/ClojureTokenMaker.flex | 566 + .../modes/ClojureTokenMaker.java | 2309 ++ .../modes/DelphiTokenMaker.flex | 564 + .../modes/DelphiTokenMaker.java | 1634 + .../rsyntaxtextarea/modes/DtdTokenMaker.flex | 346 + .../rsyntaxtextarea/modes/DtdTokenMaker.java | 831 + .../modes/FormulaTokenMaker.flex | 702 + .../modes/FormulaTokenMaker.java | 3227 ++ .../modes/FortranTokenMaker.flex | 482 + .../modes/FortranTokenMaker.java | 1014 + .../modes/GroovyTokenMaker.flex | 890 + .../modes/GroovyTokenMaker.java | 5272 ++++ .../rsyntaxtextarea/modes/HTMLTokenMaker.flex | 1189 + .../rsyntaxtextarea/modes/HTMLTokenMaker.java | 2987 ++ .../modes/HtaccessTokenMaker.flex | 500 + .../modes/HtaccessTokenMaker.java | 1505 + .../rsyntaxtextarea/modes/JSPTokenMaker.flex | 1565 + .../rsyntaxtextarea/modes/JSPTokenMaker.java | 5319 ++++ .../modes/JavaScriptTokenMaker.flex | 890 + .../modes/JavaScriptTokenMaker.java | 2134 ++ .../rsyntaxtextarea/modes/JavaTokenMaker.flex | 756 + .../rsyntaxtextarea/modes/JavaTokenMaker.java | 4969 +++ .../rsyntaxtextarea/modes/JsonTokenMaker.flex | 261 + .../rsyntaxtextarea/modes/JsonTokenMaker.java | 704 + .../modes/LatexTokenMaker.flex | 270 + .../modes/LatexTokenMaker.java | 719 + .../rsyntaxtextarea/modes/LispTokenMaker.flex | 434 + .../rsyntaxtextarea/modes/LispTokenMaker.java | 1311 + .../rsyntaxtextarea/modes/LuaTokenMaker.flex | 374 + .../rsyntaxtextarea/modes/LuaTokenMaker.java | 970 + .../modes/MakefileTokenMaker.flex | 338 + .../modes/MakefileTokenMaker.java | 867 + .../rsyntaxtextarea/modes/MxmlTokenMaker.flex | 811 + .../rsyntaxtextarea/modes/MxmlTokenMaker.java | 2708 ++ .../rsyntaxtextarea/modes/NSISTokenMaker.flex | 747 + .../rsyntaxtextarea/modes/NSISTokenMaker.java | 2982 ++ .../rsyntaxtextarea/modes/PHPTokenMaker.flex | 2323 ++ .../rsyntaxtextarea/modes/PHPTokenMaker.java | 25471 ++++++++++++++++ .../rsyntaxtextarea/modes/PerlTokenMaker.flex | 812 + .../rsyntaxtextarea/modes/PerlTokenMaker.java | 2110 ++ .../modes/PlainTextTokenMaker.flex | 227 + .../modes/PlainTextTokenMaker.java | 647 + .../modes/PropertiesFileTokenMaker.flex | 237 + .../modes/PropertiesFileTokenMaker.java | 664 + .../modes/PythonTokenMaker.flex | 443 + .../modes/PythonTokenMaker.java | 1092 + .../rsyntaxtextarea/modes/RubyTokenMaker.flex | 765 + .../rsyntaxtextarea/modes/RubyTokenMaker.java | 1670 + .../rsyntaxtextarea/modes/SASTokenMaker.flex | 677 + .../rsyntaxtextarea/modes/SASTokenMaker.java | 1492 + .../rsyntaxtextarea/modes/SQLTokenMaker.flex | 465 + .../rsyntaxtextarea/modes/SQLTokenMaker.java | 1129 + .../modes/ScalaTokenMaker.flex | 388 + .../modes/ScalaTokenMaker.java | 998 + .../rsyntaxtextarea/modes/TclTokenMaker.flex | 406 + .../rsyntaxtextarea/modes/TclTokenMaker.java | 1078 + .../modes/UnixShellTokenMaker.java | 1117 + .../modes/VisualBasicTokenMaker.flex | 464 + .../modes/VisualBasicTokenMaker.java | 1622 + .../modes/WindowsBatchTokenMaker.java | 605 + .../rsyntaxtextarea/modes/XMLTokenMaker.flex | 487 + .../rsyntaxtextarea/modes/XMLTokenMaker.java | 997 + .../ui/rsyntaxtextarea/modes/package.html | 5 + .../syntax/ui/rsyntaxtextarea/package.html | 5 + .../parser/AbstractParser.java | 95 + .../parser/DefaultParseResult.java | 145 + .../parser/DefaultParserNotice.java | 273 + .../parser/ExtendedHyperlinkListener.java | 38 + .../rsyntaxtextarea/parser/ParseResult.java | 84 + .../ui/rsyntaxtextarea/parser/Parser.java | 76 + .../rsyntaxtextarea/parser/ParserNotice.java | 130 + .../rsyntaxtextarea/parser/TaskTagParser.java | 158 + .../rsyntaxtextarea/parser/ToolTipInfo.java | 95 + .../ui/rsyntaxtextarea/parser/XmlParser.java | 224 + .../ui/rsyntaxtextarea/parser/package.html | 9 + .../templates/AbstractCodeTemplate.java | 134 + .../templates/CodeTemplate.java | 74 + .../templates/StaticCodeTemplate.java | 263 + .../ui/rsyntaxtextarea/templates/package.html | 5 + .../ui/rtextarea/AbstractGutterComponent.java | 114 + .../rtextarea/BackgroundPainterStrategy.java | 44 + ...ufferedImageBackgroundPainterStrategy.java | 124 + .../rtextarea/ChangeableHighlightPainter.java | 440 + .../ColorBackgroundPainterStrategy.java | 110 + .../ui/rtextarea/ConfigurableCaret.java | 712 + .../syntax/ui/rtextarea/FoldIndicator.java | 696 + .../gui/syntax/ui/rtextarea/Gutter.java | 969 + .../syntax/ui/rtextarea/GutterIconInfo.java | 53 + .../gui/syntax/ui/rtextarea/IconGroup.java | 247 + .../syntax/ui/rtextarea/IconRowHeader.java | 875 + .../ImageBackgroundPainterStrategy.java | 171 + .../ui/rtextarea/LineHighlightManager.java | 208 + .../syntax/ui/rtextarea/LineNumberList.java | 718 + .../design/gui/syntax/ui/rtextarea/Macro.java | 427 + .../gui/syntax/ui/rtextarea/RDocument.java | 65 + .../ui/rtextarea/RDocumentCharSequence.java | 119 + .../ui/rtextarea/RTADefaultInputMap.java | 151 + .../ui/rtextarea/RTATextTransferHandler.java | 485 + .../gui/syntax/ui/rtextarea/RTextArea.java | 1710 ++ .../syntax/ui/rtextarea/RTextArea.properties | 29 + .../syntax/ui/rtextarea/RTextAreaBase.java | 1214 + .../ui/rtextarea/RTextAreaEditorKit.java | 2689 ++ .../ui/rtextarea/RTextAreaHighlighter.java | 379 + .../gui/syntax/ui/rtextarea/RTextAreaUI.java | 590 + .../ui/rtextarea/RTextArea_ar.properties | 29 + .../ui/rtextarea/RTextArea_de.properties | 29 + .../ui/rtextarea/RTextArea_es.properties | 29 + .../ui/rtextarea/RTextArea_fr.properties | 29 + .../ui/rtextarea/RTextArea_hu.properties | 29 + .../ui/rtextarea/RTextArea_in.properties | 29 + .../ui/rtextarea/RTextArea_it.properties | 29 + .../ui/rtextarea/RTextArea_ja.properties | 29 + .../ui/rtextarea/RTextArea_ko.properties | 29 + .../ui/rtextarea/RTextArea_nl.properties | 29 + .../ui/rtextarea/RTextArea_pl.properties | 29 + .../ui/rtextarea/RTextArea_pt_BR.properties | 29 + .../ui/rtextarea/RTextArea_ru.properties | 29 + .../ui/rtextarea/RTextArea_tr.properties | 29 + .../ui/rtextarea/RTextArea_zh_CN.properties | 29 + .../ui/rtextarea/RTextArea_zh_TW.properties | 29 + .../syntax/ui/rtextarea/RTextScrollPane.java | 286 + .../gui/syntax/ui/rtextarea/RUndoManager.java | 258 + .../ui/rtextarea/RecordableTextAction.java | 289 + .../syntax/ui/rtextarea/RegExReplaceInfo.java | 85 + .../syntax/ui/rtextarea/SearchContext.java | 391 + .../gui/syntax/ui/rtextarea/SearchEngine.java | 1017 + .../gui/syntax/ui/rtextarea/SearchResult.java | 244 + .../ui/rtextarea/SmartHighlightPainter.java | 159 + .../syntax/ui/rtextarea/ToolTipSupplier.java | 39 + ...olatileImageBackgroundPainterStrategy.java | 138 + .../gui/syntax/ui/rtextarea/package.html | 5 + .../gui/syntax/util/DynamicIntArray.java | 423 + .../fr/design/gui/syntax/util/package.html | 5 + .../src/com/fr/design/gui/toast/Toast.java | 147 + .../hyperlink/AbstractHyperlinkPane.java | 135 + .../hyperlink/ReporletHyperNorthPane.java | 189 + .../hyperlink/ReportletHyperlinkPane.java | 204 + .../design/hyperlink/WebHyperNorthPane.java | 112 + .../fr/design/hyperlink/WebHyperlinkPane.java | 164 + .../src/com/fr/design/icon/BorderIcon.java | 90 + .../com/fr/design/icon/IconPathConstants.java | 1 + .../src/com/fr/design/icon/LockIcon.java | 105 + .../src/com/fr/design/icon/WarningIcon.java | 109 + .../com/fr/design/images/arrow/arrow_down.png | Bin 0 -> 222 bytes .../com/fr/design/images/arrow/arrow_up.png | Bin 0 -> 216 bytes .../src/com/fr/design/images/browser/360.png | Bin 0 -> 1914 bytes .../src/com/fr/design/images/browser/back.png | Bin 0 -> 1099 bytes .../com/fr/design/images/browser/chrome.png | Bin 0 -> 1781 bytes .../com/fr/design/images/browser/firefox.png | Bin 0 -> 2015 bytes .../com/fr/design/images/browser/forward.png | Bin 0 -> 1101 bytes .../src/com/fr/design/images/browser/go.png | Bin 0 -> 1155 bytes .../src/com/fr/design/images/browser/home.png | Bin 0 -> 1162 bytes .../src/com/fr/design/images/browser/ie.png | Bin 0 -> 4580 bytes .../com/fr/design/images/browser/reload.png | Bin 0 -> 1256 bytes .../src/com/fr/design/images/browser/stop.png | Bin 0 -> 1218 bytes .../com/fr/design/images/buttonicon/add.png | Bin 0 -> 275 bytes .../fr/design/images/buttonicon/add_over.png | Bin 0 -> 3639 bytes .../fr/design/images/buttonicon/add_press.png | Bin 0 -> 1120 bytes .../fr/design/images/buttonicon/addicon.png | Bin 0 -> 1081 bytes .../images/buttonicon/additicon_grey.png | Bin 0 -> 515 bytes .../fr/design/images/buttonicon/anab24.png | Bin 0 -> 553 bytes .../com/fr/design/images/buttonicon/anas.png | Bin 0 -> 402 bytes .../com/fr/design/images/buttonicon/arrow.png | Bin 0 -> 2869 bytes .../fr/design/images/buttonicon/arrowdown.png | Bin 0 -> 2869 bytes .../fr/design/images/buttonicon/arrowup.png | Bin 0 -> 2854 bytes .../images/buttonicon/bind_ds_column.png | Bin 0 -> 1098 bytes .../fr/design/images/buttonicon/button_0.png | Bin 0 -> 823 bytes .../com/fr/design/images/buttonicon/cell.png | Bin 0 -> 1128 bytes .../design/images/buttonicon/cell_group.png | Bin 0 -> 2955 bytes .../design/images/buttonicon/close_icon.png | Bin 0 -> 2863 bytes .../fr/design/images/buttonicon/column.png | Bin 0 -> 325 bytes .../com/fr/design/images/buttonicon/cube.png | Bin 0 -> 431 bytes .../fr/design/images/buttonicon/ds_column.png | Bin 0 -> 338 bytes .../images/buttonicon/ds_column_index.png | Bin 0 -> 1682 bytes .../images/buttonicon/ds_column_name.png | Bin 0 -> 1295 bytes .../fr/design/images/buttonicon/dscolumn.png | Bin 0 -> 1098 bytes .../com/fr/design/images/buttonicon/editn.png | Bin 0 -> 469 bytes .../com/fr/design/images/buttonicon/editp.png | Bin 0 -> 542 bytes .../com/fr/design/images/buttonicon/hiden.png | Bin 0 -> 659 bytes .../com/fr/design/images/buttonicon/hidep.png | Bin 0 -> 759 bytes .../fr/design/images/buttonicon/history.png | Bin 0 -> 3098 bytes .../design/images/buttonicon/list_cover.png | Bin 0 -> 3469 bytes .../design/images/buttonicon/list_covered.png | Bin 0 -> 3003 bytes .../fr/design/images/buttonicon/list_icon.png | Bin 0 -> 2894 bytes .../design/images/buttonicon/list_normal.png | Bin 0 -> 1020 bytes .../design/images/buttonicon/list_press.png | Bin 0 -> 3091 bytes .../design/images/buttonicon/list_pressed.png | Bin 0 -> 1046 bytes .../com/fr/design/images/buttonicon/minus.png | Bin 0 -> 155 bytes .../com/fr/design/images/buttonicon/more.png | Bin 0 -> 3924 bytes .../com/fr/design/images/buttonicon/more2.png | Bin 0 -> 3776 bytes .../com/fr/design/images/buttonicon/more3.png | Bin 0 -> 3934 bytes .../com/fr/design/images/buttonicon/more4.png | Bin 0 -> 3893 bytes .../images/buttonicon/mouseoverclose icon.png | Bin 0 -> 3086 bytes .../fr/design/images/buttonicon/newcpts.png | Bin 0 -> 251 bytes .../com/fr/design/images/buttonicon/open.png | Bin 0 -> 402 bytes .../fr/design/images/buttonicon/pageb24.png | Bin 0 -> 491 bytes .../com/fr/design/images/buttonicon/pages.png | Bin 0 -> 415 bytes .../fr/design/images/buttonicon/parameter.png | Bin 0 -> 1350 bytes .../com/fr/design/images/buttonicon/plus.png | Bin 0 -> 166 bytes .../images/buttonicon/pressclose icon.png | Bin 0 -> 3162 bytes .../images/buttonicon/prevew_down_icon.png | Bin 0 -> 2870 bytes .../fr/design/images/buttonicon/prewidget.png | Bin 0 -> 3549 bytes .../com/fr/design/images/buttonicon/redo.png | Bin 0 -> 318 bytes .../fr/design/images/buttonicon/refresh.png | Bin 0 -> 345 bytes .../com/fr/design/images/buttonicon/run24.png | Bin 0 -> 502 bytes .../com/fr/design/images/buttonicon/runs.png | Bin 0 -> 412 bytes .../com/fr/design/images/buttonicon/save.png | Bin 0 -> 218 bytes .../fr/design/images/buttonicon/select.png | Bin 0 -> 471 bytes .../design/images/buttonicon/select_item.png | Bin 0 -> 15022 bytes .../fr/design/images/buttonicon/setting.png | Bin 0 -> 3180 bytes .../images/buttonicon/switchShortCuts.png | Bin 0 -> 342 bytes .../fr/design/images/buttonicon/type_bool.png | Bin 0 -> 2925 bytes .../design/images/buttonicon/type_cursor.png | Bin 0 -> 3487 bytes .../fr/design/images/buttonicon/type_date.png | Bin 0 -> 1339 bytes .../design/images/buttonicon/type_double.png | Bin 0 -> 1381 bytes .../design/images/buttonicon/type_formula.png | Bin 0 -> 1357 bytes .../fr/design/images/buttonicon/type_int.png | Bin 0 -> 1682 bytes .../fr/design/images/buttonicon/type_none.png | Bin 0 -> 3332 bytes .../design/images/buttonicon/type_string.png | Bin 0 -> 1295 bytes .../com/fr/design/images/buttonicon/undo.png | Bin 0 -> 343 bytes .../com/fr/design/images/buttonicon/viewn.png | Bin 0 -> 3486 bytes .../com/fr/design/images/buttonicon/viewp.png | Bin 0 -> 3484 bytes .../com/fr/design/images/buttonicon/warn.png | Bin 0 -> 2864 bytes .../fr/design/images/buttonicon/widgets.png | Bin 0 -> 301 bytes .../fr/design/images/buttonicon/writeb24.png | Bin 0 -> 717 bytes .../fr/design/images/buttonicon/writes.png | Bin 0 -> 515 bytes .../com/fr/design/images/buttonicon/yes.png | Bin 0 -> 1050 bytes .../fr/design/images/calculate/average.png | Bin 0 -> 307 bytes .../com/fr/design/images/calculate/count.png | Bin 0 -> 310 bytes .../com/fr/design/images/calculate/max.png | Bin 0 -> 321 bytes .../com/fr/design/images/calculate/min.png | Bin 0 -> 283 bytes .../com/fr/design/images/calculate/none.png | Bin 0 -> 326 bytes .../com/fr/design/images/calculate/sum.png | Bin 0 -> 297 bytes .../fr/design/images/calender/month_add.png | Bin 0 -> 2990 bytes .../images/calender/month_add_click.png | Bin 0 -> 2990 bytes .../images/calender/month_add_hover.png | Bin 0 -> 2990 bytes .../design/images/calender/month_reduce.png | Bin 0 -> 2990 bytes .../images/calender/month_reduce_click.png | Bin 0 -> 2990 bytes .../images/calender/month_reduce_hover.png | Bin 0 -> 2990 bytes .../fr/design/images/calender/year_add.png | Bin 0 -> 3214 bytes .../design/images/calender/year_add_click.png | Bin 0 -> 3214 bytes .../design/images/calender/year_add_hover.png | Bin 0 -> 3214 bytes .../fr/design/images/calender/year_reduce.png | Bin 0 -> 3214 bytes .../images/calender/year_reduce_click.png | Bin 0 -> 3214 bytes .../images/calender/year_reduce_hover.png | Bin 0 -> 3214 bytes .../design/images/chart/AreaPlot/layout/0.png | Bin 0 -> 4660 bytes .../design/images/chart/AreaPlot/layout/1.png | Bin 0 -> 3929 bytes .../design/images/chart/AreaPlot/layout/2.png | Bin 0 -> 4138 bytes .../design/images/chart/AreaPlot/layout/3.png | Bin 0 -> 4437 bytes .../design/images/chart/AreaPlot/type/0.png | Bin 0 -> 1907 bytes .../design/images/chart/AreaPlot/type/1.png | Bin 0 -> 1089 bytes .../design/images/chart/AreaPlot/type/2.png | Bin 0 -> 994 bytes .../design/images/chart/AreaPlot/type/3.png | Bin 0 -> 770 bytes .../design/images/chart/AreaPlot/type/4.png | Bin 0 -> 994 bytes .../design/images/chart/AreaPlot/type/5.png | Bin 0 -> 770 bytes .../design/images/chart/BarPlot/layout/0.png | Bin 0 -> 3385 bytes .../design/images/chart/BarPlot/layout/1.png | Bin 0 -> 3085 bytes .../design/images/chart/BarPlot/layout/2.png | Bin 0 -> 3054 bytes .../design/images/chart/BarPlot/layout/3.png | Bin 0 -> 3874 bytes .../fr/design/images/chart/BarPlot/type/0.png | Bin 0 -> 616 bytes .../fr/design/images/chart/BarPlot/type/1.png | Bin 0 -> 569 bytes .../fr/design/images/chart/BarPlot/type/2.png | Bin 0 -> 567 bytes .../fr/design/images/chart/BarPlot/type/3.png | Bin 0 -> 694 bytes .../fr/design/images/chart/BarPlot/type/4.png | Bin 0 -> 1300 bytes .../fr/design/images/chart/BarPlot/type/5.png | Bin 0 -> 748 bytes .../fr/design/images/chart/BarPlot/type/6.png | Bin 0 -> 732 bytes .../images/chart/BubblePlot/layout/0.png | Bin 0 -> 3808 bytes .../images/chart/BubblePlot/layout/1.png | Bin 0 -> 3802 bytes .../images/chart/BubblePlot/layout/2.png | Bin 0 -> 3877 bytes .../images/chart/BubblePlot/layout/3.png | Bin 0 -> 3861 bytes .../design/images/chart/BubblePlot/type/0.png | Bin 0 -> 4185 bytes .../fr/design/images/chart/ChangeChart.png | Bin 0 -> 877 bytes .../images/chart/ChartAxisLineStyle/cross.png | Bin 0 -> 2866 bytes .../chart/ChartAxisLineStyle/external.png | Bin 0 -> 2852 bytes .../chart/ChartAxisLineStyle/inside.png | Bin 0 -> 2858 bytes .../com/fr/design/images/chart/ChartData.png | Bin 0 -> 335 bytes .../chart/ChartLegend/layout_bottom.png | Bin 0 -> 2830 bytes .../images/chart/ChartLegend/layout_left.png | Bin 0 -> 2837 bytes .../images/chart/ChartLegend/layout_right.png | Bin 0 -> 2831 bytes .../images/chart/ChartLegend/layout_top.png | Bin 0 -> 2830 bytes .../chart/ChartLegend/layout_top_right.png | Bin 0 -> 2850 bytes .../com/fr/design/images/chart/ChartStyle.png | Bin 0 -> 314 bytes .../com/fr/design/images/chart/ChartType.png | Bin 0 -> 362 bytes .../images/chart/ColumnPlot/layout/0.png | Bin 0 -> 3519 bytes .../images/chart/ColumnPlot/layout/1.png | Bin 0 -> 3093 bytes .../images/chart/ColumnPlot/layout/2.png | Bin 0 -> 3327 bytes .../images/chart/ColumnPlot/layout/3.png | Bin 0 -> 3793 bytes .../design/images/chart/ColumnPlot/type/0.png | Bin 0 -> 661 bytes .../design/images/chart/ColumnPlot/type/1.png | Bin 0 -> 570 bytes .../design/images/chart/ColumnPlot/type/2.png | Bin 0 -> 557 bytes .../design/images/chart/ColumnPlot/type/3.png | Bin 0 -> 523 bytes .../design/images/chart/ColumnPlot/type/4.png | Bin 0 -> 1375 bytes .../design/images/chart/ColumnPlot/type/5.png | Bin 0 -> 584 bytes .../design/images/chart/ColumnPlot/type/6.png | Bin 0 -> 591 bytes .../fr/design/images/chart/ConditionAttr.png | Bin 0 -> 458 bytes .../images/chart/CustomPlot/layout/0.png | Bin 0 -> 4329 bytes .../images/chart/CustomPlot/layout/1.png | Bin 0 -> 4206 bytes .../images/chart/CustomPlot/layout/2.png | Bin 0 -> 3893 bytes .../images/chart/CustomPlot/layout/3.png | Bin 0 -> 4036 bytes .../design/images/chart/CustomPlot/type/0.png | Bin 0 -> 4206 bytes .../images/chart/DonutPlot/layout/0.png | Bin 0 -> 5499 bytes .../images/chart/DonutPlot/layout/1.png | Bin 0 -> 4905 bytes .../images/chart/DonutPlot/layout/2.png | Bin 0 -> 5771 bytes .../images/chart/DonutPlot/layout/3.png | Bin 0 -> 5532 bytes .../design/images/chart/DonutPlot/type/0.png | Bin 0 -> 4817 bytes .../design/images/chart/DonutPlot/type/1.png | Bin 0 -> 4443 bytes .../design/images/chart/FunnelPlot/type/0.png | Bin 0 -> 458 bytes .../design/images/chart/GanttPlot/type/0.png | Bin 0 -> 3267 bytes .../images/chart/GisMapPlot/layout/0.png | Bin 0 -> 12051 bytes .../images/chart/GisMapPlot/layout/1.png | Bin 0 -> 12051 bytes .../design/images/chart/GisMapPlot/type/0.png | Bin 0 -> 1967 bytes .../com/fr/design/images/chart/InterAttr.png | Bin 0 -> 641 bytes .../design/images/chart/LinePlot/layout/0.png | Bin 0 -> 3666 bytes .../design/images/chart/LinePlot/layout/1.png | Bin 0 -> 3809 bytes .../design/images/chart/LinePlot/layout/2.png | Bin 0 -> 3686 bytes .../design/images/chart/LinePlot/layout/3.png | Bin 0 -> 3599 bytes .../design/images/chart/LinePlot/type/0.png | Bin 0 -> 1823 bytes .../design/images/chart/LinePlot/type/1.png | Bin 0 -> 1715 bytes .../design/images/chart/LinePlot/type/2.png | Bin 0 -> 1029 bytes .../fr/design/images/chart/MapPlot/type/0.png | Bin 0 -> 2214 bytes .../fr/design/images/chart/MapPlot/type/1.png | Bin 0 -> 1362 bytes .../fr/design/images/chart/MapPlot/type/2.png | Bin 0 -> 1291 bytes .../fr/design/images/chart/MapPlot/type/3.png | Bin 0 -> 806 bytes .../design/images/chart/MeterPlot/type/0.png | Bin 0 -> 1461 bytes .../design/images/chart/MeterPlot/type/1.png | Bin 0 -> 2139 bytes .../design/images/chart/MeterPlot/type/2.png | Bin 0 -> 1321 bytes .../design/images/chart/PiePlot/layout/0.png | Bin 0 -> 4962 bytes .../design/images/chart/PiePlot/layout/1.png | Bin 0 -> 4105 bytes .../design/images/chart/PiePlot/layout/2.png | Bin 0 -> 4983 bytes .../design/images/chart/PiePlot/layout/3.png | Bin 0 -> 5302 bytes .../fr/design/images/chart/PiePlot/type/0.png | Bin 0 -> 2069 bytes .../fr/design/images/chart/PiePlot/type/1.png | Bin 0 -> 1809 bytes .../design/images/chart/RadarPlot/type/0.png | Bin 0 -> 4733 bytes .../design/images/chart/RangePlot/type/0.png | Bin 0 -> 678 bytes .../design/images/chart/StockPlot/type/0.png | Bin 0 -> 3075 bytes .../images/chart/XYScatterPlot/layout/0.png | Bin 0 -> 3955 bytes .../images/chart/XYScatterPlot/layout/1.png | Bin 0 -> 3951 bytes .../images/chart/XYScatterPlot/layout/2.png | Bin 0 -> 3921 bytes .../images/chart/XYScatterPlot/layout/3.png | Bin 0 -> 4203 bytes .../images/chart/XYScatterPlot/type/0.png | Bin 0 -> 4761 bytes .../com/fr/design/images/chart/default.png | Bin 0 -> 3385 bytes .../src/com/fr/design/images/chart/link.png | Bin 0 -> 652 bytes .../src/com/fr/design/images/chart/moved.png | Bin 0 -> 3260 bytes .../src/com/fr/design/images/chart/normal.png | Bin 0 -> 3167 bytes .../com/fr/design/images/chart/pressed.png | Bin 0 -> 3235 bytes .../fr/design/images/condition/bracket.png | Bin 0 -> 265 bytes .../fr/design/images/condition/unBracket.png | Bin 0 -> 318 bytes .../com/fr/design/images/control/addPopup.png | Bin 0 -> 240 bytes .../fr/design/images/control/arrow_down.png | Bin 0 -> 251 bytes .../src/com/fr/design/images/control/bar.png | Bin 0 -> 17258 bytes .../src/com/fr/design/images/control/barl.png | Bin 0 -> 2883 bytes .../src/com/fr/design/images/control/barm.png | Bin 0 -> 2878 bytes .../com/fr/design/images/control/close.png | Bin 0 -> 2844 bytes .../design/images/control/close_rollover.png | Bin 0 -> 2860 bytes .../com/fr/design/images/control/closet.png | Bin 0 -> 1071 bytes .../design/images/control/control-center2.png | Bin 0 -> 407 bytes .../src/com/fr/design/images/control/copy.png | Bin 0 -> 251 bytes .../src/com/fr/design/images/control/dot.png | Bin 0 -> 2866 bytes .../src/com/fr/design/images/control/dotv.png | Bin 0 -> 2865 bytes .../src/com/fr/design/images/control/down.png | Bin 0 -> 222 bytes .../com/fr/design/images/control/downdis.png | Bin 0 -> 2906 bytes .../com/fr/design/images/control/downnor.png | Bin 0 -> 2916 bytes .../com/fr/design/images/control/downpre.png | Bin 0 -> 2926 bytes .../src/com/fr/design/images/control/edit.png | Bin 0 -> 303 bytes .../src/com/fr/design/images/control/left.png | Bin 0 -> 694 bytes .../com/fr/design/images/control/leftleft.png | Bin 0 -> 326 bytes .../com/fr/design/images/control/leftnor.png | Bin 0 -> 2908 bytes .../com/fr/design/images/control/leftpre.png | Bin 0 -> 2916 bytes .../src/com/fr/design/images/control/lock.png | Bin 0 -> 510 bytes .../src/com/fr/design/images/control/more.png | Bin 0 -> 966 bytes .../com/fr/design/images/control/refresh.png | Bin 0 -> 345 bytes .../com/fr/design/images/control/remove.png | Bin 0 -> 302 bytes .../com/fr/design/images/control/right.png | Bin 0 -> 706 bytes .../com/fr/design/images/control/rightnor.png | Bin 0 -> 2921 bytes .../com/fr/design/images/control/rightpre.png | Bin 0 -> 2928 bytes .../fr/design/images/control/rightright.png | Bin 0 -> 384 bytes .../com/fr/design/images/control/sortAsc.png | Bin 0 -> 404 bytes .../com/fr/design/images/control/unlock.png | Bin 0 -> 552 bytes .../src/com/fr/design/images/control/up.png | Bin 0 -> 216 bytes .../com/fr/design/images/control/updis.png | Bin 0 -> 2885 bytes .../com/fr/design/images/control/upnor.png | Bin 0 -> 2897 bytes .../com/fr/design/images/control/uppre.png | Bin 0 -> 2906 bytes .../src/com/fr/design/images/control/warn.png | Bin 0 -> 4260 bytes .../design/images/custombtn/baobiaozhuti.png | Bin 0 -> 705 bytes .../images/custombtn/baobiaozhuti_click.png | Bin 0 -> 470 bytes .../images/custombtn/baobiaozhuti_hover.png | Bin 0 -> 752 bytes .../design/images/custombtn/canshujiemian.png | Bin 0 -> 705 bytes .../images/custombtn/canshujiemian_click.png | Bin 0 -> 453 bytes .../images/custombtn/canshujiemian_hover.png | Bin 0 -> 732 bytes .../com/fr/design/images/custombtn/edit.png | Bin 0 -> 741 bytes .../fr/design/images/custombtn/edit_click.png | Bin 0 -> 520 bytes .../fr/design/images/custombtn/edit_hover.png | Bin 0 -> 739 bytes .../com/fr/design/images/custombtn/form.png | Bin 0 -> 731 bytes .../fr/design/images/custombtn/form_click.png | Bin 0 -> 534 bytes .../fr/design/images/custombtn/form_hover.png | Bin 0 -> 739 bytes .../com/fr/design/images/custombtn/left.gif | Bin 0 -> 1885 bytes .../com/fr/design/images/custombtn/page.png | Bin 0 -> 695 bytes .../fr/design/images/custombtn/page_click.png | Bin 0 -> 506 bytes .../fr/design/images/custombtn/page_hover.png | Bin 0 -> 706 bytes .../fr/design/images/custombtn/preview.png | Bin 0 -> 3182 bytes .../design/images/custombtn/preview_click.png | Bin 0 -> 3205 bytes .../design/images/custombtn/preview_hover.png | Bin 0 -> 3164 bytes .../com/fr/design/images/custombtn/right.gif | Bin 0 -> 1106 bytes .../fr/design/images/custombtn/setting.png | Bin 0 -> 845 bytes .../design/images/custombtn/setting_click.png | Bin 0 -> 747 bytes .../design/images/custombtn/setting_hover.png | Bin 0 -> 834 bytes .../com/fr/design/images/dashboard/chart.png | Bin 0 -> 1307 bytes .../com/fr/design/images/dashboard/files.png | Bin 0 -> 213 bytes .../com/fr/design/images/dashboard/form.png | Bin 0 -> 1335 bytes .../com/fr/design/images/dashboard/guide.png | Bin 0 -> 704 bytes .../com/fr/design/images/dashboard/img/0.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/1.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/1.png | Bin 0 -> 11156 bytes .../com/fr/design/images/dashboard/img/10.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/10.png | Bin 0 -> 12413 bytes .../com/fr/design/images/dashboard/img/11.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/11.png | Bin 0 -> 10832 bytes .../com/fr/design/images/dashboard/img/12.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/12.png | Bin 0 -> 13496 bytes .../com/fr/design/images/dashboard/img/13.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/13.png | Bin 0 -> 1544 bytes .../com/fr/design/images/dashboard/img/14.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/14.png | Bin 0 -> 209 bytes .../com/fr/design/images/dashboard/img/15.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/15.png | Bin 0 -> 265 bytes .../com/fr/design/images/dashboard/img/16.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/16.png | Bin 0 -> 333 bytes .../com/fr/design/images/dashboard/img/17.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/17.png | Bin 0 -> 947 bytes .../com/fr/design/images/dashboard/img/18.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/18.png | Bin 0 -> 442 bytes .../com/fr/design/images/dashboard/img/19.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/19.png | Bin 0 -> 698 bytes .../com/fr/design/images/dashboard/img/2.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/2.png | Bin 0 -> 13347 bytes .../com/fr/design/images/dashboard/img/20.png | Bin 0 -> 385 bytes .../com/fr/design/images/dashboard/img/21.png | Bin 0 -> 251 bytes .../com/fr/design/images/dashboard/img/22.png | Bin 0 -> 1024 bytes .../com/fr/design/images/dashboard/img/23.png | Bin 0 -> 834 bytes .../com/fr/design/images/dashboard/img/24.png | Bin 0 -> 311 bytes .../com/fr/design/images/dashboard/img/25.png | Bin 0 -> 11969 bytes .../com/fr/design/images/dashboard/img/26.png | Bin 0 -> 11744 bytes .../com/fr/design/images/dashboard/img/27.png | Bin 0 -> 11999 bytes .../com/fr/design/images/dashboard/img/28.png | Bin 0 -> 1148 bytes .../com/fr/design/images/dashboard/img/29.png | Bin 0 -> 985 bytes .../com/fr/design/images/dashboard/img/3.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/3.png | Bin 0 -> 13253 bytes .../com/fr/design/images/dashboard/img/30.png | Bin 0 -> 868 bytes .../com/fr/design/images/dashboard/img/31.png | Bin 0 -> 10520 bytes .../com/fr/design/images/dashboard/img/32.png | Bin 0 -> 1170 bytes .../com/fr/design/images/dashboard/img/33.png | Bin 0 -> 2005 bytes .../com/fr/design/images/dashboard/img/34.png | Bin 0 -> 3042 bytes .../com/fr/design/images/dashboard/img/35.png | Bin 0 -> 834 bytes .../com/fr/design/images/dashboard/img/36.png | Bin 0 -> 913 bytes .../com/fr/design/images/dashboard/img/37.png | Bin 0 -> 1919 bytes .../com/fr/design/images/dashboard/img/38.png | Bin 0 -> 2409 bytes .../com/fr/design/images/dashboard/img/39.png | Bin 0 -> 427 bytes .../com/fr/design/images/dashboard/img/4.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/4.png | Bin 0 -> 13490 bytes .../com/fr/design/images/dashboard/img/40.png | Bin 0 -> 245 bytes .../com/fr/design/images/dashboard/img/41.png | Bin 0 -> 1383 bytes .../com/fr/design/images/dashboard/img/42.png | Bin 0 -> 306 bytes .../com/fr/design/images/dashboard/img/43.png | Bin 0 -> 567 bytes .../com/fr/design/images/dashboard/img/44.png | Bin 0 -> 456 bytes .../com/fr/design/images/dashboard/img/45.png | Bin 0 -> 1027 bytes .../com/fr/design/images/dashboard/img/46.png | Bin 0 -> 2257 bytes .../com/fr/design/images/dashboard/img/47.png | Bin 0 -> 888 bytes .../com/fr/design/images/dashboard/img/48.png | Bin 0 -> 986 bytes .../com/fr/design/images/dashboard/img/49.png | Bin 0 -> 217 bytes .../com/fr/design/images/dashboard/img/5.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/5.png | Bin 0 -> 12740 bytes .../com/fr/design/images/dashboard/img/50.png | Bin 0 -> 402 bytes .../com/fr/design/images/dashboard/img/52.png | Bin 0 -> 897 bytes .../com/fr/design/images/dashboard/img/54.png | Bin 0 -> 2132 bytes .../com/fr/design/images/dashboard/img/55.png | Bin 0 -> 1121 bytes .../com/fr/design/images/dashboard/img/56.png | Bin 0 -> 1647 bytes .../com/fr/design/images/dashboard/img/57.png | Bin 0 -> 282 bytes .../com/fr/design/images/dashboard/img/6.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/6.png | Bin 0 -> 12287 bytes .../com/fr/design/images/dashboard/img/7.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/7.png | Bin 0 -> 10723 bytes .../com/fr/design/images/dashboard/img/8.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/8.png | Bin 0 -> 13318 bytes .../com/fr/design/images/dashboard/img/9.gif | Bin 0 -> 15804 bytes .../com/fr/design/images/dashboard/img/9.png | Bin 0 -> 12659 bytes .../fr/design/images/dashboard/img/Thumbs.db | Bin 0 -> 5632 bytes .../fr/design/images/data/arrow_branch.png | Bin 0 -> 582 bytes .../com/fr/design/images/data/bind/add.png | Bin 0 -> 1135 bytes .../images/data/bind/distanceconnect.png | Bin 0 -> 728 bytes .../images/data/bind/groupAscColumn.png | Bin 0 -> 316 bytes .../design/images/data/bind/groupColumn.png | Bin 0 -> 291 bytes .../images/data/bind/groupDescColumn.png | Bin 0 -> 318 bytes .../design/images/data/bind/localconnect.png | Bin 0 -> 306 bytes .../com/fr/design/images/data/bind/modify.png | Bin 0 -> 473 bytes .../design/images/data/bind/normalColumn.png | Bin 0 -> 291 bytes .../design/images/data/bind/selectColumn.png | Bin 0 -> 291 bytes .../design/images/data/bind/sortAscColumn.png | Bin 0 -> 316 bytes .../fr/design/images/data/bind/sortColumn.png | Bin 0 -> 291 bytes .../images/data/bind/sortDescColumn.png | Bin 0 -> 318 bytes .../design/images/data/bind/summaryColumn.png | Bin 0 -> 291 bytes .../com/fr/design/images/data/comb_widget.png | Bin 0 -> 492 bytes .../fr/design/images/data/convertEmbedded.png | Bin 0 -> 1204 bytes .../src/com/fr/design/images/data/cube.png | Bin 0 -> 3493 bytes .../fr/design/images/data/custom_widget.png | Bin 0 -> 369 bytes .../fr/design/images/data/dataDictionary.png | Bin 0 -> 216 bytes .../com/fr/design/images/data/dataTable.png | Bin 0 -> 308 bytes .../com/fr/design/images/data/database.png | Bin 0 -> 335 bytes .../com/fr/design/images/data/datakubiao.png | Bin 0 -> 973 bytes .../com/fr/design/images/data/datasource.png | Bin 0 -> 335 bytes .../fr/design/images/data/default_widget.png | Bin 0 -> 853 bytes .../src/com/fr/design/images/data/diy.png | Bin 0 -> 3681 bytes .../com/fr/design/images/data/dock/XML.png | Bin 0 -> 3338 bytes .../images/data/dock/classTableData.png | Bin 0 -> 496 bytes .../fr/design/images/data/dock/dataTable.png | Bin 0 -> 308 bytes .../fr/design/images/data/dock/database.png | Bin 0 -> 335 bytes .../com/fr/design/images/data/dock/excel.png | Bin 0 -> 3515 bytes .../images/data/dock/relation_table_data.png | Bin 0 -> 3460 bytes .../images/data/dock/serverclasstabledata.png | Bin 0 -> 3361 bytes .../images/data/dock/serverdatabase.png | Bin 0 -> 452 bytes .../images/data/dock/serverdatatable.png | Bin 0 -> 367 bytes .../fr/design/images/data/dock/table_proc.png | Bin 0 -> 3504 bytes .../fr/design/images/data/dock/table_text.png | Bin 0 -> 3495 bytes .../com/fr/design/images/data/editQuery.png | Bin 0 -> 1137 bytes .../src/com/fr/design/images/data/field.png | Bin 0 -> 1109 bytes .../src/com/fr/design/images/data/file.png | Bin 0 -> 478 bytes .../src/com/fr/design/images/data/multi.png | Bin 0 -> 198 bytes .../com/fr/design/images/data/newQuery.png | Bin 0 -> 1096 bytes .../src/com/fr/design/images/data/private.png | Bin 0 -> 338 bytes .../src/com/fr/design/images/data/public.png | Bin 0 -> 372 bytes .../src/com/fr/design/images/data/sap.png | Bin 0 -> 881 bytes .../src/com/fr/design/images/data/search.png | Bin 0 -> 939 bytes .../images/data/source/classTableData.png | Bin 0 -> 496 bytes .../fr/design/images/data/source/clear.png | Bin 0 -> 703 bytes .../images/data/source/dataDictionary.png | Bin 0 -> 216 bytes .../fr/design/images/data/source/delete.png | Bin 0 -> 302 bytes .../images/data/source/hibernateTableData.png | Bin 0 -> 869 bytes .../images/data/source/jdbcDataquery.png | Bin 0 -> 310 bytes .../images/data/source/jdbcTableData.png | Bin 0 -> 1054 bytes .../fr/design/images/data/source/moveDown.png | Bin 0 -> 222 bytes .../fr/design/images/data/source/moveUp.png | Bin 0 -> 216 bytes .../design/images/data/source/newDatabase.png | Bin 0 -> 1092 bytes .../images/data/source/newDatasource.png | Bin 0 -> 1096 bytes .../fr/design/images/data/source/rename.png | Bin 0 -> 431 bytes .../fr/design/images/data/source/schema.png | Bin 0 -> 204 bytes .../images/data/source/selectwizard/Thumbs.db | Bin 0 -> 7680 bytes .../data/source/selectwizard/accept.png | Bin 0 -> 781 bytes .../data/source/selectwizard/bullet_key.png | Bin 0 -> 436 bytes .../data/source/selectwizard/bullet_pink.png | Bin 0 -> 295 bytes .../data/source/selectwizard/cart_add.png | Bin 0 -> 711 bytes .../data/source/selectwizard/cart_delete.png | Bin 0 -> 742 bytes .../selectwizard/chart_organisation.png | Bin 0 -> 444 bytes .../data/source/selectwizard/database.png | Bin 0 -> 390 bytes .../source/selectwizard/database_connect.png | Bin 0 -> 763 bytes .../source/selectwizard/database_gear.png | Bin 0 -> 468 bytes .../selectwizard/database_lightning.png | Bin 0 -> 775 bytes .../source/selectwizard/database_save.png | Bin 0 -> 755 bytes .../source/selectwizard/database_table.png | Bin 0 -> 726 bytes .../source/selectwizard/database_tables.png | Bin 0 -> 612 bytes .../data/source/selectwizard/filter.png | Bin 0 -> 361 bytes .../source/selectwizard/folder_database.png | Bin 0 -> 687 bytes .../data/source/selectwizard/folder_page.png | Bin 0 -> 688 bytes .../data/source/selectwizard/folder_table.png | Bin 0 -> 675 bytes .../data/source/selectwizard/page_edit.png | Bin 0 -> 807 bytes .../data/source/selectwizard/page_gear.png | Bin 0 -> 833 bytes .../data/source/selectwizard/page_save.png | Bin 0 -> 774 bytes .../selectwizard/page_white_database.png | Bin 0 -> 579 bytes .../data/source/selectwizard/table_error.png | Bin 0 -> 687 bytes .../data/source/selectwizard/table_gear.png | Bin 0 -> 714 bytes .../data/source/selectwizard/table_link.png | Bin 0 -> 728 bytes .../source/selectwizard/table_multiple.png | Bin 0 -> 612 bytes .../selectwizard/table_relationship.png | Bin 0 -> 663 bytes .../source/selectwizard/table_row_delete.png | Bin 0 -> 629 bytes .../source/selectwizard/table_row_insert.png | Bin 0 -> 641 bytes .../data/source/selectwizard/table_sort.png | Bin 0 -> 678 bytes .../data/source/selectwizard/textfield.png | Bin 0 -> 153 bytes .../data/source/selectwizard/wizard.png | Bin 0 -> 3310 bytes .../data/source/selectwizard/wrench.png | Bin 0 -> 610 bytes .../images/data/source/sqlAscColumn.png | Bin 0 -> 316 bytes .../design/images/data/source/sqlColumn.png | Bin 0 -> 291 bytes .../images/data/source/sqlConditionColumn.png | Bin 0 -> 291 bytes .../images/data/source/sqlDescColumn.png | Bin 0 -> 318 bytes .../fr/design/images/data/source/sqlTable.png | Bin 0 -> 301 bytes .../images/data/source/sqlViewTable.png | Bin 0 -> 287 bytes .../fr/design/images/data/source/table.png | Bin 0 -> 356 bytes .../images/data/source/textDatasource.png | Bin 0 -> 406 bytes .../com/fr/design/images/data/source/view.png | Bin 0 -> 356 bytes .../fr/design/images/data/store_procedure.png | Bin 0 -> 216 bytes .../src/com/fr/design/images/data/string.png | Bin 0 -> 2881 bytes .../src/com/fr/design/images/data/table.png | Bin 0 -> 1146 bytes .../src/com/fr/design/images/data/table2.png | Bin 0 -> 1153 bytes .../src/com/fr/design/images/data/tables.png | Bin 0 -> 518 bytes .../src/com/fr/design/images/data/text.png | Bin 0 -> 305 bytes .../src/com/fr/design/images/data/today.gif | Bin 0 -> 94 bytes .../src/com/fr/design/images/data/tree.png | Bin 0 -> 415 bytes .../com/fr/design/images/data/user_widget.png | Bin 0 -> 3609 bytes .../src/com/fr/design/images/data/views.png | Bin 0 -> 673 bytes .../src/com/fr/design/images/data/xml.png | Bin 0 -> 3255 bytes .../com/fr/design/images/dialog/column.png | Bin 0 -> 291 bytes .../com/fr/design/images/dialog/function.gif | Bin 0 -> 84 bytes .../com/fr/design/images/dialog/parameter.gif | Bin 0 -> 117 bytes .../src/com/fr/design/images/dialog/table.png | Bin 0 -> 301 bytes .../com/fr/design/images/dialog/variable.png | Bin 0 -> 467 bytes .../src/com/fr/design/images/dock/desktop.png | Bin 0 -> 903 bytes .../src/com/fr/design/images/dock/project.png | Bin 0 -> 1250 bytes .../com/fr/design/images/dock/projectVer.png | Bin 0 -> 3111 bytes .../com/fr/design/images/dock/properties.png | Bin 0 -> 420 bytes .../com/fr/design/images/docking/close.gif | Bin 0 -> 70 bytes .../src/com/fr/design/images/docking/down.gif | Bin 0 -> 1894 bytes .../src/com/fr/design/images/docking/left.gif | Bin 0 -> 835 bytes .../src/com/fr/design/images/docking/left.png | Bin 0 -> 374 bytes .../com/fr/design/images/docking/right.gif | Bin 0 -> 1106 bytes .../com/fr/design/images/docking/right.png | Bin 0 -> 372 bytes .../src/com/fr/design/images/docking/up.gif | Bin 0 -> 1108 bytes .../com/fr/design/images/edit/deleteRow.png | Bin 0 -> 1167 bytes .../com/fr/design/images/edit/insertRow_B.png | Bin 0 -> 1171 bytes .../src/com/fr/design/images/expand/asc.png | Bin 0 -> 2905 bytes .../com/fr/design/images/expand/cellAttr.gif | Bin 0 -> 254 bytes .../src/com/fr/design/images/expand/des.png | Bin 0 -> 2909 bytes .../com/fr/design/images/expand/landspace.png | Bin 0 -> 2846 bytes .../com/fr/design/images/expand/none16x16.png | Bin 0 -> 3137 bytes .../com/fr/design/images/expand/vertical.png | Bin 0 -> 2840 bytes .../src/com/fr/design/images/file/disk.gif | Bin 0 -> 138 bytes .../src/com/fr/design/images/file/disk.png | Bin 0 -> 510 bytes .../src/com/fr/design/images/file/fold.png | Bin 0 -> 217 bytes .../src/com/fr/design/images/file/folder.gif | Bin 0 -> 887 bytes .../src/com/fr/design/images/file/gifFile.gif | Bin 0 -> 128 bytes .../src/com/fr/design/images/file/jpgFile.gif | Bin 0 -> 127 bytes .../com/fr/design/images/file/newfolder.png | Bin 0 -> 277 bytes .../src/com/fr/design/images/file/nostar.png | Bin 0 -> 516 bytes .../src/com/fr/design/images/file/pngFile.png | Bin 0 -> 354 bytes .../src/com/fr/design/images/file/star.png | Bin 0 -> 617 bytes .../src/com/fr/design/images/form/Button.gif | Bin 0 -> 101 bytes .../com/fr/design/images/form/CheckBox.gif | Bin 0 -> 122 bytes .../src/com/fr/design/images/form/Choice.gif | Bin 0 -> 123 bytes .../src/com/fr/design/images/form/List.gif | Bin 0 -> 216 bytes .../com/fr/design/images/form/RadioButton.gif | Bin 0 -> 115 bytes .../com/fr/design/images/form/TextField.gif | Bin 0 -> 121 bytes .../adapters/container/bottom_border.png | Bin 0 -> 97 bytes .../adapters/container/bottom_border_.png | Bin 0 -> 152 bytes .../beans/adapters/container/bottom_left.png | Bin 0 -> 180 bytes .../beans/adapters/container/bottom_left_.png | Bin 0 -> 167 bytes .../beans/adapters/container/bottom_right.png | Bin 0 -> 175 bytes .../adapters/container/bottom_right_.png | Bin 0 -> 169 bytes .../adapters/container/control_close.png | Bin 0 -> 1176 bytes .../adapters/container/control_close_.png | Bin 0 -> 215 bytes .../beans/adapters/container/control_max.png | Bin 0 -> 1132 bytes .../beans/adapters/container/control_max_.png | Bin 0 -> 201 bytes .../beans/adapters/container/control_min.png | Bin 0 -> 1185 bytes .../beans/adapters/container/control_min_.png | Bin 0 -> 192 bytes .../beans/adapters/container/controls.png | Bin 0 -> 2554 bytes .../beans/adapters/container/controls_.png | Bin 0 -> 296 bytes .../beans/adapters/container/left_border.png | Bin 0 -> 151 bytes .../beans/adapters/container/left_border_.png | Bin 0 -> 151 bytes .../beans/adapters/container/right_border.png | Bin 0 -> 152 bytes .../adapters/container/right_border_.png | Bin 0 -> 151 bytes .../beans/adapters/container/title_pane.png | Bin 0 -> 208 bytes .../beans/adapters/container/top_border.png | Bin 0 -> 154 bytes .../beans/adapters/container/top_border_.png | Bin 0 -> 151 bytes .../beans/adapters/container/top_left.png | Bin 0 -> 176 bytes .../beans/adapters/container/top_left_.png | Bin 0 -> 157 bytes .../beans/adapters/container/top_right.png | Bin 0 -> 179 bytes .../beans/adapters/container/top_right_.png | Bin 0 -> 164 bytes .../images/form/designer/bottom_align.png | Bin 0 -> 2875 bytes .../images/form/designer/center_align.png | Bin 0 -> 1101 bytes .../images/form/designer/cursor/add.png | Bin 0 -> 3164 bytes .../form/designer/cursor/connectorcursor.png | Bin 0 -> 3053 bytes .../images/form/designer/cursor/move.png | Bin 0 -> 3016 bytes .../design/images/form/designer/drop_down.png | Bin 0 -> 594 bytes .../design/images/form/designer/drop_over.png | Bin 0 -> 546 bytes .../design/images/form/designer/drop_up.png | Bin 0 -> 532 bytes .../fr/design/images/form/designer/holder.png | Bin 0 -> 428 bytes .../images/form/designer/left_align.png | Bin 0 -> 1075 bytes .../images/form/designer/middle_align.png | Bin 0 -> 1023 bytes .../images/form/designer/properties/minus.png | Bin 0 -> 155 bytes .../images/form/designer/properties/plus.png | Bin 0 -> 166 bytes .../images/form/designer/right_align.png | Bin 0 -> 1093 bytes .../images/form/designer/same_height.png | Bin 0 -> 2875 bytes .../images/form/designer/same_width.png | Bin 0 -> 2876 bytes .../design/images/form/designer/top_align.png | Bin 0 -> 1002 bytes .../src/com/fr/design/images/form/hover.png | Bin 0 -> 803 bytes .../com/fr/design/images/form/parameter.png | Bin 0 -> 2942 bytes .../design/images/form/toolbar/Chart-Map.png | Bin 0 -> 344 bytes .../images/form/toolbar/ChartF-Area.png | Bin 0 -> 374 bytes .../design/images/form/toolbar/ChartF-Bar.png | Bin 0 -> 178 bytes .../images/form/toolbar/ChartF-Column.png | Bin 0 -> 179 bytes .../images/form/toolbar/ChartF-Comb_Chart.png | Bin 0 -> 306 bytes .../images/form/toolbar/ChartF-Donut.png | Bin 0 -> 454 bytes .../images/form/toolbar/ChartF-Funnel.png | Bin 0 -> 276 bytes .../images/form/toolbar/ChartF-Gantt.png | Bin 0 -> 190 bytes .../design/images/form/toolbar/ChartF-Gis.png | Bin 0 -> 590 bytes .../images/form/toolbar/ChartF-Line.png | Bin 0 -> 447 bytes .../images/form/toolbar/ChartF-Meter.png | Bin 0 -> 431 bytes .../design/images/form/toolbar/ChartF-Pie.png | Bin 0 -> 372 bytes .../images/form/toolbar/ChartF-Radar.png | Bin 0 -> 723 bytes .../form/toolbar/ChartF-Range_Chart.png | Bin 0 -> 227 bytes .../images/form/toolbar/ChartF-Stock.png | Bin 0 -> 204 bytes .../images/form/toolbar/ChartF-XYScatter.png | Bin 0 -> 429 bytes .../images/form/toolbar/Chart_BubbleChart.png | Bin 0 -> 493 bytes .../toolbar/FR-Chart-Chart_BubbleChart.png | Bin 0 -> 738 bytes .../fr/design/images/form/toolbar/default.png | Bin 0 -> 179 bytes .../design/images/form/toolbar/ec_columns.png | Bin 0 -> 19086 bytes .../design/images/form/toolbar/ec_frozen.png | Bin 0 -> 213 bytes designer_base/src/com/fr/design/images/gc.png | Bin 0 -> 1076 bytes .../fr/design/images/general/close-rolver.png | Bin 0 -> 2880 bytes .../com/fr/design/images/general/close.png | Bin 0 -> 2914 bytes .../fr/design/images/general/mini-rolver.png | Bin 0 -> 2838 bytes .../src/com/fr/design/images/general/mini.png | Bin 0 -> 2838 bytes .../design/images/general/resize-rolver.png | Bin 0 -> 2876 bytes .../com/fr/design/images/general/resize.png | Bin 0 -> 2883 bytes .../src/com/fr/design/images/gui/blank.gif | Bin 0 -> 74 bytes .../src/com/fr/design/images/gui/bmpFile.gif | Bin 0 -> 128 bytes .../src/com/fr/design/images/gui/cell.gif | Bin 0 -> 96 bytes .../src/com/fr/design/images/gui/cht.png | Bin 0 -> 1500 bytes .../com/fr/design/images/gui/chtlocked.png | Bin 0 -> 3254 bytes .../com/fr/design/images/gui/classFile.gif | Bin 0 -> 147 bytes .../src/com/fr/design/images/gui/close.png | Bin 0 -> 1011 bytes .../fr/design/images/gui/color/background.png | Bin 0 -> 425 bytes .../fr/design/images/gui/color/foreground.png | Bin 0 -> 2970 bytes .../src/com/fr/design/images/gui/cptFile.png | Bin 0 -> 1173 bytes .../design/images/gui/documentFolderClose.gif | Bin 0 -> 157 bytes .../src/com/fr/design/images/gui/folder.gif | Bin 0 -> 887 bytes .../src/com/fr/design/images/gui/folder.png | Bin 0 -> 217 bytes .../fr/design/images/gui/folder/expanded.png | Bin 0 -> 636 bytes .../fr/design/images/gui/folder/foldered.png | Bin 0 -> 701 bytes .../images/gui/folder/hovered_expanded.png | Bin 0 -> 633 bytes .../images/gui/folder/hovered_foldered.png | Bin 0 -> 640 bytes .../src/com/fr/design/images/gui/frm.png | Bin 0 -> 1348 bytes .../com/fr/design/images/gui/frmlocked.png | Bin 0 -> 3137 bytes .../src/com/fr/design/images/gui/gifFile.gif | Bin 0 -> 128 bytes .../src/com/fr/design/images/gui/htmlFile.gif | Bin 0 -> 116 bytes .../src/com/fr/design/images/gui/jarFile.gif | Bin 0 -> 127 bytes .../src/com/fr/design/images/gui/javaFile.gif | Bin 0 -> 116 bytes .../src/com/fr/design/images/gui/jpgFile.gif | Bin 0 -> 127 bytes .../src/com/fr/design/images/gui/jsFile.gif | Bin 0 -> 986 bytes .../src/com/fr/design/images/gui/jspFile.gif | Bin 0 -> 339 bytes .../src/com/fr/design/images/gui/locked.gif | Bin 0 -> 123 bytes .../src/com/fr/design/images/gui/minimize.gif | Bin 0 -> 70 bytes .../src/com/fr/design/images/gui/pngFile.png | Bin 0 -> 354 bytes .../src/com/fr/design/images/gui/popup.gif | Bin 0 -> 61 bytes .../com/fr/design/images/gui/popupCenter.png | Bin 0 -> 254 bytes .../com/fr/design/images/gui/popupLarge.gif | Bin 0 -> 69 bytes .../fr/design/images/gui/tab_add_click.png | Bin 0 -> 3397 bytes .../fr/design/images/gui/tab_add_hover.png | Bin 0 -> 3053 bytes .../fr/design/images/gui/tab_add_normal.png | Bin 0 -> 3054 bytes .../com/fr/design/images/gui/tab_delete.png | Bin 0 -> 3110 bytes .../src/com/fr/design/images/gui/textFile.png | Bin 0 -> 325 bytes .../src/com/fr/design/images/gui/warning.png | Bin 0 -> 3016 bytes .../src/com/fr/design/images/gui/xmlFile.gif | Bin 0 -> 219 bytes .../com/fr/design/images/load/busy-icon0.png | Bin 0 -> 3588 bytes .../com/fr/design/images/load/busy-icon1.png | Bin 0 -> 3585 bytes .../com/fr/design/images/load/busy-icon10.png | Bin 0 -> 3568 bytes .../com/fr/design/images/load/busy-icon11.png | Bin 0 -> 3581 bytes .../com/fr/design/images/load/busy-icon12.png | Bin 0 -> 3589 bytes .../com/fr/design/images/load/busy-icon13.png | Bin 0 -> 3586 bytes .../com/fr/design/images/load/busy-icon14.png | Bin 0 -> 3586 bytes .../com/fr/design/images/load/busy-icon2.png | Bin 0 -> 3585 bytes .../com/fr/design/images/load/busy-icon3.png | Bin 0 -> 3572 bytes .../com/fr/design/images/load/busy-icon4.png | Bin 0 -> 3576 bytes .../com/fr/design/images/load/busy-icon5.png | Bin 0 -> 3580 bytes .../com/fr/design/images/load/busy-icon6.png | Bin 0 -> 3581 bytes .../com/fr/design/images/load/busy-icon7.png | Bin 0 -> 3598 bytes .../com/fr/design/images/load/busy-icon8.png | Bin 0 -> 3594 bytes .../com/fr/design/images/load/busy-icon9.png | Bin 0 -> 3581 bytes .../src/com/fr/design/images/log/clear.png | Bin 0 -> 357 bytes .../com/fr/design/images/log/selectedall.png | Bin 0 -> 1324 bytes .../src/com/fr/design/images/log/setting.png | Bin 0 -> 1187 bytes .../images/lookandfeel/ComboBoxFocus.png | Bin 0 -> 161 bytes .../images/lookandfeel/ComputerIcon.png | Bin 0 -> 913 bytes .../images/lookandfeel/DirectoryIcon.png | Bin 0 -> 217 bytes .../design/images/lookandfeel/ErrorIcon.png | Bin 0 -> 763 bytes .../images/lookandfeel/FileDetailsIcon.png | Bin 0 -> 263 bytes .../fr/design/images/lookandfeel/FileIcon.png | Bin 0 -> 3014 bytes .../images/lookandfeel/FileListIcon.png | Bin 0 -> 281 bytes .../design/images/lookandfeel/FloppyIcon.png | Bin 0 -> 218 bytes .../images/lookandfeel/HarddiskIcon.png | Bin 0 -> 510 bytes .../images/lookandfeel/HomeFolderIcon.png | Bin 0 -> 306 bytes .../images/lookandfeel/InformationIcon.png | Bin 0 -> 573 bytes .../images/lookandfeel/InternalFrameIcon.png | Bin 0 -> 990 bytes .../images/lookandfeel/NewFolderIcon.png | Bin 0 -> 277 bytes .../lookandfeel/ParentDirectoryIcon.png | Bin 0 -> 216 bytes .../images/lookandfeel/QuestionIcon.png | Bin 0 -> 601 bytes .../lookandfeel/TreeFolderClosedIcon.png | Bin 0 -> 217 bytes .../lookandfeel/TreeFolderOpenedIcon.png | Bin 0 -> 406 bytes .../images/lookandfeel/TreeLeafIcon.png | Bin 0 -> 446 bytes .../images/lookandfeel/TreeMinusIcon.png | Bin 0 -> 155 bytes .../images/lookandfeel/TreePlusIcon.png | Bin 0 -> 166 bytes .../design/images/lookandfeel/WarningIcon.png | Bin 0 -> 616 bytes .../design/images/lookandfeel/brightmask.png | Bin 0 -> 21820 bytes .../fr/design/images/m_edit/bringForward.png | Bin 0 -> 1146 bytes .../fr/design/images/m_edit/bringToFront.png | Bin 0 -> 1159 bytes .../src/com/fr/design/images/m_edit/copy.png | Bin 0 -> 258 bytes .../src/com/fr/design/images/m_edit/cut.png | Bin 0 -> 407 bytes .../fr/design/images/m_edit/directShare.png | Bin 0 -> 441 bytes .../fr/design/images/m_edit/formatBrush.png | Bin 0 -> 371 bytes .../src/com/fr/design/images/m_edit/merge.png | Bin 0 -> 226 bytes .../fr/design/images/m_edit/modifyShare.png | Bin 0 -> 469 bytes .../src/com/fr/design/images/m_edit/paste.png | Bin 0 -> 258 bytes .../fr/design/images/m_edit/pluralundo.png | Bin 0 -> 116 bytes .../src/com/fr/design/images/m_edit/redo.png | Bin 0 -> 318 bytes .../fr/design/images/m_edit/sendBackward.png | Bin 0 -> 1128 bytes .../fr/design/images/m_edit/sendToBack.png | Bin 0 -> 1146 bytes .../src/com/fr/design/images/m_edit/share.png | Bin 0 -> 439 bytes .../src/com/fr/design/images/m_edit/undo.png | Bin 0 -> 343 bytes .../com/fr/design/images/m_edit/unmerge.png | Bin 0 -> 195 bytes .../src/com/fr/design/images/m_file/close.png | Bin 0 -> 427 bytes .../fr/design/images/m_file/crossTable.png | Bin 0 -> 275 bytes .../src/com/fr/design/images/m_file/csv.png | Bin 0 -> 297 bytes .../com/fr/design/images/m_file/design.png | Bin 0 -> 644 bytes .../fr/design/images/m_file/design_large.png | Bin 0 -> 644 bytes .../src/com/fr/design/images/m_file/edit.png | Bin 0 -> 411 bytes .../src/com/fr/design/images/m_file/excel.png | Bin 0 -> 372 bytes .../com/fr/design/images/m_file/export.png | Bin 0 -> 287 bytes .../fr/design/images/m_file/formExport.png | Bin 0 -> 212 bytes .../fr/design/images/m_file/groupTable.png | Bin 0 -> 274 bytes .../src/com/fr/design/images/m_file/help.png | Bin 0 -> 817 bytes .../src/com/fr/design/images/m_file/html.png | Bin 0 -> 1478 bytes .../com/fr/design/images/m_file/hyperLink.png | Bin 0 -> 686 bytes .../com/fr/design/images/m_file/import.png | Bin 0 -> 3397 bytes .../src/com/fr/design/images/m_file/merge.png | Bin 0 -> 3675 bytes .../src/com/fr/design/images/m_file/new.png | Bin 0 -> 3217 bytes .../src/com/fr/design/images/m_file/open.png | Bin 0 -> 402 bytes .../com/fr/design/images/m_file/pageSetup.png | Bin 0 -> 203 bytes .../src/com/fr/design/images/m_file/pdf.png | Bin 0 -> 380 bytes .../com/fr/design/images/m_file/preview.png | Bin 0 -> 361 bytes .../src/com/fr/design/images/m_file/print.png | Bin 0 -> 423 bytes .../src/com/fr/design/images/m_file/save.png | Bin 0 -> 218 bytes .../com/fr/design/images/m_file/saveAs.png | Bin 0 -> 246 bytes .../src/com/fr/design/images/m_file/svg.png | Bin 0 -> 301 bytes .../com/fr/design/images/m_file/switch.png | Bin 0 -> 360 bytes .../src/com/fr/design/images/m_file/text.png | Bin 0 -> 224 bytes .../fr/design/images/m_file/view_folder.png | Bin 0 -> 228 bytes .../src/com/fr/design/images/m_file/web.png | Bin 0 -> 1279 bytes .../src/com/fr/design/images/m_file/word.png | Bin 0 -> 391 bytes .../fr/design/images/m_format/allborders.png | Bin 0 -> 128 bytes .../com/fr/design/images/m_format/border.png | Bin 0 -> 280 bytes .../com/fr/design/images/m_format/bottom.png | Bin 0 -> 100 bytes .../com/fr/design/images/m_format/cell.png | Bin 0 -> 374 bytes .../fr/design/images/m_format/cellAttr.png | Bin 0 -> 1101 bytes .../design/images/m_format/cellWriteAttr.png | Bin 0 -> 1157 bytes .../design/images/m_format/cellstyle/bold.png | Bin 0 -> 240 bytes .../m_format/cellstyle/centerAlignment.png | Bin 0 -> 251 bytes .../images/m_format/cellstyle/default.png | Bin 0 -> 3113 bytes .../m_format/cellstyle/defaultAlignment.png | Bin 0 -> 2833 bytes .../m_format/cellstyle/generalAlignment.png | Bin 0 -> 244 bytes .../m_format/cellstyle/h_center_normal.png | Bin 0 -> 2831 bytes .../m_format/cellstyle/h_center_pressed.png | Bin 0 -> 2838 bytes .../m_format/cellstyle/h_left_normal.png | Bin 0 -> 2829 bytes .../m_format/cellstyle/h_left_pressed.png | Bin 0 -> 2825 bytes .../m_format/cellstyle/h_right_normal.png | Bin 0 -> 2822 bytes .../m_format/cellstyle/h_right_pressed.png | Bin 0 -> 2827 bytes .../images/m_format/cellstyle/h_s_normal.png | Bin 0 -> 2819 bytes .../images/m_format/cellstyle/h_s_pressed.png | Bin 0 -> 2818 bytes .../images/m_format/cellstyle/italic.png | Bin 0 -> 221 bytes .../m_format/cellstyle/leftAlignment.png | Bin 0 -> 248 bytes .../images/m_format/cellstyle/otherset.png | Bin 0 -> 409 bytes .../m_format/cellstyle/rightAlignment.png | Bin 0 -> 250 bytes .../images/m_format/cellstyle/shadow.png | Bin 0 -> 3179 bytes .../m_format/cellstyle/strikethrough.png | Bin 0 -> 2954 bytes .../design/images/m_format/cellstyle/sub.png | Bin 0 -> 2968 bytes .../design/images/m_format/cellstyle/sup.png | Bin 0 -> 2972 bytes .../images/m_format/cellstyle/underline.png | Bin 0 -> 224 bytes .../m_format/cellstyle/v_center_normal.png | Bin 0 -> 2849 bytes .../m_format/cellstyle/v_center_pressed.png | Bin 0 -> 2838 bytes .../m_format/cellstyle/v_down_normal.png | Bin 0 -> 2829 bytes .../m_format/cellstyle/v_down_pressed.png | Bin 0 -> 2830 bytes .../m_format/cellstyle/v_top_normal.png | Bin 0 -> 2827 bytes .../m_format/cellstyle/v_top_pressed.png | Bin 0 -> 2825 bytes .../design/images/m_format/doublebottom.png | Bin 0 -> 119 bytes .../fr/design/images/m_format/editChart.png | Bin 0 -> 571 bytes .../fr/design/images/m_format/highlight.png | Bin 0 -> 421 bytes .../src/com/fr/design/images/m_format/in.png | Bin 0 -> 2882 bytes .../com/fr/design/images/m_format/left.png | Bin 0 -> 125 bytes .../fr/design/images/m_format/modified.png | Bin 0 -> 453 bytes .../com/fr/design/images/m_format/noboder.png | Bin 0 -> 108 bytes .../com/fr/design/images/m_format/note.png | Bin 0 -> 1237 bytes .../src/com/fr/design/images/m_format/out.png | Bin 0 -> 2869 bytes .../design/images/m_format/outsideborders.png | Bin 0 -> 143 bytes .../com/fr/design/images/m_format/right.png | Bin 0 -> 130 bytes .../com/fr/design/images/m_format/shape.png | Bin 0 -> 454 bytes .../fr/design/images/m_format/thickbottom.png | Bin 0 -> 128 bytes .../images/m_format/thickoutsideborders.png | Bin 0 -> 204 bytes .../images/m_format/topanddoublebotttom.png | Bin 0 -> 126 bytes .../images/m_format/topandthickbottom.png | Bin 0 -> 136 bytes .../fr/design/images/m_format/topbottom.png | Bin 0 -> 123 bytes .../src/com/fr/design/images/m_help/back.png | Bin 0 -> 963 bytes .../src/com/fr/design/images/m_help/demo.png | Bin 0 -> 246 bytes .../com/fr/design/images/m_help/feedback.png | Bin 0 -> 398 bytes .../src/com/fr/design/images/m_help/forum.png | Bin 0 -> 910 bytes .../com/fr/design/images/m_help/forward.png | Bin 0 -> 910 bytes .../src/com/fr/design/images/m_help/help.png | Bin 0 -> 232 bytes .../fr/design/images/m_help/preview_analy.png | Bin 0 -> 1590 bytes .../fr/design/images/m_help/preview_form.png | Bin 0 -> 1507 bytes .../fr/design/images/m_help/preview_page.png | Bin 0 -> 1532 bytes .../fr/design/images/m_help/preview_write.png | Bin 0 -> 1560 bytes .../fr/design/images/m_help/product_forum.png | Bin 0 -> 323 bytes .../fr/design/images/m_help/support_qq.png | Bin 0 -> 18272 bytes .../fr/design/images/m_insert/Pivottable.gif | Bin 0 -> 125 bytes .../com/fr/design/images/m_insert/account.png | Bin 0 -> 355 bytes .../design/images/m_insert/accountTitle.png | Bin 0 -> 294 bytes .../com/fr/design/images/m_insert/barcode.png | Bin 0 -> 1042 bytes .../com/fr/design/images/m_insert/bias.png | Bin 0 -> 358 bytes .../fr/design/images/m_insert/bindCell.png | Bin 0 -> 190 bytes .../fr/design/images/m_insert/bindColumn.png | Bin 0 -> 190 bytes .../com/fr/design/images/m_insert/blank.gif | Bin 0 -> 55 bytes .../com/fr/design/images/m_insert/boolean.png | Bin 0 -> 1038 bytes .../com/fr/design/images/m_insert/cell.png | Bin 0 -> 218 bytes .../com/fr/design/images/m_insert/cellPop.png | Bin 0 -> 2931 bytes .../com/fr/design/images/m_insert/chart.png | Bin 0 -> 362 bytes .../fr/design/images/m_insert/composite.png | Bin 0 -> 575 bytes .../design/images/m_insert/compositePop.png | Bin 0 -> 598 bytes .../fr/design/images/m_insert/crossTable.png | Bin 0 -> 275 bytes .../com/fr/design/images/m_insert/date.png | Bin 0 -> 249 bytes .../com/fr/design/images/m_insert/default.png | Bin 0 -> 304 bytes .../fr/design/images/m_insert/expandCell.gif | Bin 0 -> 104 bytes .../com/fr/design/images/m_insert/float.png | Bin 0 -> 186 bytes .../fr/design/images/m_insert/floatPop.png | Bin 0 -> 222 bytes .../com/fr/design/images/m_insert/formula.png | Bin 0 -> 1056 bytes .../fr/design/images/m_insert/groupTable.png | Bin 0 -> 274 bytes .../fr/design/images/m_insert/hyperLink.png | Bin 0 -> 686 bytes .../com/fr/design/images/m_insert/image.png | Bin 0 -> 335 bytes .../design/images/m_insert/insertColumn.png | Bin 0 -> 283 bytes .../fr/design/images/m_insert/insertRow.png | Bin 0 -> 303 bytes .../fr/design/images/m_insert/newchart.png | Bin 0 -> 1500 bytes .../fr/design/images/m_insert/richtext.png | Bin 0 -> 168 bytes .../com/fr/design/images/m_insert/shape.png | Bin 0 -> 332 bytes .../m_insert/shape_issosceles_triangle.png | Bin 0 -> 299 bytes .../fr/design/images/m_insert/shape_line.png | Bin 0 -> 268 bytes .../fr/design/images/m_insert/shape_oval.png | Bin 0 -> 313 bytes .../images/m_insert/shape_rectangle.png | Bin 0 -> 245 bytes .../m_insert/shape_rounded_rectangle.png | Bin 0 -> 266 bytes .../fr/design/images/m_insert/subReport.png | Bin 0 -> 279 bytes .../com/fr/design/images/m_insert/text.png | Bin 0 -> 200 bytes .../com/fr/design/images/m_insert/textBox.png | Bin 0 -> 331 bytes .../images/m_report/allow_authority_edit.png | Bin 0 -> 334 bytes .../fr/design/images/m_report/attributes.png | Bin 0 -> 528 bytes .../fr/design/images/m_report/background.png | Bin 0 -> 371 bytes .../fr/design/images/m_report/bindData.png | Bin 0 -> 1148 bytes .../com/fr/design/images/m_report/close.png | Bin 0 -> 544 bytes .../fr/design/images/m_report/close_over.png | Bin 0 -> 508 bytes .../fr/design/images/m_report/close_press.png | Bin 0 -> 521 bytes .../com/fr/design/images/m_report/delete.png | Bin 0 -> 302 bytes .../design/images/m_report/deleteColumn.png | Bin 0 -> 315 bytes .../fr/design/images/m_report/deleteRow.png | Bin 0 -> 338 bytes .../images/m_report/exit_authority_edit.png | Bin 0 -> 3165 bytes .../fr/design/images/m_report/exportAttr.png | Bin 0 -> 287 bytes .../com/fr/design/images/m_report/footer.png | Bin 0 -> 213 bytes .../com/fr/design/images/m_report/header.png | Bin 0 -> 215 bytes .../fr/design/images/m_report/linearAttr.png | Bin 0 -> 158 bytes .../src/com/fr/design/images/m_report/p.gif | Bin 0 -> 294 bytes .../src/com/fr/design/images/m_report/p.png | Bin 0 -> 3132 bytes .../fr/design/images/m_report/parameter.png | Bin 0 -> 3132 bytes .../com/fr/design/images/m_report/process.gif | Bin 0 -> 113 bytes .../src/com/fr/design/images/m_report/qb.png | Bin 0 -> 3289 bytes .../images/m_report/reportEngineAttr.png | Bin 0 -> 452 bytes .../images/m_report/reportWorkFlowAttr.png | Bin 0 -> 1149 bytes .../images/m_report/reportWriteAttr.png | Bin 0 -> 466 bytes .../com/fr/design/images/m_report/tree.png | Bin 0 -> 661 bytes .../images/m_report/webreportattribute.png | Bin 0 -> 545 bytes .../src/com/fr/design/images/m_web/cache.png | Bin 0 -> 379 bytes .../com/fr/design/images/m_web/connection.png | Bin 0 -> 387 bytes .../com/fr/design/images/m_web/datasource.png | Bin 0 -> 335 bytes .../src/com/fr/design/images/m_web/edit.png | Bin 0 -> 503 bytes .../src/com/fr/design/images/m_web/face.gif | Bin 0 -> 243 bytes .../com/fr/design/images/m_web/formula.png | Bin 0 -> 1056 bytes .../com/fr/design/images/m_web/function.png | Bin 0 -> 256 bytes .../src/com/fr/design/images/m_web/log.png | Bin 0 -> 652 bytes .../design/images/m_web/privilegeManager.gif | Bin 0 -> 364 bytes .../fr/design/images/m_web/reportletdemo.png | Bin 0 -> 594 bytes .../com/fr/design/images/m_web/schedule.png | Bin 0 -> 608 bytes .../src/com/fr/design/images/m_web/server.png | Bin 0 -> 832 bytes .../src/com/fr/design/images/m_web/style.png | Bin 0 -> 374 bytes .../src/com/fr/design/images/m_web/sync.png | Bin 0 -> 383 bytes .../com/fr/design/images/m_window/cascade.png | Bin 0 -> 282 bytes .../fr/design/images/m_window/formdesign.png | Bin 0 -> 485 bytes .../com/fr/design/images/m_window/frozen.png | Bin 0 -> 500 bytes .../design/images/m_window/generaldesign.png | Bin 0 -> 696 bytes .../com/fr/design/images/m_window/next.png | Bin 0 -> 329 bytes .../fr/design/images/m_window/previous.png | Bin 0 -> 336 bytes .../fr/design/images/m_window/title_hor.png | Bin 0 -> 253 bytes .../fr/design/images/m_window/title_ver.png | Bin 0 -> 255 bytes .../fr/design/images/mainframe/attribute.png | Bin 0 -> 1361 bytes .../com/fr/design/images/mainframe/class.png | Bin 0 -> 1323 bytes .../fr/design/images/mainframe/datasource.png | Bin 0 -> 1054 bytes .../com/fr/design/images/mainframe/fpt.png | Bin 0 -> 1173 bytes .../com/fr/design/images/mainframe/jar.png | Bin 0 -> 369 bytes .../com/fr/design/images/mainframe/java.png | Bin 0 -> 451 bytes .../com/fr/design/images/mainframe/server.png | Bin 0 -> 832 bytes .../com/fr/design/images/mainframe/xml.png | Bin 0 -> 3255 bytes .../src/com/fr/design/images/minimize.gif | Bin 0 -> 67 bytes .../src/com/fr/design/images/parameter.png | Bin 0 -> 1046 bytes .../images/poly/Chart-Map/Chart-Map-0.png | Bin 0 -> 3236 bytes .../images/poly/ChartF-Area/ChartF-Area-0.png | Bin 0 -> 2963 bytes .../images/poly/ChartF-Area/ChartF-Area-1.png | Bin 0 -> 2998 bytes .../images/poly/ChartF-Area/ChartF-Area-2.png | Bin 0 -> 2951 bytes .../images/poly/ChartF-Area/ChartF-Area-3.png | Bin 0 -> 3353 bytes .../images/poly/ChartF-Area/ChartF-Area-4.png | Bin 0 -> 1025 bytes .../images/poly/ChartF-Area/ChartF-Area-5.png | Bin 0 -> 3437 bytes .../images/poly/ChartF-Bar/ChartF-Bar-0.png | Bin 0 -> 3350 bytes .../images/poly/ChartF-Bar/ChartF-Bar-1.png | Bin 0 -> 2883 bytes .../images/poly/ChartF-Bar/ChartF-Bar-2.png | Bin 0 -> 3049 bytes .../images/poly/ChartF-Bar/ChartF-Bar-3.png | Bin 0 -> 3054 bytes .../images/poly/ChartF-Bar/ChartF-Bar-4.png | Bin 0 -> 976 bytes .../images/poly/ChartF-Bar/ChartF-Bar-5.png | Bin 0 -> 3082 bytes .../images/poly/ChartF-Bar/ChartF-Bar-6.png | Bin 0 -> 3188 bytes .../poly/ChartF-Column/ChartF-Column-0.png | Bin 0 -> 3255 bytes .../poly/ChartF-Column/ChartF-Column-1.png | Bin 0 -> 2898 bytes .../poly/ChartF-Column/ChartF-Column-2.png | Bin 0 -> 3006 bytes .../poly/ChartF-Column/ChartF-Column-3.png | Bin 0 -> 3019 bytes .../poly/ChartF-Column/ChartF-Column-4.png | Bin 0 -> 944 bytes .../poly/ChartF-Column/ChartF-Column-5.png | Bin 0 -> 3044 bytes .../poly/ChartF-Column/ChartF-Column-6.png | Bin 0 -> 3163 bytes .../ChartF-Comb_Chart/ChartF-Comb_Chart-0.png | Bin 0 -> 3352 bytes .../ChartF-Comb_Chart/ChartF-Comb_Chart-1.png | Bin 0 -> 2994 bytes .../poly/ChartF-Donut/ChartF-Donut-0.png | Bin 0 -> 1686 bytes .../poly/ChartF-Donut/ChartF-Donut-1.png | Bin 0 -> 728 bytes .../poly/ChartF-Gantt/ChartF-Gantt-0.png | Bin 0 -> 2892 bytes .../poly/ChartF-Gantt/ChartF-Gantt-1.png | Bin 0 -> 2946 bytes .../poly/ChartF-Gantt/ChartF-Gantt-2.png | Bin 0 -> 2949 bytes .../poly/ChartF-Gantt/ChartF-Gantt-3.png | Bin 0 -> 2979 bytes .../images/poly/ChartF-Gis/ChartF-Gis-0.png | Bin 0 -> 640 bytes .../images/poly/ChartF-Line/ChartF-Line-0.png | Bin 0 -> 2988 bytes .../images/poly/ChartF-Line/ChartF-Line-1.png | Bin 0 -> 3020 bytes .../images/poly/ChartF-Line/ChartF-Line-2.png | Bin 0 -> 2937 bytes .../images/poly/ChartF-Line/ChartF-Line-3.png | Bin 0 -> 870 bytes .../images/poly/ChartF-Line/ChartF-Line-4.png | Bin 0 -> 3194 bytes .../images/poly/ChartF-Line/ChartF-Line-5.png | Bin 0 -> 3088 bytes .../poly/ChartF-Meter/ChartF-Meter-0.png | Bin 0 -> 854 bytes .../poly/ChartF-Meter/ChartF-Meter-1.png | Bin 0 -> 3515 bytes .../images/poly/ChartF-Pie/ChartF-Pie-0.png | Bin 0 -> 1686 bytes .../images/poly/ChartF-Pie/ChartF-Pie-1.png | Bin 0 -> 728 bytes .../images/poly/ChartF-Pie/ChartF-Pie-2.png | Bin 0 -> 3356 bytes .../images/poly/ChartF-Pie/ChartF-Pie-3.png | Bin 0 -> 3181 bytes .../images/poly/ChartF-Pie/ChartF-Pie-4.png | Bin 0 -> 846 bytes .../images/poly/ChartF-Pie/ChartF-Pie-5.png | Bin 0 -> 622 bytes .../poly/ChartF-Radar/ChartF-Radar-0.png | Bin 0 -> 3081 bytes .../poly/ChartF-Radar/ChartF-Radar-1.png | Bin 0 -> 3049 bytes .../poly/ChartF-Radar/ChartF-Radar-2.png | Bin 0 -> 3066 bytes .../poly/ChartF-Radar/ChartF-Radar-3.png | Bin 0 -> 3021 bytes .../ChartF-Range_Chart-0.png | Bin 0 -> 2901 bytes .../poly/ChartF-Stock/ChartF-Stock-0.png | Bin 0 -> 2909 bytes .../poly/ChartF-Stock/ChartF-Stock-1.png | Bin 0 -> 3002 bytes .../poly/ChartF-Stock/ChartF-Stock-2.png | Bin 0 -> 2959 bytes .../poly/ChartF-Stock/ChartF-Stock-3.png | Bin 0 -> 2985 bytes .../ChartF-XYScatter/ChartF-XYScatter-0.png | Bin 0 -> 622 bytes .../ChartF-XYScatter/ChartF-XYScatter-1.png | Bin 0 -> 629 bytes .../ChartF-XYScatter/ChartF-XYScatter-2.png | Bin 0 -> 850 bytes .../Chart_BubbleChart/Chart_BubbleChart-0.png | Bin 0 -> 738 bytes .../FR-Chart-Chart_BubbleChart-0.png | Bin 0 -> 738 bytes .../src/com/fr/design/images/poly/normal.png | Bin 0 -> 798 bytes .../design/images/poly/toolbar/Chart-Map.png | Bin 0 -> 423 bytes .../images/poly/toolbar/Chart-SVG_MAP.png | Bin 0 -> 3081 bytes .../images/poly/toolbar/ChartF-Area.png | Bin 0 -> 439 bytes .../design/images/poly/toolbar/ChartF-Bar.png | Bin 0 -> 185 bytes .../images/poly/toolbar/ChartF-Column.png | Bin 0 -> 185 bytes .../images/poly/toolbar/ChartF-Comb_Chart.png | Bin 0 -> 381 bytes .../images/poly/toolbar/ChartF-Donut.png | Bin 0 -> 527 bytes .../images/poly/toolbar/ChartF-Funnel.png | Bin 0 -> 314 bytes .../images/poly/toolbar/ChartF-Gantt.png | Bin 0 -> 204 bytes .../design/images/poly/toolbar/ChartF-Gis.png | Bin 0 -> 800 bytes .../images/poly/toolbar/ChartF-Line.png | Bin 0 -> 548 bytes .../images/poly/toolbar/ChartF-Meter.png | Bin 0 -> 559 bytes .../design/images/poly/toolbar/ChartF-Pie.png | Bin 0 -> 424 bytes .../images/poly/toolbar/ChartF-Radar.png | Bin 0 -> 1002 bytes .../poly/toolbar/ChartF-Range_Chart.png | Bin 0 -> 237 bytes .../images/poly/toolbar/ChartF-Stock.png | Bin 0 -> 221 bytes .../images/poly/toolbar/ChartF-XYScatter.png | Bin 0 -> 329 bytes .../images/poly/toolbar/Chart_BubbleChart.png | Bin 0 -> 503 bytes .../images/poly/toolbar/FR-Chart-Bit_Map.png | Bin 0 -> 423 bytes .../toolbar/FR-Chart-Chart_BubbleChart.png | Bin 0 -> 503 bytes .../toolbar/FR-Chart-ThreeD_Custom_Chart.png | Bin 0 -> 381 bytes .../images/poly/toolbar/FR-Chart_Bit_Map.png | Bin 0 -> 3081 bytes .../poly/toolbar/Plugin-ChartF_NewArea.png | Bin 0 -> 439 bytes .../poly/toolbar/Plugin-ChartF_NewBar.png | Bin 0 -> 3856 bytes .../poly/toolbar/Plugin-ChartF_NewColumn.png | Bin 0 -> 3745 bytes .../poly/toolbar/Plugin-ChartF_NewLine.png | Bin 0 -> 548 bytes .../poly/toolbar/Plugin-ChartF_NewPie.png | Bin 0 -> 424 bytes .../toolbar/Plugin-ChartF_VerticalLine.png | Bin 0 -> 548 bytes .../images/poly/toolbar/Poly-Report_Block.png | Bin 0 -> 206 bytes .../src/com/fr/design/images/report/form.png | Bin 0 -> 1328 bytes .../fr/design/images/report/groupReport.png | Bin 0 -> 1097 bytes .../com/fr/design/images/report/position.png | Bin 0 -> 166 bytes .../fr/design/images/reportcolumns/col.png | Bin 0 -> 1348 bytes .../fr/design/images/reportcolumns/row.png | Bin 0 -> 3708 bytes .../com/fr/design/images/server/change.png | Bin 0 -> 3673 bytes .../com/fr/design/images/server/manage.png | Bin 0 -> 4906 bytes .../com/fr/design/images/server/plugin.png | Bin 0 -> 470 bytes .../fr/design/images/server/printerconf.png | Bin 0 -> 3623 bytes .../src/com/fr/design/images/server/start.png | Bin 0 -> 3024 bytes .../src/com/fr/design/images/server/stop.png | Bin 0 -> 431 bytes .../src/com/fr/design/images/server/view.png | Bin 0 -> 3326 bytes .../src/com/fr/design/images/serverM/fs.png | Bin 0 -> 818 bytes .../src/com/fr/design/images/serverM/org.png | Bin 0 -> 852 bytes .../fr/design/images/serverM/organization.png | Bin 0 -> 1073 bytes .../src/com/fr/design/images/serverM/role.png | Bin 0 -> 1131 bytes .../com/fr/design/images/serverM/roleAdd.png | Bin 0 -> 1148 bytes .../fr/design/images/serverM/roleRemove.png | Bin 0 -> 1165 bytes .../src/com/fr/design/images/serverM/rtr.png | Bin 0 -> 667 bytes .../src/com/fr/design/images/serverM/use.png | Bin 0 -> 740 bytes .../src/com/fr/design/images/serverM/user.png | Bin 0 -> 1232 bytes .../fr/design/images/sheet/addpolysheet.png | Bin 0 -> 379 bytes .../fr/design/images/sheet/left_right_btn.png | Bin 0 -> 1540 bytes .../com/fr/design/images/sheet/polysheet.png | Bin 0 -> 1065 bytes .../com/fr/design/images/toolbarbtn/chart.png | Bin 0 -> 1166 bytes .../images/toolbarbtn/chartChangeClose.png | Bin 0 -> 2937 bytes .../com/fr/design/images/toolbarbtn/close.png | Bin 0 -> 3097 bytes .../design/images/toolbarbtn/close_tags.png | Bin 0 -> 1164 bytes .../design/images/toolbarbtn/closehover.png | Bin 0 -> 588 bytes .../fr/design/images/toolbarbtn/connector.png | Bin 0 -> 2892 bytes .../com/fr/design/images/toolbarbtn/down.png | Bin 0 -> 2839 bytes .../images/toolbarbtn/parameter-hover.png | Bin 0 -> 3712 bytes .../images/toolbarbtn/parametersetting.png | Bin 0 -> 3886 bytes .../com/fr/design/images/toolbarbtn/pop.gif | Bin 0 -> 1106 bytes .../fr/design/images/toolbarbtn/setting.png | Bin 0 -> 409 bytes .../images/toolbarbtn/toolbarbtnclear.png | Bin 0 -> 345 bytes .../images/toolbarbtn/toolbarbtnsetting.png | Bin 0 -> 923 bytes .../com/fr/design/images/toolbarbtn/up.png | Bin 0 -> 2840 bytes .../com/fr/design/images/toolbarbtn/xiala.png | Bin 0 -> 682 bytes .../src/com/fr/design/images/tree/close.png | Bin 0 -> 2992 bytes .../src/com/fr/design/images/tree/open.png | Bin 0 -> 2973 bytes .../src/com/fr/design/images/wait.gif | Bin 0 -> 3933 bytes .../fr/design/images/warnings/warning 2.png | Bin 0 -> 2846 bytes .../com/fr/design/images/warnings/warning.png | Bin 0 -> 3382 bytes .../fr/design/images/warnings/warning3.png | Bin 0 -> 1441 bytes .../design/insert/formula/variable/cn/$$$.txt | 1 + .../formula/variable/cn/$$page_number.txt | 1 + .../variable/cn/$$totalPage_number.txt | 1 + .../formula/variable/cn/$fr_authority.txt | 1 + .../formula/variable/cn/$fr_username.txt | 1 + .../formula/variable/cn/$fr_userposition.txt | 3 + .../insert/formula/variable/cn/NOFILTER.txt | 1 + .../insert/formula/variable/cn/NULL.txt | 1 + .../formula/variable/cn/contextPath.txt | 3 + .../insert/formula/variable/cn/curReport.txt | 1 + .../formula/variable/cn/fr_submitinfo.txt | 1 + .../insert/formula/variable/cn/reportName.txt | 3 + .../insert/formula/variable/cn/serverName.txt | 3 + .../insert/formula/variable/cn/serverPort.txt | 1 + .../formula/variable/cn/serverSchema.txt | 3 + .../insert/formula/variable/cn/serverURL.txt | 3 + .../insert/formula/variable/cn/servletURL.txt | 2 + .../insert/formula/variable/cn/sessionID.txt | 4 + .../design/insert/formula/variable/en/$$$.txt | 1 + .../formula/variable/en/$$page_number.txt | 1 + .../variable/en/$$totalPage_number.txt | 1 + .../formula/variable/en/$fr_authority.txt | 1 + .../formula/variable/en/$fr_username.txt | 1 + .../formula/variable/en/$fr_userposition.txt | 1 + .../insert/formula/variable/en/NOFILTER.txt | 1 + .../insert/formula/variable/en/NULL.txt | 1 + .../formula/variable/en/contextPath.txt | 1 + .../insert/formula/variable/en/curReport.txt | 1 + .../formula/variable/en/fr_submitinfo.txt | 1 + .../insert/formula/variable/en/reportName.txt | 3 + .../insert/formula/variable/en/serverName.txt | 3 + .../insert/formula/variable/en/serverPort.txt | 1 + .../formula/variable/en/serverSchema.txt | 3 + .../insert/formula/variable/en/serverURL.txt | 3 + .../insert/formula/variable/en/servletURL.txt | 2 + .../insert/formula/variable/en/sessionID.txt | 1 + .../javascript/Commit2DBJavaScriptPane.java | 164 + .../design/javascript/CustomActionPane.java | 1 + .../com/fr/design/javascript/EmailPane.java | 153 + .../javascript/FormSubmitJavaScriptPane.java | 135 + .../fr/design/javascript/JSContentPane.java | 148 + .../javascript/JavaScriptActionPane.java | 205 + .../design/javascript/JavaScriptImplPane.java | 276 + .../javascript/ParameterJavaScriptPane.java | 140 + .../design/javascript/ProcessJSImplPane.java | 219 + .../ProcessParameterTableModel.java | 238 + .../javascript/ProcessTransitionAdapter.java | 40 + .../fr/design/layout/FRGUIPaneFactory.java | 456 + .../com/fr/design/layout/FRGridLayout.java | 16 + .../fr/design/layout/FRLeftFlowLayout.java | 85 + .../design/layout/LeftCenterRightLayout.java | 150 + .../src/com/fr/design/layout/TableLayout.java | 2057 ++ .../design/layout/TableLayoutConstraints.java | 231 + .../fr/design/layout/TableLayoutHelper.java | 290 + .../com/fr/design/layout/TableLayoutTest.java | 82 + .../fr/design/layout/VerticalFlowLayout.java | 457 + .../design/mainframe/AbstractAppProvider.java | 13 + .../src/com/fr/design/mainframe/App.java | 39 + .../design/mainframe/AuthorityEditPane.java | 1 + .../mainframe/AuthorityPropertyPane.java | 1 + .../fr/design/mainframe/BaseFormDesigner.java | 1 + .../com/fr/design/mainframe/BaseJForm.java | 1 + .../fr/design/mainframe/BaseUndoState.java | 45 + .../mainframe/BaseWidgetPropertyPane.java | 1 + .../com/fr/design/mainframe/DecodeDialog.java | 91 + .../com/fr/design/mainframe/DesignerBean.java | 17 + .../fr/design/mainframe/DesignerContext.java | 139 + .../fr/design/mainframe/DesignerFrame.java | 1002 + .../DesignerFrameFileDealerPane.java | 530 + .../fr/design/mainframe/DesktopCardPane.java | 51 + .../com/fr/design/mainframe/DockingView.java | 45 + .../com/fr/design/mainframe/DottedLine.java | 1 + .../mainframe/EastRegionContainerPane.java | 38 + .../fr/design/mainframe/FormScrollBar.java | 156 + .../com/fr/design/mainframe/JTemplate.java | 955 + .../mainframe/JTemplateActionListener.java | 12 + .../design/mainframe/JTemplateProvider.java | 6 + .../fr/design/mainframe/JViewContainer.java | 174 + .../mainframe/NoSupportAuthorityEdit.java | 1 + .../com/fr/design/mainframe/TemplatePane.java | 278 + .../fr/design/mainframe/UndoStateEdit.java | 74 + .../mainframe/WestRegionContainerPane.java | 30 + .../backgroundpane/BackgroundSettingPane.java | 33 + .../backgroundpane/ColorBackgroundPane.java | 72 + .../backgroundpane/ImageBackgroundPane.java | 185 + .../backgroundpane/ImagePreviewPane.java | 288 + .../backgroundpane/NullBackgroundPane.java | 54 + .../backgroundpane/PatternBackgroundPane.java | 211 + .../backgroundpane/TextureBackgroundPane.java | 173 + .../dnd/ArrayListTransferHandler.java | 206 + .../mainframe/dnd/ArrayListTransferable.java | 49 + .../mainframe/dnd/ArrayTransferable.java | 33 + .../dnd/SerializableTransferable.java | 64 + .../form/FormECCompositeProvider.java | 17 + .../form/FormECDesignerProvider.java | 71 + .../mainframe/hold/DefaultTitlePlace.java | 14 + .../loghandler/DesignerLogHandler.java | 302 + .../mainframe/loghandler/DesignerLogImpl.java | 46 + .../mainframe/loghandler/LogDetailPane.java | 30 + .../mainframe/loghandler/LogHandlerBar.java | 207 + .../mainframe/loghandler/LogHandlerBarUI.java | 158 + .../mainframe/loghandler/LogMessageBar.java | 67 + .../AuthorityEditToolBarComponent.java | 1 + .../mainframe/toolbar/ToolBarMenuDock.java | 559 + .../toolbar/ToolBarMenuDockPlus.java | 63 + .../editors/AbstractPropertyEditor.java | 79 + .../widget/editors/DataBindingEditor.java | 149 + .../widget/editors/DataTableEditor.java | 84 + .../editors/ExtendedPropertyEditor.java | 19 + .../widget/editors/FormattedEditor.java | 71 + .../widget/editors/IntegerPropertyEditor.java | 19 + .../widget/editors/PropertyCellEditor.java | 91 + .../editors/ServerDataBindingEditor.java | 13 + .../widget/editors/ServerDataTableEditor.java | 13 + .../widget/editors/StringEditor.java | 66 + .../widget/editors/WidgetValueEditor.java | 123 + .../com/fr/design/menu/DottedSeparator.java | 75 + .../com/fr/design/menu/DottedSeparatorUI.java | 67 + .../src/com/fr/design/menu/KeySetUtils.java | 1076 + .../src/com/fr/design/menu/LineSeparator.java | 72 + .../src/com/fr/design/menu/MenuDef.java | 345 + .../src/com/fr/design/menu/MenuKeySet.java | 34 + .../src/com/fr/design/menu/MenuManager.java | 175 + .../src/com/fr/design/menu/NameSeparator.java | 97 + .../src/com/fr/design/menu/SeparatorDef.java | 45 + .../src/com/fr/design/menu/ShortCut.java | 66 + .../src/com/fr/design/menu/ToolBarDef.java | 63 + .../fr/design/menu/TwoDottedSeparatorUI.java | 65 + .../src/com/fr/design/menu/UISeparatorUI.java | 58 + .../com/fr/design/module/DesignModule.java | 51 + .../fr/design/module/DesignModuleFactory.java | 1 + .../src/com/fr/design/object/NameObject.java | 70 + .../parameter/AbstractParameterReader.java | 30 + .../design/parameter/HierarchyTreePane.java | 1 + .../fr/design/parameter/ParaDefinitePane.java | 1 + .../design/parameter/ParameterArrayPane.java | 100 + .../fr/design/parameter/ParameterBridge.java | 51 + .../parameter/ParameterDesignerProvider.java | 1 + .../fr/design/parameter/ParameterGroup.java | 21 + .../design/parameter/ParameterInputPane.java | 227 + .../parameter/ParameterManagerPane.java | 61 + .../fr/design/parameter/ParameterPane.java | 92 + .../fr/design/parameter/ParameterReader.java | 28 + .../fr/design/present/DictPresentPane.java | 53 + .../fr/design/present/FormulaPresentPane.java | 47 + .../fr/design/present/NonePresentPane.java | 38 + .../design/present/dict/AbstractDicPane.java | 10 + .../dict/CustomDictCorrelationPane.java | 32 + .../design/present/dict/CustomDictPane.java | 82 + .../design/present/dict/DatabaseDictPane.java | 293 + .../design/present/dict/DictionaryPane.java | 72 + .../design/present/dict/FormulaDictPane.java | 107 + .../present/dict/TableDataDictPane.java | 355 + .../com/fr/design/preview/PagePreview.java | 32 + .../com/fr/design/preview/ViewPreview.java | 42 + .../com/fr/design/preview/WritePreview.java | 42 + .../roleAuthority/ReportAndFSManagePane.java | 1 + .../design/roleAuthority/RoleDataWrapper.java | 1 + .../fr/design/roleAuthority/RoleSourceOP.java | 1 + .../com/fr/design/roleAuthority/RoleTree.java | 1 + .../roleAuthority/RolesAlreadyEditedPane.java | 1 + .../roleAuthority/RolesEditedSourceOP.java | 1 + .../fr/design/roleAuthority/UIRoleTreeUI.java | 25 + .../com/fr/design/scrollruler/BaseRuler.java | 118 + .../design/scrollruler/HorizontalRuler.java | 18 + .../design/scrollruler/HorizontalRulerUI.java | 68 + .../fr/design/scrollruler/ModLineBorder.java | 165 + .../fr/design/scrollruler/RulerLayout.java | 154 + .../com/fr/design/scrollruler/RulerUI.java | 90 + .../scrollruler/ScrollRulerComponent.java | 28 + .../fr/design/scrollruler/VerticalRuler.java | 18 + .../design/scrollruler/VerticalRulerUI.java | 65 + .../com/fr/design/selection/QuickEditor.java | 53 + .../design/selection/SelectableElement.java | 20 + .../com/fr/design/selection/Selectedable.java | 25 + .../fr/design/selection/SelectionEvent.java | 16 + .../design/selection/SelectionListener.java | 14 + .../com/fr/design/style/AbstractPopBox.java | 232 + .../fr/design/style/AbstractSelectBox.java | 154 + .../com/fr/design/style/AlignmentPane.java | 393 + .../src/com/fr/design/style/AlphaPane.java | 124 + .../src/com/fr/design/style/BorderPane.java | 731 + .../com/fr/design/style/ChooseFileView.java | 185 + .../com/fr/design/style/CustomSelectBox.java | 64 + .../src/com/fr/design/style/FRFontPane.java | 404 + .../fr/design/style/FRFontPreviewArea.java | 74 + .../com/fr/design/style/FontFamilyPane.java | 79 + .../fr/design/style/FontSizeStylePane.java | 106 + .../src/com/fr/design/style/FormatBox.java | 208 + .../src/com/fr/design/style/FormatPane.java | 489 + .../BackgroundCustomJComponent.java | 66 + .../background/BackgroundJComponent.java | 44 + .../style/background/BackgroundPane.java | 957 + .../background/BackgroundPane4BoxChange.java | 26 + .../background/BackgroundPreviewLabel.java | 74 + .../background/BackgroundSelectPane.java | 80 + .../BackgroundUIComboBoxNoImagePane.java | 34 + .../background/BackgroundUIComboBoxPane.java | 167 + .../GradientBackgroundSelectPane.java | 118 + .../background/gradient/GradientBar.java | 307 + .../gradient/GradientChangeBoxPane.java | 129 + .../gradient/GradientFromToPixPane.java | 67 + .../background/gradient/GradientPane.java | 135 + .../gradient/GradientSelectBox.java | 84 + .../gradient/SelectColorPointBtn.java | 96 + .../background/image/ImageFileChooser.java | 255 + .../background/image/ImagePreviewPane.java | 257 + .../background/image/ImageSelectPane.java | 164 + .../background/pattern/PatternSelectBox.java | 51 + .../background/pattern/PatternSelectPane.java | 34 + .../pattern/PatternUIComboBoxPane.java | 63 + .../background/texture/TextureSelectBox.java | 51 + .../background/texture/TextureSelectPane.java | 32 + .../texture/TextureUIComboBoxPane.java | 43 + .../com/fr/design/style/color/ColorCell.java | 119 + .../style/color/ColorChooserPreview.java | 203 + .../style/color/ColorControlWindow.java | 81 + .../fr/design/style/color/ColorFactory.java | 75 + .../fr/design/style/color/ColorSelectBox.java | 103 + .../style/color/ColorSelectConfigManager.java | 56 + .../style/color/ColorSelectDetailPane.java | 112 + .../design/style/color/ColorSelectDialog.java | 178 + .../design/style/color/ColorSelectPane.java | 185 + .../design/style/color/ColorSelectable.java | 15 + .../style/color/ColorUIComboBoxPane.java | 59 + .../style/color/CustomChooserPanel.java | 1072 + .../style/color/DetailColorSelectPane.java | 106 + .../design/style/color/NewColorSelectBox.java | 96 + .../style/color/NewColorSelectPane.java | 204 + .../style/color/RecentUseColorPane.java | 55 + .../style/color/SwatchChooserPanel.java | 616 + .../color/TransparentColorControlWindow.java | 24 + .../design/style/color/TransparentPane.java | 85 + .../style/color/UIToolbarColorButton.java | 253 + .../fr/design/style/color/UsedColorPane.java | 86 + .../com/fr/design/utils/ColorRoutines.java | 1012 + .../com/fr/design/utils/ComponentUtils.java | 151 + .../src/com/fr/design/utils/DesignUtils.java | 463 + .../src/com/fr/design/utils/DrawRoutines.java | 354 + .../src/com/fr/design/utils/ThemeUtils.java | 185 + .../com/fr/design/utils/gui/GUICoreUtils.java | 820 + .../fr/design/utils/gui/GUIPaintUtils.java | 186 + .../com/fr/design/utils/gui/JListUtils.java | 68 + .../com/fr/design/utils/gui/LayoutUtils.java | 81 + .../src/com/fr/design/web/CustomIconPane.java | 445 + .../src/com/fr/design/widget/Appearance.java | 33 + .../com/fr/design/widget/IconDefinePane.java | 101 + .../fr/design/widget/btn/ButtonConstants.java | 47 + .../design/widget/btn/ButtonDetailPane.java | 62 + .../btn/ButtonWithHotkeysDetailPane.java | 77 + .../fr/design/write/submit/CustomJobPane.java | 1 + .../write/submit/CustomSubmitJobPane.java | 19 + .../DBManipulationInWidgetEventPane.java | 37 + .../write/submit/DBManipulationPane.java | 1106 + .../fr/design/write/submit/DMLJobPane.java | 37 + .../write/submit/SubmitJobListPane.java | 63 + designer_base/src/com/fr/env/EnvListPane.java | 592 + designer_base/src/com/fr/env/RemoteEnv.java | 2054 ++ .../src/com/fr/env/RemoteSignInPane.java | 47 + designer_base/src/com/fr/env/SignIn.java | 42 + designer_base/src/com/fr/file/FILE.java | 93 + .../src/com/fr/file/FILEChooserPane.java | 1431 + .../src/com/fr/file/FILEFactory.java | 56 + designer_base/src/com/fr/file/FileFILE.java | 270 + .../src/com/fr/file/FileNodeFILE.java | 414 + designer_base/src/com/fr/file/MemFILE.java | 155 + .../com/fr/file/filter/ChooseFileFilter.java | 260 + .../src/com/fr/file/filter/FILEFilter.java | 27 + .../filter/OnlyShowDirectoryFileFilter.java | 13 + .../src/com/fr/plugin/PluginManager.java | 128 + .../com/fr/start/BBSGuestPaneProvider.java | 15 + .../src/com/fr/start/BaseDesigner.java | 280 + designer_base/src/com/fr/start/Demo.java | 49 + .../src/com/fr/start/JettyFRHost.java | 1 + .../src/com/fr/start/SplashPane.java | 78 + .../src/com/fr/start/SplashWindow.java | 68 + .../src/com/fr/start/StartDocURL.java | 48 + .../src/com/fr/start/StartServer.java | 200 + .../src/com/fr/start/server/JettyHost.java | 286 + .../fr/start/server/JettyServerListener.java | 18 + .../fr/start/server/MultiOutputStream.java | 62 + .../fr/start/server/ServerManageFrame.java | 168 + .../src/com/fr/start/server/ServerTray.java | 207 + 2198 files changed, 295464 insertions(+) create mode 100644 designer_base/.classpath create mode 100644 designer_base/.project create mode 100644 designer_base/designer_base.iml create mode 100644 designer_base/src/com/fr/design/DesignModelAdapter.java create mode 100644 designer_base/src/com/fr/design/DesignState.java create mode 100644 designer_base/src/com/fr/design/DesignerEnvManager.java create mode 100644 designer_base/src/com/fr/design/Exception/ValidationException.java create mode 100644 designer_base/src/com/fr/design/ExtraDesignClassManager.java create mode 100644 designer_base/src/com/fr/design/RestartHelper.java create mode 100644 designer_base/src/com/fr/design/actions/AllowAuthorityEditAction.java create mode 100644 designer_base/src/com/fr/design/actions/CheckBoxAction.java create mode 100644 designer_base/src/com/fr/design/actions/ExitAuthorityEditAction.java create mode 100644 designer_base/src/com/fr/design/actions/HyperlinkPluginAction.java create mode 100644 designer_base/src/com/fr/design/actions/JTemplateAction.java create mode 100644 designer_base/src/com/fr/design/actions/MenuAction.java create mode 100644 designer_base/src/com/fr/design/actions/TableDataSourceAction.java create mode 100644 designer_base/src/com/fr/design/actions/TemplateComponentAction.java create mode 100644 designer_base/src/com/fr/design/actions/TemplateComponentActionInterface.java create mode 100644 designer_base/src/com/fr/design/actions/ToggleButtonUpdateAction.java create mode 100644 designer_base/src/com/fr/design/actions/ToolbarActionManager.java create mode 100644 designer_base/src/com/fr/design/actions/UndoableAction.java create mode 100644 designer_base/src/com/fr/design/actions/UpdateAction.java create mode 100644 designer_base/src/com/fr/design/actions/core/ActionUtils.java create mode 100644 designer_base/src/com/fr/design/actions/edit/CopyAction.java create mode 100644 designer_base/src/com/fr/design/actions/edit/CutAction.java create mode 100644 designer_base/src/com/fr/design/actions/edit/PasteAction.java create mode 100644 designer_base/src/com/fr/design/actions/edit/RedoAction.java create mode 100644 designer_base/src/com/fr/design/actions/edit/UndoAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/CloseCurrentTemplateAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/CloseTemplateAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/EditEnvAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/ExitDesignerAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/LocalePane.java create mode 100644 designer_base/src/com/fr/design/actions/file/OpenRecentReportMenuDef.java create mode 100644 designer_base/src/com/fr/design/actions/file/OpenTemplateAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/PreferenceAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/PreferencePane.java create mode 100644 designer_base/src/com/fr/design/actions/file/SaveAsTemplateAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/SaveTemplateAction.java create mode 100644 designer_base/src/com/fr/design/actions/file/SwitchExistEnv.java create mode 100644 designer_base/src/com/fr/design/actions/file/WebPreviewUtils.java create mode 100644 designer_base/src/com/fr/design/actions/help/AboutAction.java create mode 100644 designer_base/src/com/fr/design/actions/help/AboutDialog.java create mode 100644 designer_base/src/com/fr/design/actions/help/AboutPane.java create mode 100644 designer_base/src/com/fr/design/actions/help/FeedBackAction.java create mode 100644 designer_base/src/com/fr/design/actions/help/FeedBackPane.java create mode 100644 designer_base/src/com/fr/design/actions/help/ForumAction.java create mode 100644 designer_base/src/com/fr/design/actions/help/SupportQQAction.java create mode 100644 designer_base/src/com/fr/design/actions/help/SystemInfoPane.java create mode 100644 designer_base/src/com/fr/design/actions/help/TutorialAction.java create mode 100644 designer_base/src/com/fr/design/actions/help/WebDemoAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/ConnectionListAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/FunctionManagerAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/GlobalParameterAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/GlobalTableDataAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/PlatformManagerAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/PluginManagerAction.java create mode 100644 designer_base/src/com/fr/design/actions/server/ProcedureListAction.java create mode 100644 designer_base/src/com/fr/design/actions/tabledata/TableDataAction.java create mode 100644 designer_base/src/com/fr/design/beans/BasicBeanPane.java create mode 100644 designer_base/src/com/fr/design/beans/FurtherBasicBeanPane.java create mode 100644 designer_base/src/com/fr/design/beans/GroupModel.java create mode 100644 designer_base/src/com/fr/design/beans/location/Absorptionline.java create mode 100644 designer_base/src/com/fr/design/beans/location/MoveUtils.java create mode 100644 designer_base/src/com/fr/design/border/UIRoundedBorder.java create mode 100644 designer_base/src/com/fr/design/border/UITitledBorder.java create mode 100644 designer_base/src/com/fr/design/bridge/DesignToolbarProvider.java create mode 100644 designer_base/src/com/fr/design/cell/FloatElementsProvider.java create mode 100644 designer_base/src/com/fr/design/condition/CellHighlightAddMenuDef.java create mode 100644 designer_base/src/com/fr/design/condition/ConditionAttrSingleConditionPane.java create mode 100644 designer_base/src/com/fr/design/condition/ConditionAttributesPane.java create mode 100644 designer_base/src/com/fr/design/condition/ContinuousTreeSelectionModel.java create mode 100644 designer_base/src/com/fr/design/condition/DSColumnLiteConditionPane.java create mode 100644 designer_base/src/com/fr/design/condition/DSColumnSimpleLiteConditionPane.java create mode 100644 designer_base/src/com/fr/design/condition/HighLightConditionAction.java create mode 100644 designer_base/src/com/fr/design/condition/LiteConditionPane.java create mode 100644 designer_base/src/com/fr/design/condition/ObjectLiteConditionPane.java create mode 100644 designer_base/src/com/fr/design/condition/SingleConditionPane.java create mode 100644 designer_base/src/com/fr/design/constants/KeyWords.java create mode 100644 designer_base/src/com/fr/design/constants/LayoutConstants.java create mode 100644 designer_base/src/com/fr/design/constants/UIConstants.java create mode 100644 designer_base/src/com/fr/design/data/DataCreatorUI.java create mode 100644 designer_base/src/com/fr/design/data/DesignTableDataManager.java create mode 100644 designer_base/src/com/fr/design/data/datapane/ChoosePane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/ChoosePaneSupportFormula.java create mode 100644 designer_base/src/com/fr/design/data/datapane/DSButtonGroup.java create mode 100644 designer_base/src/com/fr/design/data/datapane/DataBaseItems.java create mode 100644 designer_base/src/com/fr/design/data/datapane/EditOrNewLabel.java create mode 100644 designer_base/src/com/fr/design/data/datapane/FlashLookLabelMouseAdapter.java create mode 100644 designer_base/src/com/fr/design/data/datapane/GlobalTableDataComboBox.java create mode 100644 designer_base/src/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/RefreshLabel.java create mode 100644 designer_base/src/com/fr/design/data/datapane/ReportTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataComboBox.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataCreatorProducer.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataListPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataNameObjectCreator.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataSourceOP.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataTree.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataTreeDragSource.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TableDataTreePane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TreeTableDataComboBox.java create mode 100644 designer_base/src/com/fr/design/data/datapane/TreeTableDataDictPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/VerticalChoosePane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/ConnectionListPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/ConnectionManagerPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/DataConnectionAction.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/JDBCDefPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/connect/JNDIDefPane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/preview/LoadedEventListener.java create mode 100644 designer_base/src/com/fr/design/data/datapane/preview/PreviewLabel.java create mode 100644 designer_base/src/com/fr/design/data/datapane/preview/PreviewTableModel.java create mode 100644 designer_base/src/com/fr/design/data/datapane/preview/PreviewTablePane.java create mode 100644 designer_base/src/com/fr/design/data/datapane/sqlpane/SQLEditPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/Prepare4DataSourceChange.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/ResponseDataSourceChange.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/StoreProcedureWorkerListener.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/gui/CONTENT.txt create mode 100644 designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN1.txt create mode 100644 designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN2.txt create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/AbstractTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/AutoStoreProcedureTableModel.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassNameSelectPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/CustomDictModel.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/DecoratedTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataDefinedPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableModel.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallHeightPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/FormatExplanationPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalMultiTDTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalTreeTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/OneListTableModel.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureListPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureManagerPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureParameterPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureTableModel.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/TableDataManagerPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/tabledatapane/TreeTableDataPane.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/AbstractTableDataWrapper.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/ServerTableDataWrapper.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureNameWrapper.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataFactory.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataWrapper.java create mode 100644 designer_base/src/com/fr/design/data/tabledata/wrapper/TemplateTableDataWrapper.java create mode 100644 designer_base/src/com/fr/design/designer/EditingState.java create mode 100644 designer_base/src/com/fr/design/designer/TargetComponent.java create mode 100644 designer_base/src/com/fr/design/dialog/BasicDialog.java create mode 100644 designer_base/src/com/fr/design/dialog/BasicPane.java create mode 100644 designer_base/src/com/fr/design/dialog/BasicScrollPane.java create mode 100644 designer_base/src/com/fr/design/dialog/DialogActionAdapter.java create mode 100644 designer_base/src/com/fr/design/dialog/DialogActionListener.java create mode 100644 designer_base/src/com/fr/design/dialog/InformationWarnPane.java create mode 100644 designer_base/src/com/fr/design/dialog/JWizardDialog.java create mode 100644 designer_base/src/com/fr/design/dialog/JWizardPanel.java create mode 100644 designer_base/src/com/fr/design/dialog/MultiTabPane.java create mode 100644 designer_base/src/com/fr/design/dialog/UIDialog.java create mode 100644 designer_base/src/com/fr/design/dialog/package.html create mode 100644 designer_base/src/com/fr/design/editor/ValueEditorPane.java create mode 100644 designer_base/src/com/fr/design/editor/ValueEditorPaneFactory.java create mode 100644 designer_base/src/com/fr/design/editor/editor/BooleanEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ColumnIndexEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ColumnNameEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ColumnRowEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ColumnRowGroupEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ColumnSelectedEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ConstantsEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/CursorEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/DateEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/DoubleEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/Editor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/EditorListener.java create mode 100644 designer_base/src/com/fr/design/editor/editor/FloatEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/FormulaEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/IntegerEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/LongEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/NoneEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/NumberEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/OldColumnIndexEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/ParameterEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/TextEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/WidgetNameEditor.java create mode 100644 designer_base/src/com/fr/design/editor/editor/XMLANameEditor.java create mode 100644 designer_base/src/com/fr/design/event/ChangeEvent.java create mode 100644 designer_base/src/com/fr/design/event/ChangeListener.java create mode 100644 designer_base/src/com/fr/design/event/GlobalNameListener.java create mode 100644 designer_base/src/com/fr/design/event/GlobalNameObserver.java create mode 100644 designer_base/src/com/fr/design/event/TargetModifiedEvent.java create mode 100644 designer_base/src/com/fr/design/event/TargetModifiedListener.java create mode 100644 designer_base/src/com/fr/design/event/TemplateTreeDragSource.java create mode 100644 designer_base/src/com/fr/design/event/UIObserver.java create mode 100644 designer_base/src/com/fr/design/event/UIObserverListener.java create mode 100644 designer_base/src/com/fr/design/extra/After.java create mode 100644 designer_base/src/com/fr/design/extra/AppStoreBuilder.java create mode 100644 designer_base/src/com/fr/design/extra/LoginCheckContext.java create mode 100644 designer_base/src/com/fr/design/extra/LoginCheckListener.java create mode 100644 designer_base/src/com/fr/design/extra/PluginAbstractLoadingViewPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginAbstractViewPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginConstants.java create mode 100644 designer_base/src/com/fr/design/extra/PluginControlPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginDescriptionLabel.java create mode 100644 designer_base/src/com/fr/design/extra/PluginDetailPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginFromStorePane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginHelper.java create mode 100644 designer_base/src/com/fr/design/extra/PluginInstalledPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginListPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginManagerPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginSelectListener.java create mode 100644 designer_base/src/com/fr/design/extra/PluginStatusCheckCompletePane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginTask.java create mode 100644 designer_base/src/com/fr/design/extra/PluginUpdatePane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginWebBridge.java create mode 100644 designer_base/src/com/fr/design/extra/PluginWebPane.java create mode 100644 designer_base/src/com/fr/design/extra/PluginsReaderFromStore.java create mode 100644 designer_base/src/com/fr/design/extra/Process.java create mode 100644 designer_base/src/com/fr/design/extra/exe/Command.java create mode 100644 designer_base/src/com/fr/design/extra/exe/Executor.java create mode 100644 designer_base/src/com/fr/design/extra/exe/InstallFromDiskExecutor.java create mode 100644 designer_base/src/com/fr/design/extra/exe/InstallOnlineExecutor.java create mode 100644 designer_base/src/com/fr/design/extra/exe/ModifyStatusExecutor.java create mode 100644 designer_base/src/com/fr/design/extra/exe/UninstallExecutor.java create mode 100644 designer_base/src/com/fr/design/extra/exe/UpdateFromDiskExecutor.java create mode 100644 designer_base/src/com/fr/design/extra/exe/UpdateOnlineExecutor.java create mode 100644 designer_base/src/com/fr/design/extra/plugin.properties create mode 100644 designer_base/src/com/fr/design/file/FileOperations.java create mode 100644 designer_base/src/com/fr/design/file/FileToolbarStateChangeListener.java create mode 100644 designer_base/src/com/fr/design/file/HistoryTemplateListPane.java create mode 100644 designer_base/src/com/fr/design/file/MutilTempalteTabPane.java create mode 100644 designer_base/src/com/fr/design/file/NewTemplatePane.java create mode 100644 designer_base/src/com/fr/design/file/SaveSomeTemplatePane.java create mode 100644 designer_base/src/com/fr/design/file/TemplateTreePane.java create mode 100644 designer_base/src/com/fr/design/formula/AbstractNameAndDescription.java create mode 100644 designer_base/src/com/fr/design/formula/CustomVariableResolver.java create mode 100644 designer_base/src/com/fr/design/formula/DefaultUIFormulaProcessor.java create mode 100644 designer_base/src/com/fr/design/formula/FormulaFactory.java create mode 100644 designer_base/src/com/fr/design/formula/FormulaPane.java create mode 100644 designer_base/src/com/fr/design/formula/FormulaPaneWhenReserveFormula.java create mode 100644 designer_base/src/com/fr/design/formula/FunctionConstants.java create mode 100644 designer_base/src/com/fr/design/formula/FunctionDefNAD.java create mode 100644 designer_base/src/com/fr/design/formula/FunctionGroup.java create mode 100644 designer_base/src/com/fr/design/formula/FunctionManagerPane.java create mode 100644 designer_base/src/com/fr/design/formula/FunctionNAD.java create mode 100644 designer_base/src/com/fr/design/formula/JavaEditorPane.java create mode 100644 designer_base/src/com/fr/design/formula/NameAndDescription.java create mode 100644 designer_base/src/com/fr/design/formula/NameAndFunctionList.java create mode 100644 designer_base/src/com/fr/design/formula/NameAndTypeAndFunctionList.java create mode 100644 designer_base/src/com/fr/design/formula/SortFormulaPane.java create mode 100644 designer_base/src/com/fr/design/formula/TinyFormulaPane.java create mode 100644 designer_base/src/com/fr/design/formula/UIFormula.java create mode 100644 designer_base/src/com/fr/design/formula/VariableResolver.java create mode 100644 designer_base/src/com/fr/design/formula/VariableResolverAdapter.java create mode 100644 designer_base/src/com/fr/design/fun/CellAttributeProvider.java create mode 100644 designer_base/src/com/fr/design/fun/CellWidgetOptionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/ConnectionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/ExportToolBarProvider.java create mode 100644 designer_base/src/com/fr/design/fun/Feedback.java create mode 100644 designer_base/src/com/fr/design/fun/FormElementCaseEditorProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/FormWidgetOptionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/GlobalListenerProvider.java create mode 100644 designer_base/src/com/fr/design/fun/HighlightProvider.java create mode 100644 designer_base/src/com/fr/design/fun/HyperlinkProvider.java create mode 100644 designer_base/src/com/fr/design/fun/IndentationUnitProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/MenuHandler.java create mode 100644 designer_base/src/com/fr/design/fun/ParameterWidgetOptionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/PresentKindProvider.java create mode 100644 designer_base/src/com/fr/design/fun/PreviewProvider.java create mode 100644 designer_base/src/com/fr/design/fun/ServerTableDataDefineProvider.java create mode 100644 designer_base/src/com/fr/design/fun/SubmitProvider.java create mode 100644 designer_base/src/com/fr/design/fun/TableDataCreatorProvider.java create mode 100644 designer_base/src/com/fr/design/fun/TableDataDefineProvider.java create mode 100644 designer_base/src/com/fr/design/fun/TitlePlaceProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/ToolbarItemProvider.java create mode 100644 designer_base/src/com/fr/design/fun/UIFormulaProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractCellAttributeProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractCellWidgetOptionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractConnectionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractFormElementCaseEditorProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractFormWidgetOptionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractGlobalListenerProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractHighlightProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractHyperlinkProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractIndentationUnitProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractMenuHandler.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractParameterWidgetOptionProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractPresentKindProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractPreviewProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractServerTableDataDefineProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractSubmitProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractTableDataDefineProvider.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractTitleProcessor.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractToolbarItem.java create mode 100644 designer_base/src/com/fr/design/fun/impl/AbstractUIFormulaProcessor.java create mode 100644 designer_base/src/com/fr/design/gui/UIDefaultTheme.java create mode 100644 designer_base/src/com/fr/design/gui/UILookAndFeel.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDemo.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDescWindow.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AutoCompletePopupWindow.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AutoCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/AutoCompletionStyleContext.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/BasicCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/Completion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/CompletionCellRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/CompletionListModel.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/CompletionProvider.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/CompletionProviderBase.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/CompletionXMLParser.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/CompletionXml.dtd create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/DelegatingCellRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/DescWindowCallback.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/EmptyIcon.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ExternalURLHandler.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/FastListUI.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/FunctionCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/LinkRedirector.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/MarkupTagCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/OutlineHighlightPainter.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ParameterChoicesProvider.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionChoicesWindow.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionDescriptionToolTip.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionInsertionInfo.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/ShorthandCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/SizeGrip.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/SortByRelevanceComparator.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/TemplateCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/TemplatePiece.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/TipUtil.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/Util.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/VariableCompletion.java create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/arrow_left.png create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/arrow_right.png create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/bullet_black.png create mode 100644 designer_base/src/com/fr/design/gui/autocomplete/osx_sizegrip.png create mode 100644 designer_base/src/com/fr/design/gui/borders/UIFrameBorder.java create mode 100644 designer_base/src/com/fr/design/gui/borders/UIInternalFrameBorder.java create mode 100644 designer_base/src/com/fr/design/gui/borders/UITableHeaderBorder.java create mode 100644 designer_base/src/com/fr/design/gui/borders/UITableHeaderRolloverBorder.java create mode 100644 designer_base/src/com/fr/design/gui/borders/UITableScrollPaneBorder.java create mode 100644 designer_base/src/com/fr/design/gui/borders/UITextFieldBorder.java create mode 100644 designer_base/src/com/fr/design/gui/chart/BaseChartPropertyPane.java create mode 100644 designer_base/src/com/fr/design/gui/chart/MiddleChartComponent.java create mode 100644 designer_base/src/com/fr/design/gui/chart/MiddleChartDialog.java create mode 100644 designer_base/src/com/fr/design/gui/columnrow/ColumnRowPane.java create mode 100644 designer_base/src/com/fr/design/gui/columnrow/ColumnRowVerticalPane.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/AbstractNameableCreator.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/ControlPane.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/JControlPane.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/NameObjectCreator.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/NameableCreator.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/NameableSelfCreator.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/ObjectJControlPane.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/ShortCut4JControlPane.java create mode 100644 designer_base/src/com/fr/design/gui/controlpane/UnrepeatedNameHelper.java create mode 100644 designer_base/src/com/fr/design/gui/core/CustomWidgetOption.java create mode 100644 designer_base/src/com/fr/design/gui/core/UIFurtherTabComponent.java create mode 100644 designer_base/src/com/fr/design/gui/core/UISelectedComponent.java create mode 100644 designer_base/src/com/fr/design/gui/core/UITabComponent.java create mode 100644 designer_base/src/com/fr/design/gui/core/UserDefinedWidgetOption.java create mode 100644 designer_base/src/com/fr/design/gui/core/WidgetConstants.java create mode 100644 designer_base/src/com/fr/design/gui/core/WidgetOption.java create mode 100644 designer_base/src/com/fr/design/gui/core/WidgetOptionFactory.java create mode 100644 designer_base/src/com/fr/design/gui/date/CalendarNumberField.java create mode 100644 designer_base/src/com/fr/design/gui/date/JDateDocument.java create mode 100644 designer_base/src/com/fr/design/gui/date/SingleObjectComboBoxModel.java create mode 100644 designer_base/src/com/fr/design/gui/date/UICalendarPanel.java create mode 100644 designer_base/src/com/fr/design/gui/date/UIDatePicker.java create mode 100644 designer_base/src/com/fr/design/gui/date/UIDayLabel.java create mode 100644 designer_base/src/com/fr/design/gui/demo/ComboBoxDemo.java create mode 100644 designer_base/src/com/fr/design/gui/demo/LabelDemo.java create mode 100644 designer_base/src/com/fr/design/gui/demo/ListDemo.java create mode 100644 designer_base/src/com/fr/design/gui/demo/LoadingPaneDemo.java create mode 100644 designer_base/src/com/fr/design/gui/demo/MultiLineTooltipDemo.java create mode 100644 designer_base/src/com/fr/design/gui/demo/SwingComponentsDemo.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/AttributeChangeListener.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/BaseHyperlinkGroup.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/CommitTabbedPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/EditingStringListPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupType.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/ImgChoosePane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/JTreeAutoBuildPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/JTreeControlPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/LimitedDocument.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/ListenerUpdatePane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/LoadingBasicPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/LoadingBasicPaneTest.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/ObjectProperiesPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/RegPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/ReportletParameterViewPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/TemplateParameterPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/TreeSettingPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UIAdvancedTextPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UIBasicOptionPaneUI.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UIBubbleFloatPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UIComboBoxPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UICorrelationComboBoxPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UICorrelationPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UIExtensionPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UINumberDragPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UINumberSlidePane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UIRadioPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UITabbedPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UITabbedPaneUI.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UITextPane.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UITitlePanel.java create mode 100644 designer_base/src/com/fr/design/gui/frpane/UnitInputPane.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/FiveButtonLayout.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/SpecialUIButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIBasicButtonUI.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIButtonBorder.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIButtonGroup.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIButtonUI.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIColorButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UICombinationButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIHeadGroup.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIPasswordField.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIPreviewButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIRadioButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonIcon.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonMenuItemUI.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonUI.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UITabButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UITabGroup.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIToggleButton.java create mode 100644 designer_base/src/com/fr/design/gui/ibutton/UIToolButtonBorder.java create mode 100644 designer_base/src/com/fr/design/gui/icheckbox/UICheckBox.java create mode 100644 designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxIcon.java create mode 100644 designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxUI.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/AlignmentComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/ComboCheckBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/DictionaryComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/DictionaryConstants.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBoxTest.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/FRTreeComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/FilterComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/FilterableComboBoxModel.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/FixedHeightComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/FunctionComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/IntComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/LazyComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/LazyComboBoxTest.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/LineComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/ParameterComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/SortOrderComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/TreeComboBoxUI.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxEditor.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxUI.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIComboBoxButton.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIComboBoxEditor.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIComboBoxRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIComboBoxUI.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/UIDictionaryComboBox.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/filter/Filter.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/filter/LastStartWithFilter.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/filter/StartsWithFilter.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeCellRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeLabel.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNode.java create mode 100644 designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNodeSelectionListener.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UIModeControlContainer.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UIResizableContainer.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UIScrollPane.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneBorder.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneUI.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UITableScrollPaneBorder.java create mode 100644 designer_base/src/com/fr/design/gui/icontainer/UIVerticalScrollPane.java create mode 100644 designer_base/src/com/fr/design/gui/ilable/ActionLabel.java create mode 100644 designer_base/src/com/fr/design/gui/ilable/BoldFontTextLabel.java create mode 100644 designer_base/src/com/fr/design/gui/ilable/FRExplainLabel.java create mode 100644 designer_base/src/com/fr/design/gui/ilable/MultilineLabel.java create mode 100644 designer_base/src/com/fr/design/gui/ilable/UILabel.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/ArrayListModel.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/CheckBoxList.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/DefaultListCellEditor.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/JNameEdList.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/ListCellEditor.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/ListModelElement.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/ModNameActionListener.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/QuickList.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/TableViewList.java create mode 100644 designer_base/src/com/fr/design/gui/ilist/UIList.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIBasicMenuItemUI.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIBasicMenuUI.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UICheckBoxMenuItem.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIListPopup.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIMenu.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIMenuBar.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIMenuBarUI.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIMenuHighLight.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIMenuItem.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIMenuUI.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIPopupMenu.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIPopupMenuBorder.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIPopupMenuSeparatorUI.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIScrollMenu.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIScrollMenuDemo.java create mode 100644 designer_base/src/com/fr/design/gui/imenu/UIScrollPopUpMenu.java create mode 100644 designer_base/src/com/fr/design/gui/imenutable/UIMenuNameableCreator.java create mode 100644 designer_base/src/com/fr/design/gui/imenutable/UIMenuTable.java create mode 100644 designer_base/src/com/fr/design/gui/imenutable/UIMenuTableDataModel.java create mode 100644 designer_base/src/com/fr/design/gui/imenutable/UIMenuTableUI.java create mode 100644 designer_base/src/com/fr/design/gui/ipasswordfield/UIPassWordField.java create mode 100644 designer_base/src/com/fr/design/gui/ipoppane/PopupHider.java create mode 100644 designer_base/src/com/fr/design/gui/iprogressbar/AutoProgressBar.java create mode 100644 designer_base/src/com/fr/design/gui/iprogressbar/FRProgressBar.java create mode 100644 designer_base/src/com/fr/design/gui/iprogressbar/MonitorCancelWork.java create mode 100644 designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarBorder.java create mode 100644 designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarUI.java create mode 100644 designer_base/src/com/fr/design/gui/iscrollbar/UIBasicScrollBarUI.java create mode 100644 designer_base/src/com/fr/design/gui/iscrollbar/UISBChooser.java create mode 100644 designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBar.java create mode 100644 designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBarUI.java create mode 100644 designer_base/src/com/fr/design/gui/iscrollbar/UIScrollButton.java create mode 100644 designer_base/src/com/fr/design/gui/islider/UISlider.java create mode 100644 designer_base/src/com/fr/design/gui/ispinner/UIBasicSpinner.java create mode 100644 designer_base/src/com/fr/design/gui/ispinner/UISpinner.java create mode 100644 designer_base/src/com/fr/design/gui/ispinner/UISpinnerButtonUI.java create mode 100644 designer_base/src/com/fr/design/gui/ispinner/UISpinnerUI.java create mode 100644 designer_base/src/com/fr/design/gui/ispinner/UpperCaseSpinner.java create mode 100644 designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneDivider.java create mode 100644 designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneUI.java create mode 100644 designer_base/src/com/fr/design/gui/itable/AbstractPropertyTable.java create mode 100644 designer_base/src/com/fr/design/gui/itable/GroupRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/itable/HeaderRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/itable/PropertyGroup.java create mode 100644 designer_base/src/com/fr/design/gui/itable/SortableJTable.java create mode 100644 designer_base/src/com/fr/design/gui/itable/TableSorter.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UIBasicTableUI.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UIComponentTable.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UIDefaultTableCellEditor.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UISelectTable.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UITable.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UITableComponentModel.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UITableDataModel.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UITableEditor.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UITableNoOptionUI.java create mode 100644 designer_base/src/com/fr/design/gui/itable/UITableUI.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/ActionStyle.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/ParameterTableModel.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/UIArrayTableModel.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditAction.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorLoader.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorPane.java create mode 100644 designer_base/src/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java create mode 100644 designer_base/src/com/fr/design/gui/itabpane/TitleChangeListener.java create mode 100644 designer_base/src/com/fr/design/gui/itabpane/UITabPaneCreator.java create mode 100644 designer_base/src/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java create mode 100644 designer_base/src/com/fr/design/gui/itextarea/DescriptionTextArea.java create mode 100644 designer_base/src/com/fr/design/gui/itextarea/FRExplainTextArea.java create mode 100644 designer_base/src/com/fr/design/gui/itextarea/UITextArea.java create mode 100644 designer_base/src/com/fr/design/gui/itextarea/UITextAreaUI.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/AutoCompletionDemo.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/CompletionFilter.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/DefaultCompletionFilter.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/EditTextField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/FRGraphics2D.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/PlaceholderTextField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/TextFieldUI.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/UIAutoCompletionField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/UIGridTextField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/UINumberField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/UISearchTextField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/UITextField.java create mode 100644 designer_base/src/com/fr/design/gui/itextfield/UITextFieldUI.java create mode 100644 designer_base/src/com/fr/design/gui/itoolbar/UILargeToolbar.java create mode 100644 designer_base/src/com/fr/design/gui/itoolbar/UIToolBarBorder.java create mode 100644 designer_base/src/com/fr/design/gui/itoolbar/UIToolBarSeparatorUI.java create mode 100644 designer_base/src/com/fr/design/gui/itoolbar/UIToolBarUI.java create mode 100644 designer_base/src/com/fr/design/gui/itoolbar/UIToolbar.java create mode 100644 designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTip.java create mode 100644 designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTipUI.java create mode 100644 designer_base/src/com/fr/design/gui/itooltip/UIToolTip.java create mode 100644 designer_base/src/com/fr/design/gui/itooltip/UIToolTipBorder.java create mode 100644 designer_base/src/com/fr/design/gui/itooltip/UIToolTipUI.java create mode 100644 designer_base/src/com/fr/design/gui/itree/UITreeUI.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeSelectionModel.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/NullLabel.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/NullPanel.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java create mode 100644 designer_base/src/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/AbstractFileTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/ClassFileTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/EnvFileTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/FileComparator.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/FileDirectoryNode.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/FileNodeComparator.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/FileTreeIcon.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/JFileTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/ReportletPane.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/RootFile.java create mode 100644 designer_base/src/com/fr/design/gui/itree/filetree/TemplateFileTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTreeTest.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeDataCardPane.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeNodePane.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectOP.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectRefreshJTree.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenLoaderFactory.java create mode 100644 designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenNodesLoader.java create mode 100644 designer_base/src/com/fr/design/gui/style/AbstractBasicStylePane.java create mode 100644 designer_base/src/com/fr/design/gui/style/AlignmentPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/BackgroundNoImagePane.java create mode 100644 designer_base/src/com/fr/design/gui/style/BackgroundPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/BackgroundSpecialPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/BorderPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/DefaultIndentationUnitProcessor.java create mode 100644 designer_base/src/com/fr/design/gui/style/FRFontPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/FormatPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/FormatePaneNumField.java create mode 100644 designer_base/src/com/fr/design/gui/style/GradientPane.java create mode 100644 designer_base/src/com/fr/design/gui/style/NumberDragBar.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/io/DocumentReader.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/io/UnicodeReader.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/io/UnicodeWriter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/io/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/print/RPrintUtilities.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/print/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractJFlexCTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractJFlexTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractTokenMakerFactory.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ActiveLineRangeEvent.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ActiveLineRangeListener.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ChangeableColorHighlightPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/CodeTemplateManager.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultOccurrenceMarker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultTokenFactory.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultTokenMakerFactory.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultTokenPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DocumentRange.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ar.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_de.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_es.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_fr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_hu.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_in.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_it.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ja.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ko.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_nl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_pl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_pt_BR.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ru.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_tr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_zh_CN.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_zh_TW.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/FileFileLocation.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/FileLocation.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/FoldingAwareIconRowHeader.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/LinkGenerator.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/LinkGeneratorResult.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/MarkOccurrencesHighlightPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/MarkOccurrencesSupport.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/OccurrenceMarker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ParserManager.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/PopupWindowDecorator.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSTAView.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxDocument.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaDefaultInputMap.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaEditorKit.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaHighlighter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaUI.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ar.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_de.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_es.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_fr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_hu.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_in.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_it.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ja.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ko.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_nl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_pl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_pt_BR.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ru.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_tr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_zh_CN.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_zh_TW.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxUtilities.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RTfToText.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RtfGenerator.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RtfTransferable.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SelectRegionLinkGeneratorResult.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SquiggleUnderlineHighlightPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Style.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxConstants.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxView.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TextEditorPane.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Token.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenFactory.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenImpl.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenIterator.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMakerBase.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMakerFactory.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMap.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenOrientedView.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenTypes.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenUtils.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/URLFileLocation.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/VisibleWhitespaceTokenPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/WrappedSyntaxView.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/WrappedSyntaxView2.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/XmlOccurrenceMarker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ar.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_de.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_es.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_fr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_hu.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_in.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_it.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ja.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ko.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_nl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_pl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_pt_BR.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ru.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_tr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_zh_CN.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_zh_TW.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/SizeGrip.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/TipUtil.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/TipWindow.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/osx_sizegrip.png create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/CurlyFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/Fold.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldCollapser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldManager.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldParserManager.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldType.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/HtmlFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/JsonFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/LatexFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/LispFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/NsisFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/XmlFoldParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/AbstractMarkupTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ActionScriptTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ActionScriptTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/AssemblerX86TokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/AssemblerX86TokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/BBCodeTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/BBCodeTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CPlusPlusTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CPlusPlusTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSSTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSSTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSharpTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSharpTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ClojureTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ClojureTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DelphiTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DelphiTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DtdTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DtdTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FortranTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FortranTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/GroovyTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/GroovyTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HTMLTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HTMLTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HtaccessTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HtaccessTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JSPTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JSPTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaScriptTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaScriptTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JsonTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JsonTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LatexTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LatexTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LispTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LispTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LuaTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LuaTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MakefileTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MakefileTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MxmlTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MxmlTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/NSISTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/NSISTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PHPTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PHPTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PerlTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PerlTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PlainTextTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PlainTextTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PropertiesFileTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PropertiesFileTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PythonTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PythonTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/RubyTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/RubyTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SASTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SASTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SQLTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SQLTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ScalaTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ScalaTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/TclTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/TclTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/UnixShellTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/VisualBasicTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/VisualBasicTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/WindowsBatchTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/XMLTokenMaker.flex create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/XMLTokenMaker.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/AbstractParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/DefaultParseResult.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/DefaultParserNotice.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ExtendedHyperlinkListener.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ParseResult.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/Parser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ParserNotice.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/TaskTagParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ToolTipInfo.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/XmlParser.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/AbstractCodeTemplate.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/CodeTemplate.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/StaticCodeTemplate.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/AbstractGutterComponent.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/BackgroundPainterStrategy.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/BufferedImageBackgroundPainterStrategy.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ChangeableHighlightPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ColorBackgroundPainterStrategy.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ConfigurableCaret.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/FoldIndicator.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/Gutter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/GutterIconInfo.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/IconGroup.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/IconRowHeader.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ImageBackgroundPainterStrategy.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/LineHighlightManager.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/LineNumberList.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/Macro.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RDocument.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RDocumentCharSequence.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTADefaultInputMap.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTATextTransferHandler.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaBase.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaEditorKit.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaHighlighter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaUI.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ar.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_de.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_es.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_fr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_hu.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_in.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_it.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ja.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ko.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_nl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_pl.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_pt_BR.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ru.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_tr.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_zh_CN.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_zh_TW.properties create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextScrollPane.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RUndoManager.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RecordableTextAction.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RegExReplaceInfo.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SearchContext.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SearchEngine.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SearchResult.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SmartHighlightPainter.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ToolTipSupplier.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/VolatileImageBackgroundPainterStrategy.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/package.html create mode 100644 designer_base/src/com/fr/design/gui/syntax/util/DynamicIntArray.java create mode 100644 designer_base/src/com/fr/design/gui/syntax/util/package.html create mode 100644 designer_base/src/com/fr/design/gui/toast/Toast.java create mode 100644 designer_base/src/com/fr/design/hyperlink/AbstractHyperlinkPane.java create mode 100644 designer_base/src/com/fr/design/hyperlink/ReporletHyperNorthPane.java create mode 100644 designer_base/src/com/fr/design/hyperlink/ReportletHyperlinkPane.java create mode 100644 designer_base/src/com/fr/design/hyperlink/WebHyperNorthPane.java create mode 100644 designer_base/src/com/fr/design/hyperlink/WebHyperlinkPane.java create mode 100644 designer_base/src/com/fr/design/icon/BorderIcon.java create mode 100644 designer_base/src/com/fr/design/icon/IconPathConstants.java create mode 100644 designer_base/src/com/fr/design/icon/LockIcon.java create mode 100644 designer_base/src/com/fr/design/icon/WarningIcon.java create mode 100644 designer_base/src/com/fr/design/images/arrow/arrow_down.png create mode 100644 designer_base/src/com/fr/design/images/arrow/arrow_up.png create mode 100644 designer_base/src/com/fr/design/images/browser/360.png create mode 100644 designer_base/src/com/fr/design/images/browser/back.png create mode 100644 designer_base/src/com/fr/design/images/browser/chrome.png create mode 100644 designer_base/src/com/fr/design/images/browser/firefox.png create mode 100644 designer_base/src/com/fr/design/images/browser/forward.png create mode 100644 designer_base/src/com/fr/design/images/browser/go.png create mode 100644 designer_base/src/com/fr/design/images/browser/home.png create mode 100644 designer_base/src/com/fr/design/images/browser/ie.png create mode 100644 designer_base/src/com/fr/design/images/browser/reload.png create mode 100644 designer_base/src/com/fr/design/images/browser/stop.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/add.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/add_over.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/add_press.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/addicon.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/additicon_grey.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/anab24.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/anas.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/arrow.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/arrowdown.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/arrowup.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/bind_ds_column.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/button_0.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/cell.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/cell_group.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/close_icon.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/column.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/cube.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/ds_column.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/ds_column_index.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/ds_column_name.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/dscolumn.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/editn.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/editp.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/hiden.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/hidep.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/history.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/list_cover.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/list_covered.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/list_icon.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/list_normal.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/list_press.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/list_pressed.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/minus.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/more.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/more2.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/more3.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/more4.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/mouseoverclose icon.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/newcpts.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/open.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/pageb24.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/pages.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/parameter.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/plus.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/pressclose icon.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/prevew_down_icon.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/prewidget.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/redo.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/refresh.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/run24.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/runs.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/save.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/select.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/select_item.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/setting.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/switchShortCuts.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_bool.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_cursor.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_date.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_double.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_formula.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_int.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_none.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/type_string.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/undo.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/viewn.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/viewp.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/warn.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/widgets.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/writeb24.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/writes.png create mode 100644 designer_base/src/com/fr/design/images/buttonicon/yes.png create mode 100644 designer_base/src/com/fr/design/images/calculate/average.png create mode 100644 designer_base/src/com/fr/design/images/calculate/count.png create mode 100644 designer_base/src/com/fr/design/images/calculate/max.png create mode 100644 designer_base/src/com/fr/design/images/calculate/min.png create mode 100644 designer_base/src/com/fr/design/images/calculate/none.png create mode 100644 designer_base/src/com/fr/design/images/calculate/sum.png create mode 100644 designer_base/src/com/fr/design/images/calender/month_add.png create mode 100644 designer_base/src/com/fr/design/images/calender/month_add_click.png create mode 100644 designer_base/src/com/fr/design/images/calender/month_add_hover.png create mode 100644 designer_base/src/com/fr/design/images/calender/month_reduce.png create mode 100644 designer_base/src/com/fr/design/images/calender/month_reduce_click.png create mode 100644 designer_base/src/com/fr/design/images/calender/month_reduce_hover.png create mode 100644 designer_base/src/com/fr/design/images/calender/year_add.png create mode 100644 designer_base/src/com/fr/design/images/calender/year_add_click.png create mode 100644 designer_base/src/com/fr/design/images/calender/year_add_hover.png create mode 100644 designer_base/src/com/fr/design/images/calender/year_reduce.png create mode 100644 designer_base/src/com/fr/design/images/calender/year_reduce_click.png create mode 100644 designer_base/src/com/fr/design/images/calender/year_reduce_hover.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/type/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/type/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/type/4.png create mode 100644 designer_base/src/com/fr/design/images/chart/AreaPlot/type/5.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/4.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/5.png create mode 100644 designer_base/src/com/fr/design/images/chart/BarPlot/type/6.png create mode 100644 designer_base/src/com/fr/design/images/chart/BubblePlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/BubblePlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/BubblePlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/BubblePlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/BubblePlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChangeChart.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartAxisLineStyle/cross.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartAxisLineStyle/external.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartAxisLineStyle/inside.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartData.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartLegend/layout_bottom.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartLegend/layout_left.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartLegend/layout_right.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartLegend/layout_top.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartLegend/layout_top_right.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartStyle.png create mode 100644 designer_base/src/com/fr/design/images/chart/ChartType.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/4.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/5.png create mode 100644 designer_base/src/com/fr/design/images/chart/ColumnPlot/type/6.png create mode 100644 designer_base/src/com/fr/design/images/chart/ConditionAttr.png create mode 100644 designer_base/src/com/fr/design/images/chart/CustomPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/CustomPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/CustomPlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/CustomPlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/CustomPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/DonutPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/DonutPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/DonutPlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/DonutPlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/DonutPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/DonutPlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/FunnelPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/GanttPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/GisMapPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/GisMapPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/GisMapPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/InterAttr.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/LinePlot/type/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/MapPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/MapPlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/MapPlot/type/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/MapPlot/type/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/MeterPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/MeterPlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/MeterPlot/type/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/PiePlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/PiePlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/PiePlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/PiePlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/PiePlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/PiePlot/type/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/RadarPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/RangePlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/StockPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/1.png create mode 100644 designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/2.png create mode 100644 designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/3.png create mode 100644 designer_base/src/com/fr/design/images/chart/XYScatterPlot/type/0.png create mode 100644 designer_base/src/com/fr/design/images/chart/default.png create mode 100644 designer_base/src/com/fr/design/images/chart/link.png create mode 100644 designer_base/src/com/fr/design/images/chart/moved.png create mode 100644 designer_base/src/com/fr/design/images/chart/normal.png create mode 100644 designer_base/src/com/fr/design/images/chart/pressed.png create mode 100644 designer_base/src/com/fr/design/images/condition/bracket.png create mode 100644 designer_base/src/com/fr/design/images/condition/unBracket.png create mode 100644 designer_base/src/com/fr/design/images/control/addPopup.png create mode 100644 designer_base/src/com/fr/design/images/control/arrow_down.png create mode 100644 designer_base/src/com/fr/design/images/control/bar.png create mode 100644 designer_base/src/com/fr/design/images/control/barl.png create mode 100644 designer_base/src/com/fr/design/images/control/barm.png create mode 100644 designer_base/src/com/fr/design/images/control/close.png create mode 100644 designer_base/src/com/fr/design/images/control/close_rollover.png create mode 100644 designer_base/src/com/fr/design/images/control/closet.png create mode 100644 designer_base/src/com/fr/design/images/control/control-center2.png create mode 100644 designer_base/src/com/fr/design/images/control/copy.png create mode 100644 designer_base/src/com/fr/design/images/control/dot.png create mode 100644 designer_base/src/com/fr/design/images/control/dotv.png create mode 100644 designer_base/src/com/fr/design/images/control/down.png create mode 100644 designer_base/src/com/fr/design/images/control/downdis.png create mode 100644 designer_base/src/com/fr/design/images/control/downnor.png create mode 100644 designer_base/src/com/fr/design/images/control/downpre.png create mode 100644 designer_base/src/com/fr/design/images/control/edit.png create mode 100644 designer_base/src/com/fr/design/images/control/left.png create mode 100644 designer_base/src/com/fr/design/images/control/leftleft.png create mode 100644 designer_base/src/com/fr/design/images/control/leftnor.png create mode 100644 designer_base/src/com/fr/design/images/control/leftpre.png create mode 100644 designer_base/src/com/fr/design/images/control/lock.png create mode 100644 designer_base/src/com/fr/design/images/control/more.png create mode 100644 designer_base/src/com/fr/design/images/control/refresh.png create mode 100644 designer_base/src/com/fr/design/images/control/remove.png create mode 100644 designer_base/src/com/fr/design/images/control/right.png create mode 100644 designer_base/src/com/fr/design/images/control/rightnor.png create mode 100644 designer_base/src/com/fr/design/images/control/rightpre.png create mode 100644 designer_base/src/com/fr/design/images/control/rightright.png create mode 100644 designer_base/src/com/fr/design/images/control/sortAsc.png create mode 100644 designer_base/src/com/fr/design/images/control/unlock.png create mode 100644 designer_base/src/com/fr/design/images/control/up.png create mode 100644 designer_base/src/com/fr/design/images/control/updis.png create mode 100644 designer_base/src/com/fr/design/images/control/upnor.png create mode 100644 designer_base/src/com/fr/design/images/control/uppre.png create mode 100644 designer_base/src/com/fr/design/images/control/warn.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/baobiaozhuti.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/baobiaozhuti_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/baobiaozhuti_hover.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/canshujiemian.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/canshujiemian_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/canshujiemian_hover.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/edit.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/edit_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/edit_hover.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/form.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/form_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/form_hover.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/left.gif create mode 100644 designer_base/src/com/fr/design/images/custombtn/page.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/page_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/page_hover.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/preview.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/preview_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/preview_hover.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/right.gif create mode 100644 designer_base/src/com/fr/design/images/custombtn/setting.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/setting_click.png create mode 100644 designer_base/src/com/fr/design/images/custombtn/setting_hover.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/chart.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/files.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/form.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/guide.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/0.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/1.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/1.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/10.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/10.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/11.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/11.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/12.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/12.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/13.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/13.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/14.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/14.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/15.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/15.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/16.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/16.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/17.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/17.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/18.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/18.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/19.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/19.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/2.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/2.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/20.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/21.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/22.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/23.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/24.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/25.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/26.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/27.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/28.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/29.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/3.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/3.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/30.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/31.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/32.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/33.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/34.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/35.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/36.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/37.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/38.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/39.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/4.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/4.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/40.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/41.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/42.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/43.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/44.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/45.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/46.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/47.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/48.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/49.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/5.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/5.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/50.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/52.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/54.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/55.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/56.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/57.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/6.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/6.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/7.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/7.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/8.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/8.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/9.gif create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/9.png create mode 100644 designer_base/src/com/fr/design/images/dashboard/img/Thumbs.db create mode 100644 designer_base/src/com/fr/design/images/data/arrow_branch.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/add.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/distanceconnect.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/groupAscColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/groupColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/groupDescColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/localconnect.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/modify.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/normalColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/selectColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/sortAscColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/sortColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/sortDescColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/bind/summaryColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/comb_widget.png create mode 100644 designer_base/src/com/fr/design/images/data/convertEmbedded.png create mode 100644 designer_base/src/com/fr/design/images/data/cube.png create mode 100644 designer_base/src/com/fr/design/images/data/custom_widget.png create mode 100644 designer_base/src/com/fr/design/images/data/dataDictionary.png create mode 100644 designer_base/src/com/fr/design/images/data/dataTable.png create mode 100644 designer_base/src/com/fr/design/images/data/database.png create mode 100644 designer_base/src/com/fr/design/images/data/datakubiao.png create mode 100644 designer_base/src/com/fr/design/images/data/datasource.png create mode 100644 designer_base/src/com/fr/design/images/data/default_widget.png create mode 100644 designer_base/src/com/fr/design/images/data/diy.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/XML.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/classTableData.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/dataTable.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/database.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/excel.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/relation_table_data.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/serverclasstabledata.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/serverdatabase.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/serverdatatable.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/table_proc.png create mode 100644 designer_base/src/com/fr/design/images/data/dock/table_text.png create mode 100644 designer_base/src/com/fr/design/images/data/editQuery.png create mode 100644 designer_base/src/com/fr/design/images/data/field.png create mode 100644 designer_base/src/com/fr/design/images/data/file.png create mode 100644 designer_base/src/com/fr/design/images/data/multi.png create mode 100644 designer_base/src/com/fr/design/images/data/newQuery.png create mode 100644 designer_base/src/com/fr/design/images/data/private.png create mode 100644 designer_base/src/com/fr/design/images/data/public.png create mode 100644 designer_base/src/com/fr/design/images/data/sap.png create mode 100644 designer_base/src/com/fr/design/images/data/search.png create mode 100644 designer_base/src/com/fr/design/images/data/source/classTableData.png create mode 100644 designer_base/src/com/fr/design/images/data/source/clear.png create mode 100644 designer_base/src/com/fr/design/images/data/source/dataDictionary.png create mode 100644 designer_base/src/com/fr/design/images/data/source/delete.png create mode 100644 designer_base/src/com/fr/design/images/data/source/hibernateTableData.png create mode 100644 designer_base/src/com/fr/design/images/data/source/jdbcDataquery.png create mode 100644 designer_base/src/com/fr/design/images/data/source/jdbcTableData.png create mode 100644 designer_base/src/com/fr/design/images/data/source/moveDown.png create mode 100644 designer_base/src/com/fr/design/images/data/source/moveUp.png create mode 100644 designer_base/src/com/fr/design/images/data/source/newDatabase.png create mode 100644 designer_base/src/com/fr/design/images/data/source/newDatasource.png create mode 100644 designer_base/src/com/fr/design/images/data/source/rename.png create mode 100644 designer_base/src/com/fr/design/images/data/source/schema.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/Thumbs.db create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/accept.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/bullet_key.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/bullet_pink.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/cart_add.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/cart_delete.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/chart_organisation.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database_connect.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database_gear.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database_lightning.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database_save.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database_table.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/database_tables.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/filter.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/folder_database.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/folder_page.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/folder_table.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/page_edit.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/page_gear.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/page_save.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/page_white_database.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_error.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_gear.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_link.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_multiple.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_relationship.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_row_delete.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_row_insert.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/table_sort.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/textfield.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/wizard.png create mode 100644 designer_base/src/com/fr/design/images/data/source/selectwizard/wrench.png create mode 100644 designer_base/src/com/fr/design/images/data/source/sqlAscColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/source/sqlColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/source/sqlConditionColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/source/sqlDescColumn.png create mode 100644 designer_base/src/com/fr/design/images/data/source/sqlTable.png create mode 100644 designer_base/src/com/fr/design/images/data/source/sqlViewTable.png create mode 100644 designer_base/src/com/fr/design/images/data/source/table.png create mode 100644 designer_base/src/com/fr/design/images/data/source/textDatasource.png create mode 100644 designer_base/src/com/fr/design/images/data/source/view.png create mode 100644 designer_base/src/com/fr/design/images/data/store_procedure.png create mode 100644 designer_base/src/com/fr/design/images/data/string.png create mode 100644 designer_base/src/com/fr/design/images/data/table.png create mode 100644 designer_base/src/com/fr/design/images/data/table2.png create mode 100644 designer_base/src/com/fr/design/images/data/tables.png create mode 100644 designer_base/src/com/fr/design/images/data/text.png create mode 100644 designer_base/src/com/fr/design/images/data/today.gif create mode 100644 designer_base/src/com/fr/design/images/data/tree.png create mode 100644 designer_base/src/com/fr/design/images/data/user_widget.png create mode 100644 designer_base/src/com/fr/design/images/data/views.png create mode 100644 designer_base/src/com/fr/design/images/data/xml.png create mode 100644 designer_base/src/com/fr/design/images/dialog/column.png create mode 100644 designer_base/src/com/fr/design/images/dialog/function.gif create mode 100644 designer_base/src/com/fr/design/images/dialog/parameter.gif create mode 100644 designer_base/src/com/fr/design/images/dialog/table.png create mode 100644 designer_base/src/com/fr/design/images/dialog/variable.png create mode 100644 designer_base/src/com/fr/design/images/dock/desktop.png create mode 100644 designer_base/src/com/fr/design/images/dock/project.png create mode 100644 designer_base/src/com/fr/design/images/dock/projectVer.png create mode 100644 designer_base/src/com/fr/design/images/dock/properties.png create mode 100644 designer_base/src/com/fr/design/images/docking/close.gif create mode 100644 designer_base/src/com/fr/design/images/docking/down.gif create mode 100644 designer_base/src/com/fr/design/images/docking/left.gif create mode 100644 designer_base/src/com/fr/design/images/docking/left.png create mode 100644 designer_base/src/com/fr/design/images/docking/right.gif create mode 100644 designer_base/src/com/fr/design/images/docking/right.png create mode 100644 designer_base/src/com/fr/design/images/docking/up.gif create mode 100644 designer_base/src/com/fr/design/images/edit/deleteRow.png create mode 100644 designer_base/src/com/fr/design/images/edit/insertRow_B.png create mode 100644 designer_base/src/com/fr/design/images/expand/asc.png create mode 100644 designer_base/src/com/fr/design/images/expand/cellAttr.gif create mode 100644 designer_base/src/com/fr/design/images/expand/des.png create mode 100644 designer_base/src/com/fr/design/images/expand/landspace.png create mode 100644 designer_base/src/com/fr/design/images/expand/none16x16.png create mode 100644 designer_base/src/com/fr/design/images/expand/vertical.png create mode 100644 designer_base/src/com/fr/design/images/file/disk.gif create mode 100644 designer_base/src/com/fr/design/images/file/disk.png create mode 100644 designer_base/src/com/fr/design/images/file/fold.png create mode 100644 designer_base/src/com/fr/design/images/file/folder.gif create mode 100644 designer_base/src/com/fr/design/images/file/gifFile.gif create mode 100644 designer_base/src/com/fr/design/images/file/jpgFile.gif create mode 100644 designer_base/src/com/fr/design/images/file/newfolder.png create mode 100644 designer_base/src/com/fr/design/images/file/nostar.png create mode 100644 designer_base/src/com/fr/design/images/file/pngFile.png create mode 100644 designer_base/src/com/fr/design/images/file/star.png create mode 100644 designer_base/src/com/fr/design/images/form/Button.gif create mode 100644 designer_base/src/com/fr/design/images/form/CheckBox.gif create mode 100644 designer_base/src/com/fr/design/images/form/Choice.gif create mode 100644 designer_base/src/com/fr/design/images/form/List.gif create mode 100644 designer_base/src/com/fr/design/images/form/RadioButton.gif create mode 100644 designer_base/src/com/fr/design/images/form/TextField.gif create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_border.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_border_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_left.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_left_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_right.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_right_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_close.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_close_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_max.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_max_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_min.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_min_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/controls.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/controls_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/left_border.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/left_border_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/right_border.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/right_border_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/title_pane.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_border.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_border_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_left.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_left_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_right.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_right_.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/bottom_align.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/center_align.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/cursor/add.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/cursor/connectorcursor.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/cursor/move.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/drop_down.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/drop_over.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/drop_up.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/holder.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/left_align.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/middle_align.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/properties/minus.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/properties/plus.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/right_align.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/same_height.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/same_width.png create mode 100644 designer_base/src/com/fr/design/images/form/designer/top_align.png create mode 100644 designer_base/src/com/fr/design/images/form/hover.png create mode 100644 designer_base/src/com/fr/design/images/form/parameter.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/Chart-Map.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Area.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Bar.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Column.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Comb_Chart.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Donut.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Funnel.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Gantt.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Gis.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Line.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Meter.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Pie.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Radar.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Range_Chart.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-Stock.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ChartF-XYScatter.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/Chart_BubbleChart.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/FR-Chart-Chart_BubbleChart.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/default.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ec_columns.png create mode 100644 designer_base/src/com/fr/design/images/form/toolbar/ec_frozen.png create mode 100644 designer_base/src/com/fr/design/images/gc.png create mode 100644 designer_base/src/com/fr/design/images/general/close-rolver.png create mode 100644 designer_base/src/com/fr/design/images/general/close.png create mode 100644 designer_base/src/com/fr/design/images/general/mini-rolver.png create mode 100644 designer_base/src/com/fr/design/images/general/mini.png create mode 100644 designer_base/src/com/fr/design/images/general/resize-rolver.png create mode 100644 designer_base/src/com/fr/design/images/general/resize.png create mode 100644 designer_base/src/com/fr/design/images/gui/blank.gif create mode 100644 designer_base/src/com/fr/design/images/gui/bmpFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/cell.gif create mode 100644 designer_base/src/com/fr/design/images/gui/cht.png create mode 100644 designer_base/src/com/fr/design/images/gui/chtlocked.png create mode 100644 designer_base/src/com/fr/design/images/gui/classFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/close.png create mode 100644 designer_base/src/com/fr/design/images/gui/color/background.png create mode 100644 designer_base/src/com/fr/design/images/gui/color/foreground.png create mode 100644 designer_base/src/com/fr/design/images/gui/cptFile.png create mode 100644 designer_base/src/com/fr/design/images/gui/documentFolderClose.gif create mode 100644 designer_base/src/com/fr/design/images/gui/folder.gif create mode 100644 designer_base/src/com/fr/design/images/gui/folder.png create mode 100644 designer_base/src/com/fr/design/images/gui/folder/expanded.png create mode 100644 designer_base/src/com/fr/design/images/gui/folder/foldered.png create mode 100644 designer_base/src/com/fr/design/images/gui/folder/hovered_expanded.png create mode 100644 designer_base/src/com/fr/design/images/gui/folder/hovered_foldered.png create mode 100644 designer_base/src/com/fr/design/images/gui/frm.png create mode 100644 designer_base/src/com/fr/design/images/gui/frmlocked.png create mode 100644 designer_base/src/com/fr/design/images/gui/gifFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/htmlFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/jarFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/javaFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/jpgFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/jsFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/jspFile.gif create mode 100644 designer_base/src/com/fr/design/images/gui/locked.gif create mode 100644 designer_base/src/com/fr/design/images/gui/minimize.gif create mode 100644 designer_base/src/com/fr/design/images/gui/pngFile.png create mode 100644 designer_base/src/com/fr/design/images/gui/popup.gif create mode 100644 designer_base/src/com/fr/design/images/gui/popupCenter.png create mode 100644 designer_base/src/com/fr/design/images/gui/popupLarge.gif create mode 100644 designer_base/src/com/fr/design/images/gui/tab_add_click.png create mode 100644 designer_base/src/com/fr/design/images/gui/tab_add_hover.png create mode 100644 designer_base/src/com/fr/design/images/gui/tab_add_normal.png create mode 100644 designer_base/src/com/fr/design/images/gui/tab_delete.png create mode 100644 designer_base/src/com/fr/design/images/gui/textFile.png create mode 100644 designer_base/src/com/fr/design/images/gui/warning.png create mode 100644 designer_base/src/com/fr/design/images/gui/xmlFile.gif create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon0.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon1.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon10.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon11.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon12.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon13.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon14.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon2.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon3.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon4.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon5.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon6.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon7.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon8.png create mode 100755 designer_base/src/com/fr/design/images/load/busy-icon9.png create mode 100644 designer_base/src/com/fr/design/images/log/clear.png create mode 100644 designer_base/src/com/fr/design/images/log/selectedall.png create mode 100644 designer_base/src/com/fr/design/images/log/setting.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/ComboBoxFocus.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/ComputerIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/DirectoryIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/ErrorIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/FileDetailsIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/FileIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/FileListIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/FloppyIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/HarddiskIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/HomeFolderIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/InformationIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/InternalFrameIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/NewFolderIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/ParentDirectoryIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/QuestionIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/TreeFolderClosedIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/TreeFolderOpenedIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/TreeLeafIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/TreeMinusIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/TreePlusIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/WarningIcon.png create mode 100644 designer_base/src/com/fr/design/images/lookandfeel/brightmask.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/bringForward.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/bringToFront.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/copy.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/cut.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/directShare.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/formatBrush.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/merge.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/modifyShare.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/paste.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/pluralundo.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/redo.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/sendBackward.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/sendToBack.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/share.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/undo.png create mode 100644 designer_base/src/com/fr/design/images/m_edit/unmerge.png create mode 100644 designer_base/src/com/fr/design/images/m_file/close.png create mode 100644 designer_base/src/com/fr/design/images/m_file/crossTable.png create mode 100644 designer_base/src/com/fr/design/images/m_file/csv.png create mode 100644 designer_base/src/com/fr/design/images/m_file/design.png create mode 100644 designer_base/src/com/fr/design/images/m_file/design_large.png create mode 100644 designer_base/src/com/fr/design/images/m_file/edit.png create mode 100644 designer_base/src/com/fr/design/images/m_file/excel.png create mode 100644 designer_base/src/com/fr/design/images/m_file/export.png create mode 100644 designer_base/src/com/fr/design/images/m_file/formExport.png create mode 100644 designer_base/src/com/fr/design/images/m_file/groupTable.png create mode 100644 designer_base/src/com/fr/design/images/m_file/help.png create mode 100644 designer_base/src/com/fr/design/images/m_file/html.png create mode 100644 designer_base/src/com/fr/design/images/m_file/hyperLink.png create mode 100644 designer_base/src/com/fr/design/images/m_file/import.png create mode 100644 designer_base/src/com/fr/design/images/m_file/merge.png create mode 100644 designer_base/src/com/fr/design/images/m_file/new.png create mode 100644 designer_base/src/com/fr/design/images/m_file/open.png create mode 100644 designer_base/src/com/fr/design/images/m_file/pageSetup.png create mode 100644 designer_base/src/com/fr/design/images/m_file/pdf.png create mode 100644 designer_base/src/com/fr/design/images/m_file/preview.png create mode 100644 designer_base/src/com/fr/design/images/m_file/print.png create mode 100644 designer_base/src/com/fr/design/images/m_file/save.png create mode 100644 designer_base/src/com/fr/design/images/m_file/saveAs.png create mode 100644 designer_base/src/com/fr/design/images/m_file/svg.png create mode 100644 designer_base/src/com/fr/design/images/m_file/switch.png create mode 100644 designer_base/src/com/fr/design/images/m_file/text.png create mode 100644 designer_base/src/com/fr/design/images/m_file/view_folder.png create mode 100644 designer_base/src/com/fr/design/images/m_file/web.png create mode 100644 designer_base/src/com/fr/design/images/m_file/word.png create mode 100644 designer_base/src/com/fr/design/images/m_format/allborders.png create mode 100644 designer_base/src/com/fr/design/images/m_format/border.png create mode 100644 designer_base/src/com/fr/design/images/m_format/bottom.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cell.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellWriteAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/bold.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/centerAlignment.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/default.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/defaultAlignment.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/generalAlignment.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_center_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_center_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_left_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_left_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_right_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_right_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_s_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/h_s_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/italic.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/leftAlignment.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/otherset.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/rightAlignment.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/shadow.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/strikethrough.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/sub.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/sup.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/underline.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/v_center_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/v_center_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/v_down_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/v_down_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/v_top_normal.png create mode 100644 designer_base/src/com/fr/design/images/m_format/cellstyle/v_top_pressed.png create mode 100644 designer_base/src/com/fr/design/images/m_format/doublebottom.png create mode 100644 designer_base/src/com/fr/design/images/m_format/editChart.png create mode 100644 designer_base/src/com/fr/design/images/m_format/highlight.png create mode 100644 designer_base/src/com/fr/design/images/m_format/in.png create mode 100644 designer_base/src/com/fr/design/images/m_format/left.png create mode 100644 designer_base/src/com/fr/design/images/m_format/modified.png create mode 100644 designer_base/src/com/fr/design/images/m_format/noboder.png create mode 100644 designer_base/src/com/fr/design/images/m_format/note.png create mode 100644 designer_base/src/com/fr/design/images/m_format/out.png create mode 100644 designer_base/src/com/fr/design/images/m_format/outsideborders.png create mode 100644 designer_base/src/com/fr/design/images/m_format/right.png create mode 100644 designer_base/src/com/fr/design/images/m_format/shape.png create mode 100644 designer_base/src/com/fr/design/images/m_format/thickbottom.png create mode 100644 designer_base/src/com/fr/design/images/m_format/thickoutsideborders.png create mode 100644 designer_base/src/com/fr/design/images/m_format/topanddoublebotttom.png create mode 100644 designer_base/src/com/fr/design/images/m_format/topandthickbottom.png create mode 100644 designer_base/src/com/fr/design/images/m_format/topbottom.png create mode 100644 designer_base/src/com/fr/design/images/m_help/back.png create mode 100644 designer_base/src/com/fr/design/images/m_help/demo.png create mode 100644 designer_base/src/com/fr/design/images/m_help/feedback.png create mode 100644 designer_base/src/com/fr/design/images/m_help/forum.png create mode 100644 designer_base/src/com/fr/design/images/m_help/forward.png create mode 100644 designer_base/src/com/fr/design/images/m_help/help.png create mode 100644 designer_base/src/com/fr/design/images/m_help/preview_analy.png create mode 100644 designer_base/src/com/fr/design/images/m_help/preview_form.png create mode 100644 designer_base/src/com/fr/design/images/m_help/preview_page.png create mode 100644 designer_base/src/com/fr/design/images/m_help/preview_write.png create mode 100644 designer_base/src/com/fr/design/images/m_help/product_forum.png create mode 100644 designer_base/src/com/fr/design/images/m_help/support_qq.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/Pivottable.gif create mode 100644 designer_base/src/com/fr/design/images/m_insert/account.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/accountTitle.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/barcode.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/bias.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/bindCell.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/bindColumn.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/blank.gif create mode 100644 designer_base/src/com/fr/design/images/m_insert/boolean.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/cell.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/cellPop.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/chart.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/composite.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/compositePop.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/crossTable.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/date.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/default.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/expandCell.gif create mode 100644 designer_base/src/com/fr/design/images/m_insert/float.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/floatPop.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/formula.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/groupTable.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/hyperLink.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/image.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/insertColumn.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/insertRow.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/newchart.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/richtext.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/shape.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/shape_issosceles_triangle.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/shape_line.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/shape_oval.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/shape_rectangle.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/shape_rounded_rectangle.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/subReport.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/text.png create mode 100644 designer_base/src/com/fr/design/images/m_insert/textBox.png create mode 100644 designer_base/src/com/fr/design/images/m_report/allow_authority_edit.png create mode 100644 designer_base/src/com/fr/design/images/m_report/attributes.png create mode 100644 designer_base/src/com/fr/design/images/m_report/background.png create mode 100644 designer_base/src/com/fr/design/images/m_report/bindData.png create mode 100644 designer_base/src/com/fr/design/images/m_report/close.png create mode 100644 designer_base/src/com/fr/design/images/m_report/close_over.png create mode 100644 designer_base/src/com/fr/design/images/m_report/close_press.png create mode 100644 designer_base/src/com/fr/design/images/m_report/delete.png create mode 100644 designer_base/src/com/fr/design/images/m_report/deleteColumn.png create mode 100644 designer_base/src/com/fr/design/images/m_report/deleteRow.png create mode 100644 designer_base/src/com/fr/design/images/m_report/exit_authority_edit.png create mode 100644 designer_base/src/com/fr/design/images/m_report/exportAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_report/footer.png create mode 100644 designer_base/src/com/fr/design/images/m_report/header.png create mode 100644 designer_base/src/com/fr/design/images/m_report/linearAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_report/p.gif create mode 100644 designer_base/src/com/fr/design/images/m_report/p.png create mode 100644 designer_base/src/com/fr/design/images/m_report/parameter.png create mode 100644 designer_base/src/com/fr/design/images/m_report/process.gif create mode 100644 designer_base/src/com/fr/design/images/m_report/qb.png create mode 100644 designer_base/src/com/fr/design/images/m_report/reportEngineAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_report/reportWorkFlowAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_report/reportWriteAttr.png create mode 100644 designer_base/src/com/fr/design/images/m_report/tree.png create mode 100644 designer_base/src/com/fr/design/images/m_report/webreportattribute.png create mode 100644 designer_base/src/com/fr/design/images/m_web/cache.png create mode 100644 designer_base/src/com/fr/design/images/m_web/connection.png create mode 100644 designer_base/src/com/fr/design/images/m_web/datasource.png create mode 100644 designer_base/src/com/fr/design/images/m_web/edit.png create mode 100644 designer_base/src/com/fr/design/images/m_web/face.gif create mode 100644 designer_base/src/com/fr/design/images/m_web/formula.png create mode 100644 designer_base/src/com/fr/design/images/m_web/function.png create mode 100644 designer_base/src/com/fr/design/images/m_web/log.png create mode 100644 designer_base/src/com/fr/design/images/m_web/privilegeManager.gif create mode 100644 designer_base/src/com/fr/design/images/m_web/reportletdemo.png create mode 100644 designer_base/src/com/fr/design/images/m_web/schedule.png create mode 100644 designer_base/src/com/fr/design/images/m_web/server.png create mode 100644 designer_base/src/com/fr/design/images/m_web/style.png create mode 100644 designer_base/src/com/fr/design/images/m_web/sync.png create mode 100644 designer_base/src/com/fr/design/images/m_window/cascade.png create mode 100644 designer_base/src/com/fr/design/images/m_window/formdesign.png create mode 100644 designer_base/src/com/fr/design/images/m_window/frozen.png create mode 100644 designer_base/src/com/fr/design/images/m_window/generaldesign.png create mode 100644 designer_base/src/com/fr/design/images/m_window/next.png create mode 100644 designer_base/src/com/fr/design/images/m_window/previous.png create mode 100644 designer_base/src/com/fr/design/images/m_window/title_hor.png create mode 100644 designer_base/src/com/fr/design/images/m_window/title_ver.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/attribute.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/class.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/datasource.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/fpt.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/jar.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/java.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/server.png create mode 100644 designer_base/src/com/fr/design/images/mainframe/xml.png create mode 100644 designer_base/src/com/fr/design/images/minimize.gif create mode 100644 designer_base/src/com/fr/design/images/parameter.png create mode 100644 designer_base/src/com/fr/design/images/poly/Chart-Map/Chart-Map-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-4.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-5.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-4.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-5.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-6.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-4.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-5.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-6.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Comb_Chart/ChartF-Comb_Chart-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Comb_Chart/ChartF-Comb_Chart-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Donut/ChartF-Donut-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Donut/ChartF-Donut-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Gis/ChartF-Gis-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-4.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-5.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Meter/ChartF-Meter-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Meter/ChartF-Meter-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-4.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-5.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Range_Chart/ChartF-Range_Chart-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-3.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-XYScatter/ChartF-XYScatter-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-XYScatter/ChartF-XYScatter-1.png create mode 100644 designer_base/src/com/fr/design/images/poly/ChartF-XYScatter/ChartF-XYScatter-2.png create mode 100644 designer_base/src/com/fr/design/images/poly/Chart_BubbleChart/Chart_BubbleChart-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/Chart_BubbleChart/FR-Chart-Chart_BubbleChart-0.png create mode 100644 designer_base/src/com/fr/design/images/poly/normal.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Chart-Map.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Chart-SVG_MAP.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Area.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Bar.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Column.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Comb_Chart.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Donut.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Funnel.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Gantt.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Gis.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Line.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Meter.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Pie.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Radar.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Range_Chart.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Stock.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/ChartF-XYScatter.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Chart_BubbleChart.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart-Bit_Map.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart-Chart_BubbleChart.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart-ThreeD_Custom_Chart.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart_Bit_Map.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewArea.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewBar.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewColumn.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewLine.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewPie.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_VerticalLine.png create mode 100644 designer_base/src/com/fr/design/images/poly/toolbar/Poly-Report_Block.png create mode 100644 designer_base/src/com/fr/design/images/report/form.png create mode 100644 designer_base/src/com/fr/design/images/report/groupReport.png create mode 100644 designer_base/src/com/fr/design/images/report/position.png create mode 100644 designer_base/src/com/fr/design/images/reportcolumns/col.png create mode 100644 designer_base/src/com/fr/design/images/reportcolumns/row.png create mode 100644 designer_base/src/com/fr/design/images/server/change.png create mode 100644 designer_base/src/com/fr/design/images/server/manage.png create mode 100644 designer_base/src/com/fr/design/images/server/plugin.png create mode 100644 designer_base/src/com/fr/design/images/server/printerconf.png create mode 100644 designer_base/src/com/fr/design/images/server/start.png create mode 100644 designer_base/src/com/fr/design/images/server/stop.png create mode 100644 designer_base/src/com/fr/design/images/server/view.png create mode 100644 designer_base/src/com/fr/design/images/serverM/fs.png create mode 100644 designer_base/src/com/fr/design/images/serverM/org.png create mode 100644 designer_base/src/com/fr/design/images/serverM/organization.png create mode 100644 designer_base/src/com/fr/design/images/serverM/role.png create mode 100644 designer_base/src/com/fr/design/images/serverM/roleAdd.png create mode 100644 designer_base/src/com/fr/design/images/serverM/roleRemove.png create mode 100644 designer_base/src/com/fr/design/images/serverM/rtr.png create mode 100644 designer_base/src/com/fr/design/images/serverM/use.png create mode 100644 designer_base/src/com/fr/design/images/serverM/user.png create mode 100644 designer_base/src/com/fr/design/images/sheet/addpolysheet.png create mode 100644 designer_base/src/com/fr/design/images/sheet/left_right_btn.png create mode 100644 designer_base/src/com/fr/design/images/sheet/polysheet.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/chart.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/chartChangeClose.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/close.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/close_tags.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/closehover.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/connector.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/down.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/parameter-hover.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/parametersetting.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/pop.gif create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/setting.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/toolbarbtnclear.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/toolbarbtnsetting.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/up.png create mode 100644 designer_base/src/com/fr/design/images/toolbarbtn/xiala.png create mode 100644 designer_base/src/com/fr/design/images/tree/close.png create mode 100644 designer_base/src/com/fr/design/images/tree/open.png create mode 100644 designer_base/src/com/fr/design/images/wait.gif create mode 100644 designer_base/src/com/fr/design/images/warnings/warning 2.png create mode 100644 designer_base/src/com/fr/design/images/warnings/warning.png create mode 100644 designer_base/src/com/fr/design/images/warnings/warning3.png create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/$$$.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/$$page_number.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/$$totalPage_number.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/$fr_authority.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/$fr_username.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/$fr_userposition.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/NOFILTER.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/NULL.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/contextPath.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/curReport.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/fr_submitinfo.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/reportName.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/serverName.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/serverPort.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/serverSchema.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/serverURL.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/servletURL.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/cn/sessionID.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/$$$.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/$$page_number.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/$$totalPage_number.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/$fr_authority.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/$fr_username.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/$fr_userposition.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/NOFILTER.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/NULL.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/contextPath.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/curReport.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/fr_submitinfo.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/reportName.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/serverName.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/serverPort.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/serverSchema.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/serverURL.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/servletURL.txt create mode 100644 designer_base/src/com/fr/design/insert/formula/variable/en/sessionID.txt create mode 100644 designer_base/src/com/fr/design/javascript/Commit2DBJavaScriptPane.java create mode 100644 designer_base/src/com/fr/design/javascript/CustomActionPane.java create mode 100644 designer_base/src/com/fr/design/javascript/EmailPane.java create mode 100644 designer_base/src/com/fr/design/javascript/FormSubmitJavaScriptPane.java create mode 100644 designer_base/src/com/fr/design/javascript/JSContentPane.java create mode 100644 designer_base/src/com/fr/design/javascript/JavaScriptActionPane.java create mode 100644 designer_base/src/com/fr/design/javascript/JavaScriptImplPane.java create mode 100644 designer_base/src/com/fr/design/javascript/ParameterJavaScriptPane.java create mode 100644 designer_base/src/com/fr/design/javascript/ProcessJSImplPane.java create mode 100644 designer_base/src/com/fr/design/javascript/ProcessParameterTableModel.java create mode 100644 designer_base/src/com/fr/design/javascript/ProcessTransitionAdapter.java create mode 100644 designer_base/src/com/fr/design/layout/FRGUIPaneFactory.java create mode 100644 designer_base/src/com/fr/design/layout/FRGridLayout.java create mode 100644 designer_base/src/com/fr/design/layout/FRLeftFlowLayout.java create mode 100644 designer_base/src/com/fr/design/layout/LeftCenterRightLayout.java create mode 100644 designer_base/src/com/fr/design/layout/TableLayout.java create mode 100644 designer_base/src/com/fr/design/layout/TableLayoutConstraints.java create mode 100644 designer_base/src/com/fr/design/layout/TableLayoutHelper.java create mode 100644 designer_base/src/com/fr/design/layout/TableLayoutTest.java create mode 100644 designer_base/src/com/fr/design/layout/VerticalFlowLayout.java create mode 100644 designer_base/src/com/fr/design/mainframe/AbstractAppProvider.java create mode 100644 designer_base/src/com/fr/design/mainframe/App.java create mode 100644 designer_base/src/com/fr/design/mainframe/AuthorityEditPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/AuthorityPropertyPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/BaseFormDesigner.java create mode 100644 designer_base/src/com/fr/design/mainframe/BaseJForm.java create mode 100644 designer_base/src/com/fr/design/mainframe/BaseUndoState.java create mode 100644 designer_base/src/com/fr/design/mainframe/BaseWidgetPropertyPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/DecodeDialog.java create mode 100644 designer_base/src/com/fr/design/mainframe/DesignerBean.java create mode 100644 designer_base/src/com/fr/design/mainframe/DesignerContext.java create mode 100644 designer_base/src/com/fr/design/mainframe/DesignerFrame.java create mode 100644 designer_base/src/com/fr/design/mainframe/DesignerFrameFileDealerPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/DesktopCardPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/DockingView.java create mode 100644 designer_base/src/com/fr/design/mainframe/DottedLine.java create mode 100644 designer_base/src/com/fr/design/mainframe/EastRegionContainerPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/FormScrollBar.java create mode 100644 designer_base/src/com/fr/design/mainframe/JTemplate.java create mode 100644 designer_base/src/com/fr/design/mainframe/JTemplateActionListener.java create mode 100644 designer_base/src/com/fr/design/mainframe/JTemplateProvider.java create mode 100644 designer_base/src/com/fr/design/mainframe/JViewContainer.java create mode 100644 designer_base/src/com/fr/design/mainframe/NoSupportAuthorityEdit.java create mode 100644 designer_base/src/com/fr/design/mainframe/TemplatePane.java create mode 100644 designer_base/src/com/fr/design/mainframe/UndoStateEdit.java create mode 100644 designer_base/src/com/fr/design/mainframe/WestRegionContainerPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/BackgroundSettingPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/ColorBackgroundPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/ImageBackgroundPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/ImagePreviewPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/NullBackgroundPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/PatternBackgroundPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/backgroundpane/TextureBackgroundPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/dnd/ArrayListTransferHandler.java create mode 100644 designer_base/src/com/fr/design/mainframe/dnd/ArrayListTransferable.java create mode 100644 designer_base/src/com/fr/design/mainframe/dnd/ArrayTransferable.java create mode 100644 designer_base/src/com/fr/design/mainframe/dnd/SerializableTransferable.java create mode 100644 designer_base/src/com/fr/design/mainframe/form/FormECCompositeProvider.java create mode 100644 designer_base/src/com/fr/design/mainframe/form/FormECDesignerProvider.java create mode 100644 designer_base/src/com/fr/design/mainframe/hold/DefaultTitlePlace.java create mode 100644 designer_base/src/com/fr/design/mainframe/loghandler/DesignerLogHandler.java create mode 100644 designer_base/src/com/fr/design/mainframe/loghandler/DesignerLogImpl.java create mode 100644 designer_base/src/com/fr/design/mainframe/loghandler/LogDetailPane.java create mode 100644 designer_base/src/com/fr/design/mainframe/loghandler/LogHandlerBar.java create mode 100644 designer_base/src/com/fr/design/mainframe/loghandler/LogHandlerBarUI.java create mode 100644 designer_base/src/com/fr/design/mainframe/loghandler/LogMessageBar.java create mode 100644 designer_base/src/com/fr/design/mainframe/toolbar/AuthorityEditToolBarComponent.java create mode 100644 designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java create mode 100644 designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/AbstractPropertyEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/DataBindingEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/DataTableEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/ExtendedPropertyEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/FormattedEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/IntegerPropertyEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/PropertyCellEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/ServerDataBindingEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/ServerDataTableEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/StringEditor.java create mode 100644 designer_base/src/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java create mode 100644 designer_base/src/com/fr/design/menu/DottedSeparator.java create mode 100644 designer_base/src/com/fr/design/menu/DottedSeparatorUI.java create mode 100644 designer_base/src/com/fr/design/menu/KeySetUtils.java create mode 100644 designer_base/src/com/fr/design/menu/LineSeparator.java create mode 100644 designer_base/src/com/fr/design/menu/MenuDef.java create mode 100644 designer_base/src/com/fr/design/menu/MenuKeySet.java create mode 100644 designer_base/src/com/fr/design/menu/MenuManager.java create mode 100644 designer_base/src/com/fr/design/menu/NameSeparator.java create mode 100644 designer_base/src/com/fr/design/menu/SeparatorDef.java create mode 100644 designer_base/src/com/fr/design/menu/ShortCut.java create mode 100644 designer_base/src/com/fr/design/menu/ToolBarDef.java create mode 100644 designer_base/src/com/fr/design/menu/TwoDottedSeparatorUI.java create mode 100644 designer_base/src/com/fr/design/menu/UISeparatorUI.java create mode 100644 designer_base/src/com/fr/design/module/DesignModule.java create mode 100644 designer_base/src/com/fr/design/module/DesignModuleFactory.java create mode 100644 designer_base/src/com/fr/design/object/NameObject.java create mode 100644 designer_base/src/com/fr/design/parameter/AbstractParameterReader.java create mode 100644 designer_base/src/com/fr/design/parameter/HierarchyTreePane.java create mode 100644 designer_base/src/com/fr/design/parameter/ParaDefinitePane.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterArrayPane.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterBridge.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterGroup.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterInputPane.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterManagerPane.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterPane.java create mode 100644 designer_base/src/com/fr/design/parameter/ParameterReader.java create mode 100644 designer_base/src/com/fr/design/present/DictPresentPane.java create mode 100644 designer_base/src/com/fr/design/present/FormulaPresentPane.java create mode 100644 designer_base/src/com/fr/design/present/NonePresentPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/AbstractDicPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/CustomDictCorrelationPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/CustomDictPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/DatabaseDictPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/DictionaryPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/FormulaDictPane.java create mode 100644 designer_base/src/com/fr/design/present/dict/TableDataDictPane.java create mode 100644 designer_base/src/com/fr/design/preview/PagePreview.java create mode 100644 designer_base/src/com/fr/design/preview/ViewPreview.java create mode 100644 designer_base/src/com/fr/design/preview/WritePreview.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/ReportAndFSManagePane.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/RoleDataWrapper.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/RoleSourceOP.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/RoleTree.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/RolesAlreadyEditedPane.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/RolesEditedSourceOP.java create mode 100644 designer_base/src/com/fr/design/roleAuthority/UIRoleTreeUI.java create mode 100644 designer_base/src/com/fr/design/scrollruler/BaseRuler.java create mode 100644 designer_base/src/com/fr/design/scrollruler/HorizontalRuler.java create mode 100644 designer_base/src/com/fr/design/scrollruler/HorizontalRulerUI.java create mode 100644 designer_base/src/com/fr/design/scrollruler/ModLineBorder.java create mode 100644 designer_base/src/com/fr/design/scrollruler/RulerLayout.java create mode 100644 designer_base/src/com/fr/design/scrollruler/RulerUI.java create mode 100644 designer_base/src/com/fr/design/scrollruler/ScrollRulerComponent.java create mode 100644 designer_base/src/com/fr/design/scrollruler/VerticalRuler.java create mode 100644 designer_base/src/com/fr/design/scrollruler/VerticalRulerUI.java create mode 100644 designer_base/src/com/fr/design/selection/QuickEditor.java create mode 100644 designer_base/src/com/fr/design/selection/SelectableElement.java create mode 100644 designer_base/src/com/fr/design/selection/Selectedable.java create mode 100644 designer_base/src/com/fr/design/selection/SelectionEvent.java create mode 100644 designer_base/src/com/fr/design/selection/SelectionListener.java create mode 100644 designer_base/src/com/fr/design/style/AbstractPopBox.java create mode 100644 designer_base/src/com/fr/design/style/AbstractSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/AlignmentPane.java create mode 100644 designer_base/src/com/fr/design/style/AlphaPane.java create mode 100644 designer_base/src/com/fr/design/style/BorderPane.java create mode 100644 designer_base/src/com/fr/design/style/ChooseFileView.java create mode 100644 designer_base/src/com/fr/design/style/CustomSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/FRFontPane.java create mode 100644 designer_base/src/com/fr/design/style/FRFontPreviewArea.java create mode 100644 designer_base/src/com/fr/design/style/FontFamilyPane.java create mode 100644 designer_base/src/com/fr/design/style/FontSizeStylePane.java create mode 100644 designer_base/src/com/fr/design/style/FormatBox.java create mode 100644 designer_base/src/com/fr/design/style/FormatPane.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundCustomJComponent.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundJComponent.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundPane.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundPane4BoxChange.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundPreviewLabel.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundUIComboBoxNoImagePane.java create mode 100644 designer_base/src/com/fr/design/style/background/BackgroundUIComboBoxPane.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/GradientBackgroundSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/GradientBar.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/GradientChangeBoxPane.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/GradientFromToPixPane.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/GradientPane.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/GradientSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/background/gradient/SelectColorPointBtn.java create mode 100644 designer_base/src/com/fr/design/style/background/image/ImageFileChooser.java create mode 100644 designer_base/src/com/fr/design/style/background/image/ImagePreviewPane.java create mode 100644 designer_base/src/com/fr/design/style/background/image/ImageSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/background/pattern/PatternSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/background/pattern/PatternSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/background/pattern/PatternUIComboBoxPane.java create mode 100644 designer_base/src/com/fr/design/style/background/texture/TextureSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/background/texture/TextureSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/background/texture/TextureUIComboBoxPane.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorCell.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorChooserPreview.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorControlWindow.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorFactory.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorSelectConfigManager.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorSelectDetailPane.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorSelectDialog.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorSelectable.java create mode 100644 designer_base/src/com/fr/design/style/color/ColorUIComboBoxPane.java create mode 100644 designer_base/src/com/fr/design/style/color/CustomChooserPanel.java create mode 100644 designer_base/src/com/fr/design/style/color/DetailColorSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/color/NewColorSelectBox.java create mode 100644 designer_base/src/com/fr/design/style/color/NewColorSelectPane.java create mode 100644 designer_base/src/com/fr/design/style/color/RecentUseColorPane.java create mode 100644 designer_base/src/com/fr/design/style/color/SwatchChooserPanel.java create mode 100644 designer_base/src/com/fr/design/style/color/TransparentColorControlWindow.java create mode 100644 designer_base/src/com/fr/design/style/color/TransparentPane.java create mode 100644 designer_base/src/com/fr/design/style/color/UIToolbarColorButton.java create mode 100644 designer_base/src/com/fr/design/style/color/UsedColorPane.java create mode 100644 designer_base/src/com/fr/design/utils/ColorRoutines.java create mode 100644 designer_base/src/com/fr/design/utils/ComponentUtils.java create mode 100644 designer_base/src/com/fr/design/utils/DesignUtils.java create mode 100644 designer_base/src/com/fr/design/utils/DrawRoutines.java create mode 100644 designer_base/src/com/fr/design/utils/ThemeUtils.java create mode 100644 designer_base/src/com/fr/design/utils/gui/GUICoreUtils.java create mode 100644 designer_base/src/com/fr/design/utils/gui/GUIPaintUtils.java create mode 100644 designer_base/src/com/fr/design/utils/gui/JListUtils.java create mode 100644 designer_base/src/com/fr/design/utils/gui/LayoutUtils.java create mode 100644 designer_base/src/com/fr/design/web/CustomIconPane.java create mode 100644 designer_base/src/com/fr/design/widget/Appearance.java create mode 100644 designer_base/src/com/fr/design/widget/IconDefinePane.java create mode 100644 designer_base/src/com/fr/design/widget/btn/ButtonConstants.java create mode 100644 designer_base/src/com/fr/design/widget/btn/ButtonDetailPane.java create mode 100644 designer_base/src/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java create mode 100644 designer_base/src/com/fr/design/write/submit/CustomJobPane.java create mode 100644 designer_base/src/com/fr/design/write/submit/CustomSubmitJobPane.java create mode 100644 designer_base/src/com/fr/design/write/submit/DBManipulationInWidgetEventPane.java create mode 100644 designer_base/src/com/fr/design/write/submit/DBManipulationPane.java create mode 100644 designer_base/src/com/fr/design/write/submit/DMLJobPane.java create mode 100644 designer_base/src/com/fr/design/write/submit/SubmitJobListPane.java create mode 100644 designer_base/src/com/fr/env/EnvListPane.java create mode 100644 designer_base/src/com/fr/env/RemoteEnv.java create mode 100644 designer_base/src/com/fr/env/RemoteSignInPane.java create mode 100644 designer_base/src/com/fr/env/SignIn.java create mode 100644 designer_base/src/com/fr/file/FILE.java create mode 100644 designer_base/src/com/fr/file/FILEChooserPane.java create mode 100644 designer_base/src/com/fr/file/FILEFactory.java create mode 100644 designer_base/src/com/fr/file/FileFILE.java create mode 100644 designer_base/src/com/fr/file/FileNodeFILE.java create mode 100644 designer_base/src/com/fr/file/MemFILE.java create mode 100644 designer_base/src/com/fr/file/filter/ChooseFileFilter.java create mode 100644 designer_base/src/com/fr/file/filter/FILEFilter.java create mode 100644 designer_base/src/com/fr/file/filter/OnlyShowDirectoryFileFilter.java create mode 100644 designer_base/src/com/fr/plugin/PluginManager.java create mode 100644 designer_base/src/com/fr/start/BBSGuestPaneProvider.java create mode 100644 designer_base/src/com/fr/start/BaseDesigner.java create mode 100644 designer_base/src/com/fr/start/Demo.java create mode 100644 designer_base/src/com/fr/start/JettyFRHost.java create mode 100644 designer_base/src/com/fr/start/SplashPane.java create mode 100644 designer_base/src/com/fr/start/SplashWindow.java create mode 100644 designer_base/src/com/fr/start/StartDocURL.java create mode 100644 designer_base/src/com/fr/start/StartServer.java create mode 100644 designer_base/src/com/fr/start/server/JettyHost.java create mode 100644 designer_base/src/com/fr/start/server/JettyServerListener.java create mode 100644 designer_base/src/com/fr/start/server/MultiOutputStream.java create mode 100644 designer_base/src/com/fr/start/server/ServerManageFrame.java create mode 100644 designer_base/src/com/fr/start/server/ServerTray.java diff --git a/.gitattributes b/.gitattributes index 75c7a0cfbb..20c9ef128d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -456,6 +456,2202 @@ designer/src/com/fr/start/Designer.java -text designer/src/com/fr/start/Designer4BI.java -text designer/src/com/fr/start/Designer4Debug.java -text designer/src/com/fr/start/ReportSplashPane.java -text +designer_base/.classpath -text +designer_base/.project -text +designer_base/designer_base.iml -text +designer_base/src/com/fr/design/DesignModelAdapter.java -text +designer_base/src/com/fr/design/DesignState.java -text +designer_base/src/com/fr/design/DesignerEnvManager.java -text +designer_base/src/com/fr/design/Exception/ValidationException.java -text +designer_base/src/com/fr/design/ExtraDesignClassManager.java -text +designer_base/src/com/fr/design/RestartHelper.java -text +designer_base/src/com/fr/design/actions/AllowAuthorityEditAction.java -text +designer_base/src/com/fr/design/actions/CheckBoxAction.java -text +designer_base/src/com/fr/design/actions/ExitAuthorityEditAction.java -text +designer_base/src/com/fr/design/actions/HyperlinkPluginAction.java -text +designer_base/src/com/fr/design/actions/JTemplateAction.java -text +designer_base/src/com/fr/design/actions/MenuAction.java -text +designer_base/src/com/fr/design/actions/TableDataSourceAction.java -text +designer_base/src/com/fr/design/actions/TemplateComponentAction.java -text +designer_base/src/com/fr/design/actions/TemplateComponentActionInterface.java -text +designer_base/src/com/fr/design/actions/ToggleButtonUpdateAction.java -text +designer_base/src/com/fr/design/actions/ToolbarActionManager.java -text +designer_base/src/com/fr/design/actions/UndoableAction.java -text +designer_base/src/com/fr/design/actions/UpdateAction.java -text +designer_base/src/com/fr/design/actions/core/ActionUtils.java -text +designer_base/src/com/fr/design/actions/edit/CopyAction.java -text +designer_base/src/com/fr/design/actions/edit/CutAction.java -text +designer_base/src/com/fr/design/actions/edit/PasteAction.java -text +designer_base/src/com/fr/design/actions/edit/RedoAction.java -text +designer_base/src/com/fr/design/actions/edit/UndoAction.java -text +designer_base/src/com/fr/design/actions/file/CloseCurrentTemplateAction.java -text +designer_base/src/com/fr/design/actions/file/CloseTemplateAction.java -text +designer_base/src/com/fr/design/actions/file/EditEnvAction.java -text +designer_base/src/com/fr/design/actions/file/ExitDesignerAction.java -text +designer_base/src/com/fr/design/actions/file/LocalePane.java -text +designer_base/src/com/fr/design/actions/file/OpenRecentReportMenuDef.java -text +designer_base/src/com/fr/design/actions/file/OpenTemplateAction.java -text +designer_base/src/com/fr/design/actions/file/PreferenceAction.java -text +designer_base/src/com/fr/design/actions/file/PreferencePane.java -text +designer_base/src/com/fr/design/actions/file/SaveAsTemplateAction.java -text +designer_base/src/com/fr/design/actions/file/SaveTemplateAction.java -text +designer_base/src/com/fr/design/actions/file/SwitchExistEnv.java -text +designer_base/src/com/fr/design/actions/file/WebPreviewUtils.java -text +designer_base/src/com/fr/design/actions/help/AboutAction.java -text +designer_base/src/com/fr/design/actions/help/AboutDialog.java -text +designer_base/src/com/fr/design/actions/help/AboutPane.java -text +designer_base/src/com/fr/design/actions/help/FeedBackAction.java -text +designer_base/src/com/fr/design/actions/help/FeedBackPane.java -text +designer_base/src/com/fr/design/actions/help/ForumAction.java -text +designer_base/src/com/fr/design/actions/help/SupportQQAction.java -text +designer_base/src/com/fr/design/actions/help/SystemInfoPane.java -text +designer_base/src/com/fr/design/actions/help/TutorialAction.java -text +designer_base/src/com/fr/design/actions/help/WebDemoAction.java -text +designer_base/src/com/fr/design/actions/server/ConnectionListAction.java -text +designer_base/src/com/fr/design/actions/server/FunctionManagerAction.java -text +designer_base/src/com/fr/design/actions/server/GlobalParameterAction.java -text +designer_base/src/com/fr/design/actions/server/GlobalTableDataAction.java -text +designer_base/src/com/fr/design/actions/server/PlatformManagerAction.java -text +designer_base/src/com/fr/design/actions/server/PluginManagerAction.java -text +designer_base/src/com/fr/design/actions/server/ProcedureListAction.java -text +designer_base/src/com/fr/design/actions/tabledata/TableDataAction.java -text +designer_base/src/com/fr/design/beans/BasicBeanPane.java -text +designer_base/src/com/fr/design/beans/FurtherBasicBeanPane.java -text +designer_base/src/com/fr/design/beans/GroupModel.java -text +designer_base/src/com/fr/design/beans/location/Absorptionline.java -text +designer_base/src/com/fr/design/beans/location/MoveUtils.java -text +designer_base/src/com/fr/design/border/UIRoundedBorder.java -text +designer_base/src/com/fr/design/border/UITitledBorder.java -text +designer_base/src/com/fr/design/bridge/DesignToolbarProvider.java -text +designer_base/src/com/fr/design/cell/FloatElementsProvider.java -text +designer_base/src/com/fr/design/condition/CellHighlightAddMenuDef.java -text +designer_base/src/com/fr/design/condition/ConditionAttrSingleConditionPane.java -text +designer_base/src/com/fr/design/condition/ConditionAttributesPane.java -text +designer_base/src/com/fr/design/condition/ContinuousTreeSelectionModel.java -text +designer_base/src/com/fr/design/condition/DSColumnLiteConditionPane.java -text +designer_base/src/com/fr/design/condition/DSColumnSimpleLiteConditionPane.java -text +designer_base/src/com/fr/design/condition/HighLightConditionAction.java -text +designer_base/src/com/fr/design/condition/LiteConditionPane.java -text +designer_base/src/com/fr/design/condition/ObjectLiteConditionPane.java -text +designer_base/src/com/fr/design/condition/SingleConditionPane.java -text +designer_base/src/com/fr/design/constants/KeyWords.java -text +designer_base/src/com/fr/design/constants/LayoutConstants.java -text +designer_base/src/com/fr/design/constants/UIConstants.java -text +designer_base/src/com/fr/design/data/DataCreatorUI.java -text +designer_base/src/com/fr/design/data/DesignTableDataManager.java -text +designer_base/src/com/fr/design/data/datapane/ChoosePane.java -text +designer_base/src/com/fr/design/data/datapane/ChoosePaneSupportFormula.java -text +designer_base/src/com/fr/design/data/datapane/DSButtonGroup.java -text +designer_base/src/com/fr/design/data/datapane/DataBaseItems.java -text +designer_base/src/com/fr/design/data/datapane/EditOrNewLabel.java -text +designer_base/src/com/fr/design/data/datapane/FlashLookLabelMouseAdapter.java -text +designer_base/src/com/fr/design/data/datapane/GlobalTableDataComboBox.java -text +designer_base/src/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java -text +designer_base/src/com/fr/design/data/datapane/RefreshLabel.java -text +designer_base/src/com/fr/design/data/datapane/ReportTableDataPane.java -text +designer_base/src/com/fr/design/data/datapane/TableDataComboBox.java -text +designer_base/src/com/fr/design/data/datapane/TableDataCreatorProducer.java -text +designer_base/src/com/fr/design/data/datapane/TableDataListPane.java -text +designer_base/src/com/fr/design/data/datapane/TableDataNameObjectCreator.java -text +designer_base/src/com/fr/design/data/datapane/TableDataSourceOP.java -text +designer_base/src/com/fr/design/data/datapane/TableDataTree.java -text +designer_base/src/com/fr/design/data/datapane/TableDataTreeDragSource.java -text +designer_base/src/com/fr/design/data/datapane/TableDataTreePane.java -text +designer_base/src/com/fr/design/data/datapane/TreeTableDataComboBox.java -text +designer_base/src/com/fr/design/data/datapane/TreeTableDataDictPane.java -text +designer_base/src/com/fr/design/data/datapane/VerticalChoosePane.java -text +designer_base/src/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java -text +designer_base/src/com/fr/design/data/datapane/connect/ConnectionListPane.java -text +designer_base/src/com/fr/design/data/datapane/connect/ConnectionManagerPane.java -text +designer_base/src/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java -text +designer_base/src/com/fr/design/data/datapane/connect/DataConnectionAction.java -text +designer_base/src/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java -text +designer_base/src/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java -text +designer_base/src/com/fr/design/data/datapane/connect/JDBCDefPane.java -text +designer_base/src/com/fr/design/data/datapane/connect/JNDIDefPane.java -text +designer_base/src/com/fr/design/data/datapane/preview/LoadedEventListener.java -text +designer_base/src/com/fr/design/data/datapane/preview/PreviewLabel.java -text +designer_base/src/com/fr/design/data/datapane/preview/PreviewTableModel.java -text +designer_base/src/com/fr/design/data/datapane/preview/PreviewTablePane.java -text +designer_base/src/com/fr/design/data/datapane/sqlpane/SQLEditPane.java -text +designer_base/src/com/fr/design/data/tabledata/Prepare4DataSourceChange.java -text +designer_base/src/com/fr/design/data/tabledata/ResponseDataSourceChange.java -text +designer_base/src/com/fr/design/data/tabledata/StoreProcedureWorkerListener.java -text +designer_base/src/com/fr/design/data/tabledata/gui/CONTENT.txt -text +designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN1.txt -text +designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN2.txt -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/AbstractTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/AutoStoreProcedureTableModel.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassNameSelectPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/CustomDictModel.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/DecoratedTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataDefinedPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableModel.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallHeightPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/FormatExplanationPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalMultiTDTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalTreeTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/OneListTableModel.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureListPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureManagerPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureParameterPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureTableModel.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/TableDataManagerPane.java -text +designer_base/src/com/fr/design/data/tabledata/tabledatapane/TreeTableDataPane.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/AbstractTableDataWrapper.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/ServerTableDataWrapper.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureNameWrapper.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataFactory.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataWrapper.java -text +designer_base/src/com/fr/design/data/tabledata/wrapper/TemplateTableDataWrapper.java -text +designer_base/src/com/fr/design/designer/EditingState.java -text +designer_base/src/com/fr/design/designer/TargetComponent.java -text +designer_base/src/com/fr/design/dialog/BasicDialog.java -text +designer_base/src/com/fr/design/dialog/BasicPane.java -text +designer_base/src/com/fr/design/dialog/BasicScrollPane.java -text +designer_base/src/com/fr/design/dialog/DialogActionAdapter.java -text +designer_base/src/com/fr/design/dialog/DialogActionListener.java -text +designer_base/src/com/fr/design/dialog/InformationWarnPane.java -text +designer_base/src/com/fr/design/dialog/JWizardDialog.java -text +designer_base/src/com/fr/design/dialog/JWizardPanel.java -text +designer_base/src/com/fr/design/dialog/MultiTabPane.java -text +designer_base/src/com/fr/design/dialog/UIDialog.java -text +designer_base/src/com/fr/design/dialog/package.html -text +designer_base/src/com/fr/design/editor/ValueEditorPane.java -text +designer_base/src/com/fr/design/editor/ValueEditorPaneFactory.java -text +designer_base/src/com/fr/design/editor/editor/BooleanEditor.java -text +designer_base/src/com/fr/design/editor/editor/ColumnIndexEditor.java -text +designer_base/src/com/fr/design/editor/editor/ColumnNameEditor.java -text +designer_base/src/com/fr/design/editor/editor/ColumnRowEditor.java -text +designer_base/src/com/fr/design/editor/editor/ColumnRowGroupEditor.java -text +designer_base/src/com/fr/design/editor/editor/ColumnSelectedEditor.java -text +designer_base/src/com/fr/design/editor/editor/ConstantsEditor.java -text +designer_base/src/com/fr/design/editor/editor/CursorEditor.java -text +designer_base/src/com/fr/design/editor/editor/DateEditor.java -text +designer_base/src/com/fr/design/editor/editor/DoubleEditor.java -text +designer_base/src/com/fr/design/editor/editor/Editor.java -text +designer_base/src/com/fr/design/editor/editor/EditorListener.java -text +designer_base/src/com/fr/design/editor/editor/FloatEditor.java -text +designer_base/src/com/fr/design/editor/editor/FormulaEditor.java -text +designer_base/src/com/fr/design/editor/editor/IntegerEditor.java -text +designer_base/src/com/fr/design/editor/editor/LongEditor.java -text +designer_base/src/com/fr/design/editor/editor/NoneEditor.java -text +designer_base/src/com/fr/design/editor/editor/NumberEditor.java -text +designer_base/src/com/fr/design/editor/editor/OldColumnIndexEditor.java -text +designer_base/src/com/fr/design/editor/editor/ParameterEditor.java -text +designer_base/src/com/fr/design/editor/editor/TextEditor.java -text +designer_base/src/com/fr/design/editor/editor/WidgetNameEditor.java -text +designer_base/src/com/fr/design/editor/editor/XMLANameEditor.java -text +designer_base/src/com/fr/design/event/ChangeEvent.java -text +designer_base/src/com/fr/design/event/ChangeListener.java -text +designer_base/src/com/fr/design/event/GlobalNameListener.java -text +designer_base/src/com/fr/design/event/GlobalNameObserver.java -text +designer_base/src/com/fr/design/event/TargetModifiedEvent.java -text +designer_base/src/com/fr/design/event/TargetModifiedListener.java -text +designer_base/src/com/fr/design/event/TemplateTreeDragSource.java -text +designer_base/src/com/fr/design/event/UIObserver.java -text +designer_base/src/com/fr/design/event/UIObserverListener.java -text +designer_base/src/com/fr/design/extra/After.java -text +designer_base/src/com/fr/design/extra/AppStoreBuilder.java -text +designer_base/src/com/fr/design/extra/LoginCheckContext.java -text +designer_base/src/com/fr/design/extra/LoginCheckListener.java -text +designer_base/src/com/fr/design/extra/PluginAbstractLoadingViewPane.java -text +designer_base/src/com/fr/design/extra/PluginAbstractViewPane.java -text +designer_base/src/com/fr/design/extra/PluginConstants.java -text +designer_base/src/com/fr/design/extra/PluginControlPane.java -text +designer_base/src/com/fr/design/extra/PluginDescriptionLabel.java -text +designer_base/src/com/fr/design/extra/PluginDetailPane.java -text +designer_base/src/com/fr/design/extra/PluginFromStorePane.java -text +designer_base/src/com/fr/design/extra/PluginHelper.java -text +designer_base/src/com/fr/design/extra/PluginInstalledPane.java -text +designer_base/src/com/fr/design/extra/PluginListPane.java -text +designer_base/src/com/fr/design/extra/PluginManagerPane.java -text +designer_base/src/com/fr/design/extra/PluginSelectListener.java -text +designer_base/src/com/fr/design/extra/PluginStatusCheckCompletePane.java -text +designer_base/src/com/fr/design/extra/PluginTask.java -text +designer_base/src/com/fr/design/extra/PluginUpdatePane.java -text +designer_base/src/com/fr/design/extra/PluginWebBridge.java -text +designer_base/src/com/fr/design/extra/PluginWebPane.java -text +designer_base/src/com/fr/design/extra/PluginsReaderFromStore.java -text +designer_base/src/com/fr/design/extra/Process.java -text +designer_base/src/com/fr/design/extra/exe/Command.java -text +designer_base/src/com/fr/design/extra/exe/Executor.java -text +designer_base/src/com/fr/design/extra/exe/InstallFromDiskExecutor.java -text +designer_base/src/com/fr/design/extra/exe/InstallOnlineExecutor.java -text +designer_base/src/com/fr/design/extra/exe/ModifyStatusExecutor.java -text +designer_base/src/com/fr/design/extra/exe/UninstallExecutor.java -text +designer_base/src/com/fr/design/extra/exe/UpdateFromDiskExecutor.java -text +designer_base/src/com/fr/design/extra/exe/UpdateOnlineExecutor.java -text +designer_base/src/com/fr/design/extra/plugin.properties -text +designer_base/src/com/fr/design/file/FileOperations.java -text +designer_base/src/com/fr/design/file/FileToolbarStateChangeListener.java -text +designer_base/src/com/fr/design/file/HistoryTemplateListPane.java -text +designer_base/src/com/fr/design/file/MutilTempalteTabPane.java -text +designer_base/src/com/fr/design/file/NewTemplatePane.java -text +designer_base/src/com/fr/design/file/SaveSomeTemplatePane.java -text +designer_base/src/com/fr/design/file/TemplateTreePane.java -text +designer_base/src/com/fr/design/formula/AbstractNameAndDescription.java -text +designer_base/src/com/fr/design/formula/CustomVariableResolver.java -text +designer_base/src/com/fr/design/formula/DefaultUIFormulaProcessor.java -text +designer_base/src/com/fr/design/formula/FormulaFactory.java -text +designer_base/src/com/fr/design/formula/FormulaPane.java -text +designer_base/src/com/fr/design/formula/FormulaPaneWhenReserveFormula.java -text +designer_base/src/com/fr/design/formula/FunctionConstants.java -text +designer_base/src/com/fr/design/formula/FunctionDefNAD.java -text +designer_base/src/com/fr/design/formula/FunctionGroup.java -text +designer_base/src/com/fr/design/formula/FunctionManagerPane.java -text +designer_base/src/com/fr/design/formula/FunctionNAD.java -text +designer_base/src/com/fr/design/formula/JavaEditorPane.java -text +designer_base/src/com/fr/design/formula/NameAndDescription.java -text +designer_base/src/com/fr/design/formula/NameAndFunctionList.java -text +designer_base/src/com/fr/design/formula/NameAndTypeAndFunctionList.java -text +designer_base/src/com/fr/design/formula/SortFormulaPane.java -text +designer_base/src/com/fr/design/formula/TinyFormulaPane.java -text +designer_base/src/com/fr/design/formula/UIFormula.java -text +designer_base/src/com/fr/design/formula/VariableResolver.java -text +designer_base/src/com/fr/design/formula/VariableResolverAdapter.java -text +designer_base/src/com/fr/design/fun/CellAttributeProvider.java -text +designer_base/src/com/fr/design/fun/CellWidgetOptionProvider.java -text +designer_base/src/com/fr/design/fun/ConnectionProvider.java -text +designer_base/src/com/fr/design/fun/ExportToolBarProvider.java -text +designer_base/src/com/fr/design/fun/Feedback.java -text +designer_base/src/com/fr/design/fun/FormElementCaseEditorProcessor.java -text +designer_base/src/com/fr/design/fun/FormWidgetOptionProvider.java -text +designer_base/src/com/fr/design/fun/GlobalListenerProvider.java -text +designer_base/src/com/fr/design/fun/HighlightProvider.java -text +designer_base/src/com/fr/design/fun/HyperlinkProvider.java -text +designer_base/src/com/fr/design/fun/IndentationUnitProcessor.java -text +designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java -text +designer_base/src/com/fr/design/fun/MenuHandler.java -text +designer_base/src/com/fr/design/fun/ParameterWidgetOptionProvider.java -text +designer_base/src/com/fr/design/fun/PresentKindProvider.java -text +designer_base/src/com/fr/design/fun/PreviewProvider.java -text +designer_base/src/com/fr/design/fun/ServerTableDataDefineProvider.java -text +designer_base/src/com/fr/design/fun/SubmitProvider.java -text +designer_base/src/com/fr/design/fun/TableDataCreatorProvider.java -text +designer_base/src/com/fr/design/fun/TableDataDefineProvider.java -text +designer_base/src/com/fr/design/fun/TitlePlaceProcessor.java -text +designer_base/src/com/fr/design/fun/ToolbarItemProvider.java -text +designer_base/src/com/fr/design/fun/UIFormulaProcessor.java -text +designer_base/src/com/fr/design/fun/impl/AbstractCellAttributeProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractCellWidgetOptionProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractConnectionProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractFormElementCaseEditorProcessor.java -text +designer_base/src/com/fr/design/fun/impl/AbstractFormWidgetOptionProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractGlobalListenerProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractHighlightProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractHyperlinkProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractIndentationUnitProcessor.java -text +designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractMenuHandler.java -text +designer_base/src/com/fr/design/fun/impl/AbstractParameterWidgetOptionProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractPresentKindProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractPreviewProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractServerTableDataDefineProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractSubmitProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractTableDataDefineProvider.java -text +designer_base/src/com/fr/design/fun/impl/AbstractTitleProcessor.java -text +designer_base/src/com/fr/design/fun/impl/AbstractToolbarItem.java -text +designer_base/src/com/fr/design/fun/impl/AbstractUIFormulaProcessor.java -text +designer_base/src/com/fr/design/gui/UIDefaultTheme.java -text +designer_base/src/com/fr/design/gui/UILookAndFeel.java -text +designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java -text +designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDemo.java -text +designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDescWindow.java -text +designer_base/src/com/fr/design/gui/autocomplete/AutoCompletePopupWindow.java -text +designer_base/src/com/fr/design/gui/autocomplete/AutoCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/AutoCompletionStyleContext.java -text +designer_base/src/com/fr/design/gui/autocomplete/BasicCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/Completion.java -text +designer_base/src/com/fr/design/gui/autocomplete/CompletionCellRenderer.java -text +designer_base/src/com/fr/design/gui/autocomplete/CompletionListModel.java -text +designer_base/src/com/fr/design/gui/autocomplete/CompletionProvider.java -text +designer_base/src/com/fr/design/gui/autocomplete/CompletionProviderBase.java -text +designer_base/src/com/fr/design/gui/autocomplete/CompletionXMLParser.java -text +designer_base/src/com/fr/design/gui/autocomplete/CompletionXml.dtd -text +designer_base/src/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java -text +designer_base/src/com/fr/design/gui/autocomplete/DelegatingCellRenderer.java -text +designer_base/src/com/fr/design/gui/autocomplete/DescWindowCallback.java -text +designer_base/src/com/fr/design/gui/autocomplete/EmptyIcon.java -text +designer_base/src/com/fr/design/gui/autocomplete/ExternalURLHandler.java -text +designer_base/src/com/fr/design/gui/autocomplete/FastListUI.java -text +designer_base/src/com/fr/design/gui/autocomplete/FunctionCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java -text +designer_base/src/com/fr/design/gui/autocomplete/LinkRedirector.java -text +designer_base/src/com/fr/design/gui/autocomplete/MarkupTagCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/OutlineHighlightPainter.java -text +designer_base/src/com/fr/design/gui/autocomplete/ParameterChoicesProvider.java -text +designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionChoicesWindow.java -text +designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java -text +designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionDescriptionToolTip.java -text +designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionInsertionInfo.java -text +designer_base/src/com/fr/design/gui/autocomplete/ShorthandCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/SizeGrip.java -text +designer_base/src/com/fr/design/gui/autocomplete/SortByRelevanceComparator.java -text +designer_base/src/com/fr/design/gui/autocomplete/TemplateCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/TemplatePiece.java -text +designer_base/src/com/fr/design/gui/autocomplete/TipUtil.java -text +designer_base/src/com/fr/design/gui/autocomplete/Util.java -text +designer_base/src/com/fr/design/gui/autocomplete/VariableCompletion.java -text +designer_base/src/com/fr/design/gui/autocomplete/arrow_left.png -text +designer_base/src/com/fr/design/gui/autocomplete/arrow_right.png -text +designer_base/src/com/fr/design/gui/autocomplete/bullet_black.png -text +designer_base/src/com/fr/design/gui/autocomplete/osx_sizegrip.png -text +designer_base/src/com/fr/design/gui/borders/UIFrameBorder.java -text +designer_base/src/com/fr/design/gui/borders/UIInternalFrameBorder.java -text +designer_base/src/com/fr/design/gui/borders/UITableHeaderBorder.java -text +designer_base/src/com/fr/design/gui/borders/UITableHeaderRolloverBorder.java -text +designer_base/src/com/fr/design/gui/borders/UITableScrollPaneBorder.java -text +designer_base/src/com/fr/design/gui/borders/UITextFieldBorder.java -text +designer_base/src/com/fr/design/gui/chart/BaseChartPropertyPane.java -text +designer_base/src/com/fr/design/gui/chart/MiddleChartComponent.java -text +designer_base/src/com/fr/design/gui/chart/MiddleChartDialog.java -text +designer_base/src/com/fr/design/gui/columnrow/ColumnRowPane.java -text +designer_base/src/com/fr/design/gui/columnrow/ColumnRowVerticalPane.java -text +designer_base/src/com/fr/design/gui/controlpane/AbstractNameableCreator.java -text +designer_base/src/com/fr/design/gui/controlpane/ControlPane.java -text +designer_base/src/com/fr/design/gui/controlpane/JControlPane.java -text +designer_base/src/com/fr/design/gui/controlpane/NameObjectCreator.java -text +designer_base/src/com/fr/design/gui/controlpane/NameableCreator.java -text +designer_base/src/com/fr/design/gui/controlpane/NameableSelfCreator.java -text +designer_base/src/com/fr/design/gui/controlpane/ObjectJControlPane.java -text +designer_base/src/com/fr/design/gui/controlpane/ShortCut4JControlPane.java -text +designer_base/src/com/fr/design/gui/controlpane/UnrepeatedNameHelper.java -text +designer_base/src/com/fr/design/gui/core/CustomWidgetOption.java -text +designer_base/src/com/fr/design/gui/core/UIFurtherTabComponent.java -text +designer_base/src/com/fr/design/gui/core/UISelectedComponent.java -text +designer_base/src/com/fr/design/gui/core/UITabComponent.java -text +designer_base/src/com/fr/design/gui/core/UserDefinedWidgetOption.java -text +designer_base/src/com/fr/design/gui/core/WidgetConstants.java -text +designer_base/src/com/fr/design/gui/core/WidgetOption.java -text +designer_base/src/com/fr/design/gui/core/WidgetOptionFactory.java -text +designer_base/src/com/fr/design/gui/date/CalendarNumberField.java -text +designer_base/src/com/fr/design/gui/date/JDateDocument.java -text +designer_base/src/com/fr/design/gui/date/SingleObjectComboBoxModel.java -text +designer_base/src/com/fr/design/gui/date/UICalendarPanel.java -text +designer_base/src/com/fr/design/gui/date/UIDatePicker.java -text +designer_base/src/com/fr/design/gui/date/UIDayLabel.java -text +designer_base/src/com/fr/design/gui/demo/ComboBoxDemo.java -text +designer_base/src/com/fr/design/gui/demo/LabelDemo.java -text +designer_base/src/com/fr/design/gui/demo/ListDemo.java -text +designer_base/src/com/fr/design/gui/demo/LoadingPaneDemo.java -text +designer_base/src/com/fr/design/gui/demo/MultiLineTooltipDemo.java -text +designer_base/src/com/fr/design/gui/demo/SwingComponentsDemo.java -text +designer_base/src/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java -text +designer_base/src/com/fr/design/gui/frpane/AttributeChangeListener.java -text +designer_base/src/com/fr/design/gui/frpane/BaseHyperlinkGroup.java -text +designer_base/src/com/fr/design/gui/frpane/CommitTabbedPane.java -text +designer_base/src/com/fr/design/gui/frpane/EditingStringListPane.java -text +designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupPane.java -text +designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupType.java -text +designer_base/src/com/fr/design/gui/frpane/ImgChoosePane.java -text +designer_base/src/com/fr/design/gui/frpane/JTreeAutoBuildPane.java -text +designer_base/src/com/fr/design/gui/frpane/JTreeControlPane.java -text +designer_base/src/com/fr/design/gui/frpane/LimitedDocument.java -text +designer_base/src/com/fr/design/gui/frpane/ListenerUpdatePane.java -text +designer_base/src/com/fr/design/gui/frpane/LoadingBasicPane.java -text +designer_base/src/com/fr/design/gui/frpane/LoadingBasicPaneTest.java -text +designer_base/src/com/fr/design/gui/frpane/ObjectProperiesPane.java -text +designer_base/src/com/fr/design/gui/frpane/RegPane.java -text +designer_base/src/com/fr/design/gui/frpane/ReportletParameterViewPane.java -text +designer_base/src/com/fr/design/gui/frpane/TemplateParameterPane.java -text +designer_base/src/com/fr/design/gui/frpane/TreeSettingPane.java -text +designer_base/src/com/fr/design/gui/frpane/UIAdvancedTextPane.java -text +designer_base/src/com/fr/design/gui/frpane/UIBasicOptionPaneUI.java -text +designer_base/src/com/fr/design/gui/frpane/UIBubbleFloatPane.java -text +designer_base/src/com/fr/design/gui/frpane/UIComboBoxPane.java -text +designer_base/src/com/fr/design/gui/frpane/UICorrelationComboBoxPane.java -text +designer_base/src/com/fr/design/gui/frpane/UICorrelationPane.java -text +designer_base/src/com/fr/design/gui/frpane/UIExtensionPane.java -text +designer_base/src/com/fr/design/gui/frpane/UINumberDragPane.java -text +designer_base/src/com/fr/design/gui/frpane/UINumberSlidePane.java -text +designer_base/src/com/fr/design/gui/frpane/UIRadioPane.java -text +designer_base/src/com/fr/design/gui/frpane/UITabbedPane.java -text +designer_base/src/com/fr/design/gui/frpane/UITabbedPaneUI.java -text +designer_base/src/com/fr/design/gui/frpane/UITextPane.java -text +designer_base/src/com/fr/design/gui/frpane/UITitlePanel.java -text +designer_base/src/com/fr/design/gui/frpane/UnitInputPane.java -text +designer_base/src/com/fr/design/gui/ibutton/FiveButtonLayout.java -text +designer_base/src/com/fr/design/gui/ibutton/SpecialUIButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UIBasicButtonUI.java -text +designer_base/src/com/fr/design/gui/ibutton/UIButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UIButtonBorder.java -text +designer_base/src/com/fr/design/gui/ibutton/UIButtonGroup.java -text +designer_base/src/com/fr/design/gui/ibutton/UIButtonUI.java -text +designer_base/src/com/fr/design/gui/ibutton/UIColorButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UICombinationButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UIHeadGroup.java -text +designer_base/src/com/fr/design/gui/ibutton/UIPasswordField.java -text +designer_base/src/com/fr/design/gui/ibutton/UIPreviewButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UIRadioButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonIcon.java -text +designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonMenuItemUI.java -text +designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonUI.java -text +designer_base/src/com/fr/design/gui/ibutton/UITabButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UITabGroup.java -text +designer_base/src/com/fr/design/gui/ibutton/UIToggleButton.java -text +designer_base/src/com/fr/design/gui/ibutton/UIToolButtonBorder.java -text +designer_base/src/com/fr/design/gui/icheckbox/UICheckBox.java -text +designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxIcon.java -text +designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxUI.java -text +designer_base/src/com/fr/design/gui/icombobox/AlignmentComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/ComboCheckBox.java -text +designer_base/src/com/fr/design/gui/icombobox/DictionaryComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/DictionaryConstants.java -text +designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBoxTest.java -text +designer_base/src/com/fr/design/gui/icombobox/FRTreeComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/FilterComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/FilterableComboBoxModel.java -text +designer_base/src/com/fr/design/gui/icombobox/FixedHeightComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/FunctionComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/IntComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/LazyComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/LazyComboBoxTest.java -text +designer_base/src/com/fr/design/gui/icombobox/LineComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/ParameterComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/SortOrderComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/TreeComboBoxUI.java -text +designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxEditor.java -text +designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxUI.java -text +designer_base/src/com/fr/design/gui/icombobox/UIComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/UIComboBoxButton.java -text +designer_base/src/com/fr/design/gui/icombobox/UIComboBoxEditor.java -text +designer_base/src/com/fr/design/gui/icombobox/UIComboBoxRenderer.java -text +designer_base/src/com/fr/design/gui/icombobox/UIComboBoxUI.java -text +designer_base/src/com/fr/design/gui/icombobox/UIDictionaryComboBox.java -text +designer_base/src/com/fr/design/gui/icombobox/filter/Filter.java -text +designer_base/src/com/fr/design/gui/icombobox/filter/LastStartWithFilter.java -text +designer_base/src/com/fr/design/gui/icombobox/filter/StartsWithFilter.java -text +designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeCellRenderer.java -text +designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeLabel.java -text +designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNode.java -text +designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNodeSelectionListener.java -text +designer_base/src/com/fr/design/gui/icontainer/UIModeControlContainer.java -text +designer_base/src/com/fr/design/gui/icontainer/UIResizableContainer.java -text +designer_base/src/com/fr/design/gui/icontainer/UIScrollPane.java -text +designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneBorder.java -text +designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneUI.java -text +designer_base/src/com/fr/design/gui/icontainer/UITableScrollPaneBorder.java -text +designer_base/src/com/fr/design/gui/icontainer/UIVerticalScrollPane.java -text +designer_base/src/com/fr/design/gui/ilable/ActionLabel.java -text +designer_base/src/com/fr/design/gui/ilable/BoldFontTextLabel.java -text +designer_base/src/com/fr/design/gui/ilable/FRExplainLabel.java -text +designer_base/src/com/fr/design/gui/ilable/MultilineLabel.java -text +designer_base/src/com/fr/design/gui/ilable/UILabel.java -text +designer_base/src/com/fr/design/gui/ilist/ArrayListModel.java -text +designer_base/src/com/fr/design/gui/ilist/CheckBoxList.java -text +designer_base/src/com/fr/design/gui/ilist/DefaultListCellEditor.java -text +designer_base/src/com/fr/design/gui/ilist/JNameEdList.java -text +designer_base/src/com/fr/design/gui/ilist/ListCellEditor.java -text +designer_base/src/com/fr/design/gui/ilist/ListModelElement.java -text +designer_base/src/com/fr/design/gui/ilist/ModNameActionListener.java -text +designer_base/src/com/fr/design/gui/ilist/QuickList.java -text +designer_base/src/com/fr/design/gui/ilist/TableViewList.java -text +designer_base/src/com/fr/design/gui/ilist/UIList.java -text +designer_base/src/com/fr/design/gui/imenu/UIBasicMenuItemUI.java -text +designer_base/src/com/fr/design/gui/imenu/UIBasicMenuUI.java -text +designer_base/src/com/fr/design/gui/imenu/UICheckBoxMenuItem.java -text +designer_base/src/com/fr/design/gui/imenu/UIListPopup.java -text +designer_base/src/com/fr/design/gui/imenu/UIMenu.java -text +designer_base/src/com/fr/design/gui/imenu/UIMenuBar.java -text +designer_base/src/com/fr/design/gui/imenu/UIMenuBarUI.java -text +designer_base/src/com/fr/design/gui/imenu/UIMenuHighLight.java -text +designer_base/src/com/fr/design/gui/imenu/UIMenuItem.java -text +designer_base/src/com/fr/design/gui/imenu/UIMenuUI.java -text +designer_base/src/com/fr/design/gui/imenu/UIPopupMenu.java -text +designer_base/src/com/fr/design/gui/imenu/UIPopupMenuBorder.java -text +designer_base/src/com/fr/design/gui/imenu/UIPopupMenuSeparatorUI.java -text +designer_base/src/com/fr/design/gui/imenu/UIScrollMenu.java -text +designer_base/src/com/fr/design/gui/imenu/UIScrollMenuDemo.java -text +designer_base/src/com/fr/design/gui/imenu/UIScrollPopUpMenu.java -text +designer_base/src/com/fr/design/gui/imenutable/UIMenuNameableCreator.java -text +designer_base/src/com/fr/design/gui/imenutable/UIMenuTable.java -text +designer_base/src/com/fr/design/gui/imenutable/UIMenuTableDataModel.java -text +designer_base/src/com/fr/design/gui/imenutable/UIMenuTableUI.java -text +designer_base/src/com/fr/design/gui/ipasswordfield/UIPassWordField.java -text +designer_base/src/com/fr/design/gui/ipoppane/PopupHider.java -text +designer_base/src/com/fr/design/gui/iprogressbar/AutoProgressBar.java -text +designer_base/src/com/fr/design/gui/iprogressbar/FRProgressBar.java -text +designer_base/src/com/fr/design/gui/iprogressbar/MonitorCancelWork.java -text +designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarBorder.java -text +designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarUI.java -text +designer_base/src/com/fr/design/gui/iscrollbar/UIBasicScrollBarUI.java -text +designer_base/src/com/fr/design/gui/iscrollbar/UISBChooser.java -text +designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBar.java -text +designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBarUI.java -text +designer_base/src/com/fr/design/gui/iscrollbar/UIScrollButton.java -text +designer_base/src/com/fr/design/gui/islider/UISlider.java -text +designer_base/src/com/fr/design/gui/ispinner/UIBasicSpinner.java -text +designer_base/src/com/fr/design/gui/ispinner/UISpinner.java -text +designer_base/src/com/fr/design/gui/ispinner/UISpinnerButtonUI.java -text +designer_base/src/com/fr/design/gui/ispinner/UISpinnerUI.java -text +designer_base/src/com/fr/design/gui/ispinner/UpperCaseSpinner.java -text +designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneDivider.java -text +designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneUI.java -text +designer_base/src/com/fr/design/gui/itable/AbstractPropertyTable.java -text +designer_base/src/com/fr/design/gui/itable/GroupRenderer.java -text +designer_base/src/com/fr/design/gui/itable/HeaderRenderer.java -text +designer_base/src/com/fr/design/gui/itable/PropertyGroup.java -text +designer_base/src/com/fr/design/gui/itable/SortableJTable.java -text +designer_base/src/com/fr/design/gui/itable/TableSorter.java -text +designer_base/src/com/fr/design/gui/itable/UIBasicTableUI.java -text +designer_base/src/com/fr/design/gui/itable/UIComponentTable.java -text +designer_base/src/com/fr/design/gui/itable/UIDefaultTableCellEditor.java -text +designer_base/src/com/fr/design/gui/itable/UISelectTable.java -text +designer_base/src/com/fr/design/gui/itable/UITable.java -text +designer_base/src/com/fr/design/gui/itable/UITableComponentModel.java -text +designer_base/src/com/fr/design/gui/itable/UITableDataModel.java -text +designer_base/src/com/fr/design/gui/itable/UITableEditor.java -text +designer_base/src/com/fr/design/gui/itable/UITableNoOptionUI.java -text +designer_base/src/com/fr/design/gui/itable/UITableUI.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/ActionStyle.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/ParameterTableModel.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/UIArrayTableModel.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditAction.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorLoader.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorPane.java -text +designer_base/src/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java -text +designer_base/src/com/fr/design/gui/itabpane/TitleChangeListener.java -text +designer_base/src/com/fr/design/gui/itabpane/UITabPaneCreator.java -text +designer_base/src/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java -text +designer_base/src/com/fr/design/gui/itextarea/DescriptionTextArea.java -text +designer_base/src/com/fr/design/gui/itextarea/FRExplainTextArea.java -text +designer_base/src/com/fr/design/gui/itextarea/UITextArea.java -text +designer_base/src/com/fr/design/gui/itextarea/UITextAreaUI.java -text +designer_base/src/com/fr/design/gui/itextfield/AutoCompletionDemo.java -text +designer_base/src/com/fr/design/gui/itextfield/CompletionFilter.java -text +designer_base/src/com/fr/design/gui/itextfield/DefaultCompletionFilter.java -text +designer_base/src/com/fr/design/gui/itextfield/EditTextField.java -text +designer_base/src/com/fr/design/gui/itextfield/FRGraphics2D.java -text +designer_base/src/com/fr/design/gui/itextfield/PlaceholderTextField.java -text +designer_base/src/com/fr/design/gui/itextfield/TextFieldUI.java -text +designer_base/src/com/fr/design/gui/itextfield/UIAutoCompletionField.java -text +designer_base/src/com/fr/design/gui/itextfield/UIGridTextField.java -text +designer_base/src/com/fr/design/gui/itextfield/UINumberField.java -text +designer_base/src/com/fr/design/gui/itextfield/UISearchTextField.java -text +designer_base/src/com/fr/design/gui/itextfield/UITextField.java -text +designer_base/src/com/fr/design/gui/itextfield/UITextFieldUI.java -text +designer_base/src/com/fr/design/gui/itoolbar/UILargeToolbar.java -text +designer_base/src/com/fr/design/gui/itoolbar/UIToolBarBorder.java -text +designer_base/src/com/fr/design/gui/itoolbar/UIToolBarSeparatorUI.java -text +designer_base/src/com/fr/design/gui/itoolbar/UIToolBarUI.java -text +designer_base/src/com/fr/design/gui/itoolbar/UIToolbar.java -text +designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTip.java -text +designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTipUI.java -text +designer_base/src/com/fr/design/gui/itooltip/UIToolTip.java -text +designer_base/src/com/fr/design/gui/itooltip/UIToolTipBorder.java -text +designer_base/src/com/fr/design/gui/itooltip/UIToolTipUI.java -text +designer_base/src/com/fr/design/gui/itree/UITreeUI.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTree.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeSelectionModel.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/NullLabel.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/NullPanel.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java -text +designer_base/src/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java -text +designer_base/src/com/fr/design/gui/itree/filetree/AbstractFileTree.java -text +designer_base/src/com/fr/design/gui/itree/filetree/ClassFileTree.java -text +designer_base/src/com/fr/design/gui/itree/filetree/EnvFileTree.java -text +designer_base/src/com/fr/design/gui/itree/filetree/FileComparator.java -text +designer_base/src/com/fr/design/gui/itree/filetree/FileDirectoryNode.java -text +designer_base/src/com/fr/design/gui/itree/filetree/FileNodeComparator.java -text +designer_base/src/com/fr/design/gui/itree/filetree/FileTreeIcon.java -text +designer_base/src/com/fr/design/gui/itree/filetree/JFileTree.java -text +designer_base/src/com/fr/design/gui/itree/filetree/ReportletPane.java -text +designer_base/src/com/fr/design/gui/itree/filetree/RootFile.java -text +designer_base/src/com/fr/design/gui/itree/filetree/TemplateFileTree.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTreeTest.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeDataCardPane.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeNodePane.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectOP.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectRefreshJTree.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenLoaderFactory.java -text +designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenNodesLoader.java -text +designer_base/src/com/fr/design/gui/style/AbstractBasicStylePane.java -text +designer_base/src/com/fr/design/gui/style/AlignmentPane.java -text +designer_base/src/com/fr/design/gui/style/BackgroundNoImagePane.java -text +designer_base/src/com/fr/design/gui/style/BackgroundPane.java -text +designer_base/src/com/fr/design/gui/style/BackgroundSpecialPane.java -text +designer_base/src/com/fr/design/gui/style/BorderPane.java -text +designer_base/src/com/fr/design/gui/style/DefaultIndentationUnitProcessor.java -text +designer_base/src/com/fr/design/gui/style/FRFontPane.java -text +designer_base/src/com/fr/design/gui/style/FormatPane.java -text +designer_base/src/com/fr/design/gui/style/FormatePaneNumField.java -text +designer_base/src/com/fr/design/gui/style/GradientPane.java -text +designer_base/src/com/fr/design/gui/style/NumberDragBar.java -text +designer_base/src/com/fr/design/gui/syntax/io/DocumentReader.java -text +designer_base/src/com/fr/design/gui/syntax/io/UnicodeReader.java -text +designer_base/src/com/fr/design/gui/syntax/io/UnicodeWriter.java -text +designer_base/src/com/fr/design/gui/syntax/io/package.html -text +designer_base/src/com/fr/design/gui/syntax/print/RPrintUtilities.java -text +designer_base/src/com/fr/design/gui/syntax/print/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractJFlexCTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractJFlexTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/AbstractTokenMakerFactory.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ActiveLineRangeEvent.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ActiveLineRangeListener.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ChangeableColorHighlightPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/CodeTemplateManager.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultOccurrenceMarker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultTokenFactory.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultTokenMakerFactory.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DefaultTokenPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/DocumentRange.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ar.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_de.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_es.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_fr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_hu.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_in.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_it.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ja.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ko.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_nl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_pl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_pt_BR.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_ru.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_tr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_zh_CN.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ErrorStrip_zh_TW.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/FileFileLocation.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/FileLocation.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/FoldingAwareIconRowHeader.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/LinkGenerator.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/LinkGeneratorResult.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/MarkOccurrencesHighlightPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/MarkOccurrencesSupport.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/OccurrenceMarker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/ParserManager.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/PopupWindowDecorator.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSTAView.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxDocument.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaDefaultInputMap.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaEditorKit.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaHighlighter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextAreaUI.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ar.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_de.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_es.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_fr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_hu.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_in.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_it.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ja.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ko.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_nl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_pl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_pt_BR.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_ru.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_tr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_zh_CN.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxTextArea_zh_TW.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RSyntaxUtilities.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RTfToText.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RtfGenerator.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/RtfTransferable.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SelectRegionLinkGeneratorResult.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SquiggleUnderlineHighlightPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Style.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxConstants.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxScheme.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/SyntaxView.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TextEditorPane.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Theme.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/Token.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenFactory.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenImpl.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenIterator.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMakerBase.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMakerFactory.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenMap.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenOrientedView.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenTypes.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/TokenUtils.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/URLFileLocation.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/VisibleWhitespaceTokenPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/WrappedSyntaxView.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/WrappedSyntaxView2.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/XmlOccurrenceMarker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ar.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_de.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_es.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_fr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_hu.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_in.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_it.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ja.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ko.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_nl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_pl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_pt_BR.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_ru.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_tr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_zh_CN.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/FocusableTip_zh_TW.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/SizeGrip.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/TipUtil.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/TipWindow.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/osx_sizegrip.png -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/focusabletip/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/CurlyFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/Fold.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldCollapser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldManager.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldParserManager.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/FoldType.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/HtmlFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/JsonFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/LatexFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/LispFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/NsisFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/XmlFoldParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/folding/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/AbstractMarkupTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ActionScriptTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ActionScriptTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/AssemblerX86TokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/AssemblerX86TokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/BBCodeTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/BBCodeTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CPlusPlusTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CPlusPlusTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSSTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSSTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSharpTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CSharpTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/CTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ClojureTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ClojureTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DelphiTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DelphiTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DtdTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/DtdTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FormulaTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FortranTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/FortranTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/GroovyTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/GroovyTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HTMLTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HTMLTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HtaccessTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/HtaccessTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JSPTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JSPTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaScriptTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaScriptTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JavaTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JsonTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/JsonTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LatexTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LatexTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LispTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LispTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LuaTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/LuaTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MakefileTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MakefileTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MxmlTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/MxmlTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/NSISTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/NSISTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PHPTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PHPTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PerlTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PerlTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PlainTextTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PlainTextTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PropertiesFileTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PropertiesFileTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PythonTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/PythonTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/RubyTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/RubyTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SASTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SASTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SQLTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/SQLTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ScalaTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/ScalaTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/TclTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/TclTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/UnixShellTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/VisualBasicTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/VisualBasicTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/WindowsBatchTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/XMLTokenMaker.flex -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/XMLTokenMaker.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/modes/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/AbstractParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/DefaultParseResult.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/DefaultParserNotice.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ExtendedHyperlinkListener.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ParseResult.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/Parser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ParserNotice.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/TaskTagParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/ToolTipInfo.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/XmlParser.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/parser/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/AbstractCodeTemplate.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/CodeTemplate.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/StaticCodeTemplate.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rsyntaxtextarea/templates/package.html -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/AbstractGutterComponent.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/BackgroundPainterStrategy.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/BufferedImageBackgroundPainterStrategy.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ChangeableHighlightPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ColorBackgroundPainterStrategy.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ConfigurableCaret.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/FoldIndicator.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/Gutter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/GutterIconInfo.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/IconGroup.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/IconRowHeader.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ImageBackgroundPainterStrategy.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/LineHighlightManager.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/LineNumberList.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/Macro.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RDocument.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RDocumentCharSequence.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTADefaultInputMap.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTATextTransferHandler.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaBase.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaEditorKit.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaHighlighter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextAreaUI.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ar.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_de.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_es.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_fr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_hu.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_in.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_it.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ja.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ko.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_nl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_pl.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_pt_BR.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_ru.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_tr.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_zh_CN.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextArea_zh_TW.properties -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RTextScrollPane.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RUndoManager.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RecordableTextAction.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/RegExReplaceInfo.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SearchContext.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SearchEngine.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SearchResult.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/SmartHighlightPainter.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/ToolTipSupplier.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/VolatileImageBackgroundPainterStrategy.java -text +designer_base/src/com/fr/design/gui/syntax/ui/rtextarea/package.html -text +designer_base/src/com/fr/design/gui/syntax/util/DynamicIntArray.java -text +designer_base/src/com/fr/design/gui/syntax/util/package.html -text +designer_base/src/com/fr/design/gui/toast/Toast.java -text +designer_base/src/com/fr/design/hyperlink/AbstractHyperlinkPane.java -text +designer_base/src/com/fr/design/hyperlink/ReporletHyperNorthPane.java -text +designer_base/src/com/fr/design/hyperlink/ReportletHyperlinkPane.java -text +designer_base/src/com/fr/design/hyperlink/WebHyperNorthPane.java -text +designer_base/src/com/fr/design/hyperlink/WebHyperlinkPane.java -text +designer_base/src/com/fr/design/icon/BorderIcon.java -text +designer_base/src/com/fr/design/icon/IconPathConstants.java -text +designer_base/src/com/fr/design/icon/LockIcon.java -text +designer_base/src/com/fr/design/icon/WarningIcon.java -text +designer_base/src/com/fr/design/images/arrow/arrow_down.png -text +designer_base/src/com/fr/design/images/arrow/arrow_up.png -text +designer_base/src/com/fr/design/images/browser/360.png -text +designer_base/src/com/fr/design/images/browser/back.png -text +designer_base/src/com/fr/design/images/browser/chrome.png -text +designer_base/src/com/fr/design/images/browser/firefox.png -text +designer_base/src/com/fr/design/images/browser/forward.png -text +designer_base/src/com/fr/design/images/browser/go.png -text +designer_base/src/com/fr/design/images/browser/home.png -text +designer_base/src/com/fr/design/images/browser/ie.png -text +designer_base/src/com/fr/design/images/browser/reload.png -text +designer_base/src/com/fr/design/images/browser/stop.png -text +designer_base/src/com/fr/design/images/buttonicon/add.png -text +designer_base/src/com/fr/design/images/buttonicon/add_over.png -text +designer_base/src/com/fr/design/images/buttonicon/add_press.png -text +designer_base/src/com/fr/design/images/buttonicon/addicon.png -text +designer_base/src/com/fr/design/images/buttonicon/additicon_grey.png -text +designer_base/src/com/fr/design/images/buttonicon/anab24.png -text +designer_base/src/com/fr/design/images/buttonicon/anas.png -text +designer_base/src/com/fr/design/images/buttonicon/arrow.png -text +designer_base/src/com/fr/design/images/buttonicon/arrowdown.png -text +designer_base/src/com/fr/design/images/buttonicon/arrowup.png -text +designer_base/src/com/fr/design/images/buttonicon/bind_ds_column.png -text +designer_base/src/com/fr/design/images/buttonicon/button_0.png -text +designer_base/src/com/fr/design/images/buttonicon/cell.png -text +designer_base/src/com/fr/design/images/buttonicon/cell_group.png -text +designer_base/src/com/fr/design/images/buttonicon/close_icon.png -text +designer_base/src/com/fr/design/images/buttonicon/column.png -text +designer_base/src/com/fr/design/images/buttonicon/cube.png -text +designer_base/src/com/fr/design/images/buttonicon/ds_column.png -text +designer_base/src/com/fr/design/images/buttonicon/ds_column_index.png -text +designer_base/src/com/fr/design/images/buttonicon/ds_column_name.png -text +designer_base/src/com/fr/design/images/buttonicon/dscolumn.png -text +designer_base/src/com/fr/design/images/buttonicon/editn.png -text +designer_base/src/com/fr/design/images/buttonicon/editp.png -text +designer_base/src/com/fr/design/images/buttonicon/hiden.png -text +designer_base/src/com/fr/design/images/buttonicon/hidep.png -text +designer_base/src/com/fr/design/images/buttonicon/history.png -text +designer_base/src/com/fr/design/images/buttonicon/list_cover.png -text +designer_base/src/com/fr/design/images/buttonicon/list_covered.png -text +designer_base/src/com/fr/design/images/buttonicon/list_icon.png -text +designer_base/src/com/fr/design/images/buttonicon/list_normal.png -text +designer_base/src/com/fr/design/images/buttonicon/list_press.png -text +designer_base/src/com/fr/design/images/buttonicon/list_pressed.png -text +designer_base/src/com/fr/design/images/buttonicon/minus.png -text +designer_base/src/com/fr/design/images/buttonicon/more.png -text +designer_base/src/com/fr/design/images/buttonicon/more2.png -text +designer_base/src/com/fr/design/images/buttonicon/more3.png -text +designer_base/src/com/fr/design/images/buttonicon/more4.png -text +designer_base/src/com/fr/design/images/buttonicon/mouseoverclose[!!-~]icon.png -text +designer_base/src/com/fr/design/images/buttonicon/newcpts.png -text +designer_base/src/com/fr/design/images/buttonicon/open.png -text +designer_base/src/com/fr/design/images/buttonicon/pageb24.png -text +designer_base/src/com/fr/design/images/buttonicon/pages.png -text +designer_base/src/com/fr/design/images/buttonicon/parameter.png -text +designer_base/src/com/fr/design/images/buttonicon/plus.png -text +designer_base/src/com/fr/design/images/buttonicon/pressclose[!!-~]icon.png -text +designer_base/src/com/fr/design/images/buttonicon/prevew_down_icon.png -text +designer_base/src/com/fr/design/images/buttonicon/prewidget.png -text +designer_base/src/com/fr/design/images/buttonicon/redo.png -text +designer_base/src/com/fr/design/images/buttonicon/refresh.png -text +designer_base/src/com/fr/design/images/buttonicon/run24.png -text +designer_base/src/com/fr/design/images/buttonicon/runs.png -text +designer_base/src/com/fr/design/images/buttonicon/save.png -text +designer_base/src/com/fr/design/images/buttonicon/select.png -text +designer_base/src/com/fr/design/images/buttonicon/select_item.png -text +designer_base/src/com/fr/design/images/buttonicon/setting.png -text +designer_base/src/com/fr/design/images/buttonicon/switchShortCuts.png -text +designer_base/src/com/fr/design/images/buttonicon/type_bool.png -text +designer_base/src/com/fr/design/images/buttonicon/type_cursor.png -text +designer_base/src/com/fr/design/images/buttonicon/type_date.png -text +designer_base/src/com/fr/design/images/buttonicon/type_double.png -text +designer_base/src/com/fr/design/images/buttonicon/type_formula.png -text +designer_base/src/com/fr/design/images/buttonicon/type_int.png -text +designer_base/src/com/fr/design/images/buttonicon/type_none.png -text +designer_base/src/com/fr/design/images/buttonicon/type_string.png -text +designer_base/src/com/fr/design/images/buttonicon/undo.png -text +designer_base/src/com/fr/design/images/buttonicon/viewn.png -text +designer_base/src/com/fr/design/images/buttonicon/viewp.png -text +designer_base/src/com/fr/design/images/buttonicon/warn.png -text +designer_base/src/com/fr/design/images/buttonicon/widgets.png -text +designer_base/src/com/fr/design/images/buttonicon/writeb24.png -text +designer_base/src/com/fr/design/images/buttonicon/writes.png -text +designer_base/src/com/fr/design/images/buttonicon/yes.png -text +designer_base/src/com/fr/design/images/calculate/average.png -text +designer_base/src/com/fr/design/images/calculate/count.png -text +designer_base/src/com/fr/design/images/calculate/max.png -text +designer_base/src/com/fr/design/images/calculate/min.png -text +designer_base/src/com/fr/design/images/calculate/none.png -text +designer_base/src/com/fr/design/images/calculate/sum.png -text +designer_base/src/com/fr/design/images/calender/month_add.png -text +designer_base/src/com/fr/design/images/calender/month_add_click.png -text +designer_base/src/com/fr/design/images/calender/month_add_hover.png -text +designer_base/src/com/fr/design/images/calender/month_reduce.png -text +designer_base/src/com/fr/design/images/calender/month_reduce_click.png -text +designer_base/src/com/fr/design/images/calender/month_reduce_hover.png -text +designer_base/src/com/fr/design/images/calender/year_add.png -text +designer_base/src/com/fr/design/images/calender/year_add_click.png -text +designer_base/src/com/fr/design/images/calender/year_add_hover.png -text +designer_base/src/com/fr/design/images/calender/year_reduce.png -text +designer_base/src/com/fr/design/images/calender/year_reduce_click.png -text +designer_base/src/com/fr/design/images/calender/year_reduce_hover.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/type/2.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/type/3.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/type/4.png -text +designer_base/src/com/fr/design/images/chart/AreaPlot/type/5.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/2.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/3.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/4.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/5.png -text +designer_base/src/com/fr/design/images/chart/BarPlot/type/6.png -text +designer_base/src/com/fr/design/images/chart/BubblePlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/BubblePlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/BubblePlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/BubblePlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/BubblePlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/ChangeChart.png -text +designer_base/src/com/fr/design/images/chart/ChartAxisLineStyle/cross.png -text +designer_base/src/com/fr/design/images/chart/ChartAxisLineStyle/external.png -text +designer_base/src/com/fr/design/images/chart/ChartAxisLineStyle/inside.png -text +designer_base/src/com/fr/design/images/chart/ChartData.png -text +designer_base/src/com/fr/design/images/chart/ChartLegend/layout_bottom.png -text +designer_base/src/com/fr/design/images/chart/ChartLegend/layout_left.png -text +designer_base/src/com/fr/design/images/chart/ChartLegend/layout_right.png -text +designer_base/src/com/fr/design/images/chart/ChartLegend/layout_top.png -text +designer_base/src/com/fr/design/images/chart/ChartLegend/layout_top_right.png -text +designer_base/src/com/fr/design/images/chart/ChartStyle.png -text +designer_base/src/com/fr/design/images/chart/ChartType.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/2.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/3.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/4.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/5.png -text +designer_base/src/com/fr/design/images/chart/ColumnPlot/type/6.png -text +designer_base/src/com/fr/design/images/chart/ConditionAttr.png -text +designer_base/src/com/fr/design/images/chart/CustomPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/CustomPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/CustomPlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/CustomPlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/CustomPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/DonutPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/DonutPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/DonutPlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/DonutPlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/DonutPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/DonutPlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/FunnelPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/GanttPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/GisMapPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/GisMapPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/GisMapPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/InterAttr.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/LinePlot/type/2.png -text +designer_base/src/com/fr/design/images/chart/MapPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/MapPlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/MapPlot/type/2.png -text +designer_base/src/com/fr/design/images/chart/MapPlot/type/3.png -text +designer_base/src/com/fr/design/images/chart/MeterPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/MeterPlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/MeterPlot/type/2.png -text +designer_base/src/com/fr/design/images/chart/PiePlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/PiePlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/PiePlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/PiePlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/PiePlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/PiePlot/type/1.png -text +designer_base/src/com/fr/design/images/chart/RadarPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/RangePlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/StockPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/0.png -text +designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/1.png -text +designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/2.png -text +designer_base/src/com/fr/design/images/chart/XYScatterPlot/layout/3.png -text +designer_base/src/com/fr/design/images/chart/XYScatterPlot/type/0.png -text +designer_base/src/com/fr/design/images/chart/default.png -text +designer_base/src/com/fr/design/images/chart/link.png -text +designer_base/src/com/fr/design/images/chart/moved.png -text +designer_base/src/com/fr/design/images/chart/normal.png -text +designer_base/src/com/fr/design/images/chart/pressed.png -text +designer_base/src/com/fr/design/images/condition/bracket.png -text +designer_base/src/com/fr/design/images/condition/unBracket.png -text +designer_base/src/com/fr/design/images/control/addPopup.png -text +designer_base/src/com/fr/design/images/control/arrow_down.png -text +designer_base/src/com/fr/design/images/control/bar.png -text +designer_base/src/com/fr/design/images/control/barl.png -text +designer_base/src/com/fr/design/images/control/barm.png -text +designer_base/src/com/fr/design/images/control/close.png -text +designer_base/src/com/fr/design/images/control/close_rollover.png -text +designer_base/src/com/fr/design/images/control/closet.png -text +designer_base/src/com/fr/design/images/control/control-center2.png -text +designer_base/src/com/fr/design/images/control/copy.png -text +designer_base/src/com/fr/design/images/control/dot.png -text +designer_base/src/com/fr/design/images/control/dotv.png -text +designer_base/src/com/fr/design/images/control/down.png -text +designer_base/src/com/fr/design/images/control/downdis.png -text +designer_base/src/com/fr/design/images/control/downnor.png -text +designer_base/src/com/fr/design/images/control/downpre.png -text +designer_base/src/com/fr/design/images/control/edit.png -text +designer_base/src/com/fr/design/images/control/left.png -text +designer_base/src/com/fr/design/images/control/leftleft.png -text +designer_base/src/com/fr/design/images/control/leftnor.png -text +designer_base/src/com/fr/design/images/control/leftpre.png -text +designer_base/src/com/fr/design/images/control/lock.png -text +designer_base/src/com/fr/design/images/control/more.png -text +designer_base/src/com/fr/design/images/control/refresh.png -text +designer_base/src/com/fr/design/images/control/remove.png -text +designer_base/src/com/fr/design/images/control/right.png -text +designer_base/src/com/fr/design/images/control/rightnor.png -text +designer_base/src/com/fr/design/images/control/rightpre.png -text +designer_base/src/com/fr/design/images/control/rightright.png -text +designer_base/src/com/fr/design/images/control/sortAsc.png -text +designer_base/src/com/fr/design/images/control/unlock.png -text +designer_base/src/com/fr/design/images/control/up.png -text +designer_base/src/com/fr/design/images/control/updis.png -text +designer_base/src/com/fr/design/images/control/upnor.png -text +designer_base/src/com/fr/design/images/control/uppre.png -text +designer_base/src/com/fr/design/images/control/warn.png -text +designer_base/src/com/fr/design/images/custombtn/baobiaozhuti.png -text +designer_base/src/com/fr/design/images/custombtn/baobiaozhuti_click.png -text +designer_base/src/com/fr/design/images/custombtn/baobiaozhuti_hover.png -text +designer_base/src/com/fr/design/images/custombtn/canshujiemian.png -text +designer_base/src/com/fr/design/images/custombtn/canshujiemian_click.png -text +designer_base/src/com/fr/design/images/custombtn/canshujiemian_hover.png -text +designer_base/src/com/fr/design/images/custombtn/edit.png -text +designer_base/src/com/fr/design/images/custombtn/edit_click.png -text +designer_base/src/com/fr/design/images/custombtn/edit_hover.png -text +designer_base/src/com/fr/design/images/custombtn/form.png -text +designer_base/src/com/fr/design/images/custombtn/form_click.png -text +designer_base/src/com/fr/design/images/custombtn/form_hover.png -text +designer_base/src/com/fr/design/images/custombtn/left.gif -text +designer_base/src/com/fr/design/images/custombtn/page.png -text +designer_base/src/com/fr/design/images/custombtn/page_click.png -text +designer_base/src/com/fr/design/images/custombtn/page_hover.png -text +designer_base/src/com/fr/design/images/custombtn/preview.png -text +designer_base/src/com/fr/design/images/custombtn/preview_click.png -text +designer_base/src/com/fr/design/images/custombtn/preview_hover.png -text +designer_base/src/com/fr/design/images/custombtn/right.gif -text +designer_base/src/com/fr/design/images/custombtn/setting.png -text +designer_base/src/com/fr/design/images/custombtn/setting_click.png -text +designer_base/src/com/fr/design/images/custombtn/setting_hover.png -text +designer_base/src/com/fr/design/images/dashboard/chart.png -text +designer_base/src/com/fr/design/images/dashboard/files.png -text +designer_base/src/com/fr/design/images/dashboard/form.png -text +designer_base/src/com/fr/design/images/dashboard/guide.png -text +designer_base/src/com/fr/design/images/dashboard/img/0.gif -text +designer_base/src/com/fr/design/images/dashboard/img/1.gif -text +designer_base/src/com/fr/design/images/dashboard/img/1.png -text +designer_base/src/com/fr/design/images/dashboard/img/10.gif -text +designer_base/src/com/fr/design/images/dashboard/img/10.png -text +designer_base/src/com/fr/design/images/dashboard/img/11.gif -text +designer_base/src/com/fr/design/images/dashboard/img/11.png -text +designer_base/src/com/fr/design/images/dashboard/img/12.gif -text +designer_base/src/com/fr/design/images/dashboard/img/12.png -text +designer_base/src/com/fr/design/images/dashboard/img/13.gif -text +designer_base/src/com/fr/design/images/dashboard/img/13.png -text +designer_base/src/com/fr/design/images/dashboard/img/14.gif -text +designer_base/src/com/fr/design/images/dashboard/img/14.png -text +designer_base/src/com/fr/design/images/dashboard/img/15.gif -text +designer_base/src/com/fr/design/images/dashboard/img/15.png -text +designer_base/src/com/fr/design/images/dashboard/img/16.gif -text +designer_base/src/com/fr/design/images/dashboard/img/16.png -text +designer_base/src/com/fr/design/images/dashboard/img/17.gif -text +designer_base/src/com/fr/design/images/dashboard/img/17.png -text +designer_base/src/com/fr/design/images/dashboard/img/18.gif -text +designer_base/src/com/fr/design/images/dashboard/img/18.png -text +designer_base/src/com/fr/design/images/dashboard/img/19.gif -text +designer_base/src/com/fr/design/images/dashboard/img/19.png -text +designer_base/src/com/fr/design/images/dashboard/img/2.gif -text +designer_base/src/com/fr/design/images/dashboard/img/2.png -text +designer_base/src/com/fr/design/images/dashboard/img/20.png -text +designer_base/src/com/fr/design/images/dashboard/img/21.png -text +designer_base/src/com/fr/design/images/dashboard/img/22.png -text +designer_base/src/com/fr/design/images/dashboard/img/23.png -text +designer_base/src/com/fr/design/images/dashboard/img/24.png -text +designer_base/src/com/fr/design/images/dashboard/img/25.png -text +designer_base/src/com/fr/design/images/dashboard/img/26.png -text +designer_base/src/com/fr/design/images/dashboard/img/27.png -text +designer_base/src/com/fr/design/images/dashboard/img/28.png -text +designer_base/src/com/fr/design/images/dashboard/img/29.png -text +designer_base/src/com/fr/design/images/dashboard/img/3.gif -text +designer_base/src/com/fr/design/images/dashboard/img/3.png -text +designer_base/src/com/fr/design/images/dashboard/img/30.png -text +designer_base/src/com/fr/design/images/dashboard/img/31.png -text +designer_base/src/com/fr/design/images/dashboard/img/32.png -text +designer_base/src/com/fr/design/images/dashboard/img/33.png -text +designer_base/src/com/fr/design/images/dashboard/img/34.png -text +designer_base/src/com/fr/design/images/dashboard/img/35.png -text +designer_base/src/com/fr/design/images/dashboard/img/36.png -text +designer_base/src/com/fr/design/images/dashboard/img/37.png -text +designer_base/src/com/fr/design/images/dashboard/img/38.png -text +designer_base/src/com/fr/design/images/dashboard/img/39.png -text +designer_base/src/com/fr/design/images/dashboard/img/4.gif -text +designer_base/src/com/fr/design/images/dashboard/img/4.png -text +designer_base/src/com/fr/design/images/dashboard/img/40.png -text +designer_base/src/com/fr/design/images/dashboard/img/41.png -text +designer_base/src/com/fr/design/images/dashboard/img/42.png -text +designer_base/src/com/fr/design/images/dashboard/img/43.png -text +designer_base/src/com/fr/design/images/dashboard/img/44.png -text +designer_base/src/com/fr/design/images/dashboard/img/45.png -text +designer_base/src/com/fr/design/images/dashboard/img/46.png -text +designer_base/src/com/fr/design/images/dashboard/img/47.png -text +designer_base/src/com/fr/design/images/dashboard/img/48.png -text +designer_base/src/com/fr/design/images/dashboard/img/49.png -text +designer_base/src/com/fr/design/images/dashboard/img/5.gif -text +designer_base/src/com/fr/design/images/dashboard/img/5.png -text +designer_base/src/com/fr/design/images/dashboard/img/50.png -text +designer_base/src/com/fr/design/images/dashboard/img/52.png -text +designer_base/src/com/fr/design/images/dashboard/img/54.png -text +designer_base/src/com/fr/design/images/dashboard/img/55.png -text +designer_base/src/com/fr/design/images/dashboard/img/56.png -text +designer_base/src/com/fr/design/images/dashboard/img/57.png -text +designer_base/src/com/fr/design/images/dashboard/img/6.gif -text +designer_base/src/com/fr/design/images/dashboard/img/6.png -text +designer_base/src/com/fr/design/images/dashboard/img/7.gif -text +designer_base/src/com/fr/design/images/dashboard/img/7.png -text +designer_base/src/com/fr/design/images/dashboard/img/8.gif -text +designer_base/src/com/fr/design/images/dashboard/img/8.png -text +designer_base/src/com/fr/design/images/dashboard/img/9.gif -text +designer_base/src/com/fr/design/images/dashboard/img/9.png -text +designer_base/src/com/fr/design/images/dashboard/img/Thumbs.db -text +designer_base/src/com/fr/design/images/data/arrow_branch.png -text +designer_base/src/com/fr/design/images/data/bind/add.png -text +designer_base/src/com/fr/design/images/data/bind/distanceconnect.png -text +designer_base/src/com/fr/design/images/data/bind/groupAscColumn.png -text +designer_base/src/com/fr/design/images/data/bind/groupColumn.png -text +designer_base/src/com/fr/design/images/data/bind/groupDescColumn.png -text +designer_base/src/com/fr/design/images/data/bind/localconnect.png -text +designer_base/src/com/fr/design/images/data/bind/modify.png -text +designer_base/src/com/fr/design/images/data/bind/normalColumn.png -text +designer_base/src/com/fr/design/images/data/bind/selectColumn.png -text +designer_base/src/com/fr/design/images/data/bind/sortAscColumn.png -text +designer_base/src/com/fr/design/images/data/bind/sortColumn.png -text +designer_base/src/com/fr/design/images/data/bind/sortDescColumn.png -text +designer_base/src/com/fr/design/images/data/bind/summaryColumn.png -text +designer_base/src/com/fr/design/images/data/comb_widget.png -text +designer_base/src/com/fr/design/images/data/convertEmbedded.png -text +designer_base/src/com/fr/design/images/data/cube.png -text +designer_base/src/com/fr/design/images/data/custom_widget.png -text +designer_base/src/com/fr/design/images/data/dataDictionary.png -text +designer_base/src/com/fr/design/images/data/dataTable.png -text +designer_base/src/com/fr/design/images/data/database.png -text +designer_base/src/com/fr/design/images/data/datakubiao.png -text +designer_base/src/com/fr/design/images/data/datasource.png -text +designer_base/src/com/fr/design/images/data/default_widget.png -text +designer_base/src/com/fr/design/images/data/diy.png -text +designer_base/src/com/fr/design/images/data/dock/XML.png -text +designer_base/src/com/fr/design/images/data/dock/classTableData.png -text +designer_base/src/com/fr/design/images/data/dock/dataTable.png -text +designer_base/src/com/fr/design/images/data/dock/database.png -text +designer_base/src/com/fr/design/images/data/dock/excel.png -text +designer_base/src/com/fr/design/images/data/dock/relation_table_data.png -text +designer_base/src/com/fr/design/images/data/dock/serverclasstabledata.png -text +designer_base/src/com/fr/design/images/data/dock/serverdatabase.png -text +designer_base/src/com/fr/design/images/data/dock/serverdatatable.png -text +designer_base/src/com/fr/design/images/data/dock/table_proc.png -text +designer_base/src/com/fr/design/images/data/dock/table_text.png -text +designer_base/src/com/fr/design/images/data/editQuery.png -text +designer_base/src/com/fr/design/images/data/field.png -text +designer_base/src/com/fr/design/images/data/file.png -text +designer_base/src/com/fr/design/images/data/multi.png -text +designer_base/src/com/fr/design/images/data/newQuery.png -text +designer_base/src/com/fr/design/images/data/private.png -text +designer_base/src/com/fr/design/images/data/public.png -text +designer_base/src/com/fr/design/images/data/sap.png -text +designer_base/src/com/fr/design/images/data/search.png -text +designer_base/src/com/fr/design/images/data/source/classTableData.png -text +designer_base/src/com/fr/design/images/data/source/clear.png -text +designer_base/src/com/fr/design/images/data/source/dataDictionary.png -text +designer_base/src/com/fr/design/images/data/source/delete.png -text +designer_base/src/com/fr/design/images/data/source/hibernateTableData.png -text +designer_base/src/com/fr/design/images/data/source/jdbcDataquery.png -text +designer_base/src/com/fr/design/images/data/source/jdbcTableData.png -text +designer_base/src/com/fr/design/images/data/source/moveDown.png -text +designer_base/src/com/fr/design/images/data/source/moveUp.png -text +designer_base/src/com/fr/design/images/data/source/newDatabase.png -text +designer_base/src/com/fr/design/images/data/source/newDatasource.png -text +designer_base/src/com/fr/design/images/data/source/rename.png -text +designer_base/src/com/fr/design/images/data/source/schema.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/Thumbs.db -text +designer_base/src/com/fr/design/images/data/source/selectwizard/accept.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/bullet_key.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/bullet_pink.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/cart_add.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/cart_delete.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/chart_organisation.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database_connect.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database_gear.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database_lightning.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database_save.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database_table.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/database_tables.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/filter.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/folder_database.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/folder_page.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/folder_table.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/page_edit.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/page_gear.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/page_save.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/page_white_database.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_error.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_gear.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_link.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_multiple.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_relationship.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_row_delete.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_row_insert.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/table_sort.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/textfield.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/wizard.png -text +designer_base/src/com/fr/design/images/data/source/selectwizard/wrench.png -text +designer_base/src/com/fr/design/images/data/source/sqlAscColumn.png -text +designer_base/src/com/fr/design/images/data/source/sqlColumn.png -text +designer_base/src/com/fr/design/images/data/source/sqlConditionColumn.png -text +designer_base/src/com/fr/design/images/data/source/sqlDescColumn.png -text +designer_base/src/com/fr/design/images/data/source/sqlTable.png -text +designer_base/src/com/fr/design/images/data/source/sqlViewTable.png -text +designer_base/src/com/fr/design/images/data/source/table.png -text +designer_base/src/com/fr/design/images/data/source/textDatasource.png -text +designer_base/src/com/fr/design/images/data/source/view.png -text +designer_base/src/com/fr/design/images/data/store_procedure.png -text +designer_base/src/com/fr/design/images/data/string.png -text +designer_base/src/com/fr/design/images/data/table.png -text +designer_base/src/com/fr/design/images/data/table2.png -text +designer_base/src/com/fr/design/images/data/tables.png -text +designer_base/src/com/fr/design/images/data/text.png -text +designer_base/src/com/fr/design/images/data/today.gif -text +designer_base/src/com/fr/design/images/data/tree.png -text +designer_base/src/com/fr/design/images/data/user_widget.png -text +designer_base/src/com/fr/design/images/data/views.png -text +designer_base/src/com/fr/design/images/data/xml.png -text +designer_base/src/com/fr/design/images/dialog/column.png -text +designer_base/src/com/fr/design/images/dialog/function.gif -text +designer_base/src/com/fr/design/images/dialog/parameter.gif -text +designer_base/src/com/fr/design/images/dialog/table.png -text +designer_base/src/com/fr/design/images/dialog/variable.png -text +designer_base/src/com/fr/design/images/dock/desktop.png -text +designer_base/src/com/fr/design/images/dock/project.png -text +designer_base/src/com/fr/design/images/dock/projectVer.png -text +designer_base/src/com/fr/design/images/dock/properties.png -text +designer_base/src/com/fr/design/images/docking/close.gif -text +designer_base/src/com/fr/design/images/docking/down.gif -text +designer_base/src/com/fr/design/images/docking/left.gif -text +designer_base/src/com/fr/design/images/docking/left.png -text +designer_base/src/com/fr/design/images/docking/right.gif -text +designer_base/src/com/fr/design/images/docking/right.png -text +designer_base/src/com/fr/design/images/docking/up.gif -text +designer_base/src/com/fr/design/images/edit/deleteRow.png -text +designer_base/src/com/fr/design/images/edit/insertRow_B.png -text +designer_base/src/com/fr/design/images/expand/asc.png -text +designer_base/src/com/fr/design/images/expand/cellAttr.gif -text +designer_base/src/com/fr/design/images/expand/des.png -text +designer_base/src/com/fr/design/images/expand/landspace.png -text +designer_base/src/com/fr/design/images/expand/none16x16.png -text +designer_base/src/com/fr/design/images/expand/vertical.png -text +designer_base/src/com/fr/design/images/file/disk.gif -text +designer_base/src/com/fr/design/images/file/disk.png -text +designer_base/src/com/fr/design/images/file/fold.png -text +designer_base/src/com/fr/design/images/file/folder.gif -text +designer_base/src/com/fr/design/images/file/gifFile.gif -text +designer_base/src/com/fr/design/images/file/jpgFile.gif -text +designer_base/src/com/fr/design/images/file/newfolder.png -text +designer_base/src/com/fr/design/images/file/nostar.png -text +designer_base/src/com/fr/design/images/file/pngFile.png -text +designer_base/src/com/fr/design/images/file/star.png -text +designer_base/src/com/fr/design/images/form/Button.gif -text +designer_base/src/com/fr/design/images/form/CheckBox.gif -text +designer_base/src/com/fr/design/images/form/Choice.gif -text +designer_base/src/com/fr/design/images/form/List.gif -text +designer_base/src/com/fr/design/images/form/RadioButton.gif -text +designer_base/src/com/fr/design/images/form/TextField.gif -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_border.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_border_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_left.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_left_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_right.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/bottom_right_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_close.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_close_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_max.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_max_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_min.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/control_min_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/controls.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/controls_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/left_border.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/left_border_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/right_border.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/right_border_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/title_pane.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_border.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_border_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_left.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_left_.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_right.png -text +designer_base/src/com/fr/design/images/form/designer/beans/adapters/container/top_right_.png -text +designer_base/src/com/fr/design/images/form/designer/bottom_align.png -text +designer_base/src/com/fr/design/images/form/designer/center_align.png -text +designer_base/src/com/fr/design/images/form/designer/cursor/add.png -text +designer_base/src/com/fr/design/images/form/designer/cursor/connectorcursor.png -text +designer_base/src/com/fr/design/images/form/designer/cursor/move.png -text +designer_base/src/com/fr/design/images/form/designer/drop_down.png -text +designer_base/src/com/fr/design/images/form/designer/drop_over.png -text +designer_base/src/com/fr/design/images/form/designer/drop_up.png -text +designer_base/src/com/fr/design/images/form/designer/holder.png -text +designer_base/src/com/fr/design/images/form/designer/left_align.png -text +designer_base/src/com/fr/design/images/form/designer/middle_align.png -text +designer_base/src/com/fr/design/images/form/designer/properties/minus.png -text +designer_base/src/com/fr/design/images/form/designer/properties/plus.png -text +designer_base/src/com/fr/design/images/form/designer/right_align.png -text +designer_base/src/com/fr/design/images/form/designer/same_height.png -text +designer_base/src/com/fr/design/images/form/designer/same_width.png -text +designer_base/src/com/fr/design/images/form/designer/top_align.png -text +designer_base/src/com/fr/design/images/form/hover.png -text +designer_base/src/com/fr/design/images/form/parameter.png -text +designer_base/src/com/fr/design/images/form/toolbar/Chart-Map.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Area.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Bar.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Column.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Comb_Chart.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Donut.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Funnel.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Gantt.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Gis.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Line.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Meter.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Pie.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Radar.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Range_Chart.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-Stock.png -text +designer_base/src/com/fr/design/images/form/toolbar/ChartF-XYScatter.png -text +designer_base/src/com/fr/design/images/form/toolbar/Chart_BubbleChart.png -text +designer_base/src/com/fr/design/images/form/toolbar/FR-Chart-Chart_BubbleChart.png -text +designer_base/src/com/fr/design/images/form/toolbar/default.png -text +designer_base/src/com/fr/design/images/form/toolbar/ec_columns.png -text +designer_base/src/com/fr/design/images/form/toolbar/ec_frozen.png -text +designer_base/src/com/fr/design/images/gc.png -text +designer_base/src/com/fr/design/images/general/close-rolver.png -text +designer_base/src/com/fr/design/images/general/close.png -text +designer_base/src/com/fr/design/images/general/mini-rolver.png -text +designer_base/src/com/fr/design/images/general/mini.png -text +designer_base/src/com/fr/design/images/general/resize-rolver.png -text +designer_base/src/com/fr/design/images/general/resize.png -text +designer_base/src/com/fr/design/images/gui/blank.gif -text +designer_base/src/com/fr/design/images/gui/bmpFile.gif -text +designer_base/src/com/fr/design/images/gui/cell.gif -text +designer_base/src/com/fr/design/images/gui/cht.png -text +designer_base/src/com/fr/design/images/gui/chtlocked.png -text +designer_base/src/com/fr/design/images/gui/classFile.gif -text +designer_base/src/com/fr/design/images/gui/close.png -text +designer_base/src/com/fr/design/images/gui/color/background.png -text +designer_base/src/com/fr/design/images/gui/color/foreground.png -text +designer_base/src/com/fr/design/images/gui/cptFile.png -text +designer_base/src/com/fr/design/images/gui/documentFolderClose.gif -text +designer_base/src/com/fr/design/images/gui/folder.gif -text +designer_base/src/com/fr/design/images/gui/folder.png -text +designer_base/src/com/fr/design/images/gui/folder/expanded.png -text +designer_base/src/com/fr/design/images/gui/folder/foldered.png -text +designer_base/src/com/fr/design/images/gui/folder/hovered_expanded.png -text +designer_base/src/com/fr/design/images/gui/folder/hovered_foldered.png -text +designer_base/src/com/fr/design/images/gui/frm.png -text +designer_base/src/com/fr/design/images/gui/frmlocked.png -text +designer_base/src/com/fr/design/images/gui/gifFile.gif -text +designer_base/src/com/fr/design/images/gui/htmlFile.gif -text +designer_base/src/com/fr/design/images/gui/jarFile.gif -text +designer_base/src/com/fr/design/images/gui/javaFile.gif -text +designer_base/src/com/fr/design/images/gui/jpgFile.gif -text +designer_base/src/com/fr/design/images/gui/jsFile.gif -text +designer_base/src/com/fr/design/images/gui/jspFile.gif -text +designer_base/src/com/fr/design/images/gui/locked.gif -text +designer_base/src/com/fr/design/images/gui/minimize.gif -text +designer_base/src/com/fr/design/images/gui/pngFile.png -text +designer_base/src/com/fr/design/images/gui/popup.gif -text +designer_base/src/com/fr/design/images/gui/popupCenter.png -text +designer_base/src/com/fr/design/images/gui/popupLarge.gif -text +designer_base/src/com/fr/design/images/gui/tab_add_click.png -text +designer_base/src/com/fr/design/images/gui/tab_add_hover.png -text +designer_base/src/com/fr/design/images/gui/tab_add_normal.png -text +designer_base/src/com/fr/design/images/gui/tab_delete.png -text +designer_base/src/com/fr/design/images/gui/textFile.png -text +designer_base/src/com/fr/design/images/gui/warning.png -text +designer_base/src/com/fr/design/images/gui/xmlFile.gif -text +designer_base/src/com/fr/design/images/load/busy-icon0.png -text +designer_base/src/com/fr/design/images/load/busy-icon1.png -text +designer_base/src/com/fr/design/images/load/busy-icon10.png -text +designer_base/src/com/fr/design/images/load/busy-icon11.png -text +designer_base/src/com/fr/design/images/load/busy-icon12.png -text +designer_base/src/com/fr/design/images/load/busy-icon13.png -text +designer_base/src/com/fr/design/images/load/busy-icon14.png -text +designer_base/src/com/fr/design/images/load/busy-icon2.png -text +designer_base/src/com/fr/design/images/load/busy-icon3.png -text +designer_base/src/com/fr/design/images/load/busy-icon4.png -text +designer_base/src/com/fr/design/images/load/busy-icon5.png -text +designer_base/src/com/fr/design/images/load/busy-icon6.png -text +designer_base/src/com/fr/design/images/load/busy-icon7.png -text +designer_base/src/com/fr/design/images/load/busy-icon8.png -text +designer_base/src/com/fr/design/images/load/busy-icon9.png -text +designer_base/src/com/fr/design/images/log/clear.png -text +designer_base/src/com/fr/design/images/log/selectedall.png -text +designer_base/src/com/fr/design/images/log/setting.png -text +designer_base/src/com/fr/design/images/lookandfeel/ComboBoxFocus.png -text +designer_base/src/com/fr/design/images/lookandfeel/ComputerIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/DirectoryIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/ErrorIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/FileDetailsIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/FileIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/FileListIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/FloppyIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/HarddiskIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/HomeFolderIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/InformationIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/InternalFrameIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/NewFolderIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/ParentDirectoryIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/QuestionIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/TreeFolderClosedIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/TreeFolderOpenedIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/TreeLeafIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/TreeMinusIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/TreePlusIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/WarningIcon.png -text +designer_base/src/com/fr/design/images/lookandfeel/brightmask.png -text +designer_base/src/com/fr/design/images/m_edit/bringForward.png -text +designer_base/src/com/fr/design/images/m_edit/bringToFront.png -text +designer_base/src/com/fr/design/images/m_edit/copy.png -text +designer_base/src/com/fr/design/images/m_edit/cut.png -text +designer_base/src/com/fr/design/images/m_edit/directShare.png -text +designer_base/src/com/fr/design/images/m_edit/formatBrush.png -text +designer_base/src/com/fr/design/images/m_edit/merge.png -text +designer_base/src/com/fr/design/images/m_edit/modifyShare.png -text +designer_base/src/com/fr/design/images/m_edit/paste.png -text +designer_base/src/com/fr/design/images/m_edit/pluralundo.png -text +designer_base/src/com/fr/design/images/m_edit/redo.png -text +designer_base/src/com/fr/design/images/m_edit/sendBackward.png -text +designer_base/src/com/fr/design/images/m_edit/sendToBack.png -text +designer_base/src/com/fr/design/images/m_edit/share.png -text +designer_base/src/com/fr/design/images/m_edit/undo.png -text +designer_base/src/com/fr/design/images/m_edit/unmerge.png -text +designer_base/src/com/fr/design/images/m_file/close.png -text +designer_base/src/com/fr/design/images/m_file/crossTable.png -text +designer_base/src/com/fr/design/images/m_file/csv.png -text +designer_base/src/com/fr/design/images/m_file/design.png -text +designer_base/src/com/fr/design/images/m_file/design_large.png -text +designer_base/src/com/fr/design/images/m_file/edit.png -text +designer_base/src/com/fr/design/images/m_file/excel.png -text +designer_base/src/com/fr/design/images/m_file/export.png -text +designer_base/src/com/fr/design/images/m_file/formExport.png -text +designer_base/src/com/fr/design/images/m_file/groupTable.png -text +designer_base/src/com/fr/design/images/m_file/help.png -text +designer_base/src/com/fr/design/images/m_file/html.png -text +designer_base/src/com/fr/design/images/m_file/hyperLink.png -text +designer_base/src/com/fr/design/images/m_file/import.png -text +designer_base/src/com/fr/design/images/m_file/merge.png -text +designer_base/src/com/fr/design/images/m_file/new.png -text +designer_base/src/com/fr/design/images/m_file/open.png -text +designer_base/src/com/fr/design/images/m_file/pageSetup.png -text +designer_base/src/com/fr/design/images/m_file/pdf.png -text +designer_base/src/com/fr/design/images/m_file/preview.png -text +designer_base/src/com/fr/design/images/m_file/print.png -text +designer_base/src/com/fr/design/images/m_file/save.png -text +designer_base/src/com/fr/design/images/m_file/saveAs.png -text +designer_base/src/com/fr/design/images/m_file/svg.png -text +designer_base/src/com/fr/design/images/m_file/switch.png -text +designer_base/src/com/fr/design/images/m_file/text.png -text +designer_base/src/com/fr/design/images/m_file/view_folder.png -text +designer_base/src/com/fr/design/images/m_file/web.png -text +designer_base/src/com/fr/design/images/m_file/word.png -text +designer_base/src/com/fr/design/images/m_format/allborders.png -text +designer_base/src/com/fr/design/images/m_format/border.png -text +designer_base/src/com/fr/design/images/m_format/bottom.png -text +designer_base/src/com/fr/design/images/m_format/cell.png -text +designer_base/src/com/fr/design/images/m_format/cellAttr.png -text +designer_base/src/com/fr/design/images/m_format/cellWriteAttr.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/bold.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/centerAlignment.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/default.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/defaultAlignment.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/generalAlignment.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_center_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_center_pressed.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_left_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_left_pressed.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_right_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_right_pressed.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_s_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/h_s_pressed.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/italic.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/leftAlignment.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/otherset.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/rightAlignment.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/shadow.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/strikethrough.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/sub.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/sup.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/underline.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/v_center_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/v_center_pressed.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/v_down_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/v_down_pressed.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/v_top_normal.png -text +designer_base/src/com/fr/design/images/m_format/cellstyle/v_top_pressed.png -text +designer_base/src/com/fr/design/images/m_format/doublebottom.png -text +designer_base/src/com/fr/design/images/m_format/editChart.png -text +designer_base/src/com/fr/design/images/m_format/highlight.png -text +designer_base/src/com/fr/design/images/m_format/in.png -text +designer_base/src/com/fr/design/images/m_format/left.png -text +designer_base/src/com/fr/design/images/m_format/modified.png -text +designer_base/src/com/fr/design/images/m_format/noboder.png -text +designer_base/src/com/fr/design/images/m_format/note.png -text +designer_base/src/com/fr/design/images/m_format/out.png -text +designer_base/src/com/fr/design/images/m_format/outsideborders.png -text +designer_base/src/com/fr/design/images/m_format/right.png -text +designer_base/src/com/fr/design/images/m_format/shape.png -text +designer_base/src/com/fr/design/images/m_format/thickbottom.png -text +designer_base/src/com/fr/design/images/m_format/thickoutsideborders.png -text +designer_base/src/com/fr/design/images/m_format/topanddoublebotttom.png -text +designer_base/src/com/fr/design/images/m_format/topandthickbottom.png -text +designer_base/src/com/fr/design/images/m_format/topbottom.png -text +designer_base/src/com/fr/design/images/m_help/back.png -text +designer_base/src/com/fr/design/images/m_help/demo.png -text +designer_base/src/com/fr/design/images/m_help/feedback.png -text +designer_base/src/com/fr/design/images/m_help/forum.png -text +designer_base/src/com/fr/design/images/m_help/forward.png -text +designer_base/src/com/fr/design/images/m_help/help.png -text +designer_base/src/com/fr/design/images/m_help/preview_analy.png -text +designer_base/src/com/fr/design/images/m_help/preview_form.png -text +designer_base/src/com/fr/design/images/m_help/preview_page.png -text +designer_base/src/com/fr/design/images/m_help/preview_write.png -text +designer_base/src/com/fr/design/images/m_help/product_forum.png -text +designer_base/src/com/fr/design/images/m_help/support_qq.png -text +designer_base/src/com/fr/design/images/m_insert/Pivottable.gif -text +designer_base/src/com/fr/design/images/m_insert/account.png -text +designer_base/src/com/fr/design/images/m_insert/accountTitle.png -text +designer_base/src/com/fr/design/images/m_insert/barcode.png -text +designer_base/src/com/fr/design/images/m_insert/bias.png -text +designer_base/src/com/fr/design/images/m_insert/bindCell.png -text +designer_base/src/com/fr/design/images/m_insert/bindColumn.png -text +designer_base/src/com/fr/design/images/m_insert/blank.gif -text +designer_base/src/com/fr/design/images/m_insert/boolean.png -text +designer_base/src/com/fr/design/images/m_insert/cell.png -text +designer_base/src/com/fr/design/images/m_insert/cellPop.png -text +designer_base/src/com/fr/design/images/m_insert/chart.png -text +designer_base/src/com/fr/design/images/m_insert/composite.png -text +designer_base/src/com/fr/design/images/m_insert/compositePop.png -text +designer_base/src/com/fr/design/images/m_insert/crossTable.png -text +designer_base/src/com/fr/design/images/m_insert/date.png -text +designer_base/src/com/fr/design/images/m_insert/default.png -text +designer_base/src/com/fr/design/images/m_insert/expandCell.gif -text +designer_base/src/com/fr/design/images/m_insert/float.png -text +designer_base/src/com/fr/design/images/m_insert/floatPop.png -text +designer_base/src/com/fr/design/images/m_insert/formula.png -text +designer_base/src/com/fr/design/images/m_insert/groupTable.png -text +designer_base/src/com/fr/design/images/m_insert/hyperLink.png -text +designer_base/src/com/fr/design/images/m_insert/image.png -text +designer_base/src/com/fr/design/images/m_insert/insertColumn.png -text +designer_base/src/com/fr/design/images/m_insert/insertRow.png -text +designer_base/src/com/fr/design/images/m_insert/newchart.png -text +designer_base/src/com/fr/design/images/m_insert/richtext.png -text +designer_base/src/com/fr/design/images/m_insert/shape.png -text +designer_base/src/com/fr/design/images/m_insert/shape_issosceles_triangle.png -text +designer_base/src/com/fr/design/images/m_insert/shape_line.png -text +designer_base/src/com/fr/design/images/m_insert/shape_oval.png -text +designer_base/src/com/fr/design/images/m_insert/shape_rectangle.png -text +designer_base/src/com/fr/design/images/m_insert/shape_rounded_rectangle.png -text +designer_base/src/com/fr/design/images/m_insert/subReport.png -text +designer_base/src/com/fr/design/images/m_insert/text.png -text +designer_base/src/com/fr/design/images/m_insert/textBox.png -text +designer_base/src/com/fr/design/images/m_report/allow_authority_edit.png -text +designer_base/src/com/fr/design/images/m_report/attributes.png -text +designer_base/src/com/fr/design/images/m_report/background.png -text +designer_base/src/com/fr/design/images/m_report/bindData.png -text +designer_base/src/com/fr/design/images/m_report/close.png -text +designer_base/src/com/fr/design/images/m_report/close_over.png -text +designer_base/src/com/fr/design/images/m_report/close_press.png -text +designer_base/src/com/fr/design/images/m_report/delete.png -text +designer_base/src/com/fr/design/images/m_report/deleteColumn.png -text +designer_base/src/com/fr/design/images/m_report/deleteRow.png -text +designer_base/src/com/fr/design/images/m_report/exit_authority_edit.png -text +designer_base/src/com/fr/design/images/m_report/exportAttr.png -text +designer_base/src/com/fr/design/images/m_report/footer.png -text +designer_base/src/com/fr/design/images/m_report/header.png -text +designer_base/src/com/fr/design/images/m_report/linearAttr.png -text +designer_base/src/com/fr/design/images/m_report/p.gif -text +designer_base/src/com/fr/design/images/m_report/p.png -text +designer_base/src/com/fr/design/images/m_report/parameter.png -text +designer_base/src/com/fr/design/images/m_report/process.gif -text +designer_base/src/com/fr/design/images/m_report/qb.png -text +designer_base/src/com/fr/design/images/m_report/reportEngineAttr.png -text +designer_base/src/com/fr/design/images/m_report/reportWorkFlowAttr.png -text +designer_base/src/com/fr/design/images/m_report/reportWriteAttr.png -text +designer_base/src/com/fr/design/images/m_report/tree.png -text +designer_base/src/com/fr/design/images/m_report/webreportattribute.png -text +designer_base/src/com/fr/design/images/m_web/cache.png -text +designer_base/src/com/fr/design/images/m_web/connection.png -text +designer_base/src/com/fr/design/images/m_web/datasource.png -text +designer_base/src/com/fr/design/images/m_web/edit.png -text +designer_base/src/com/fr/design/images/m_web/face.gif -text +designer_base/src/com/fr/design/images/m_web/formula.png -text +designer_base/src/com/fr/design/images/m_web/function.png -text +designer_base/src/com/fr/design/images/m_web/log.png -text +designer_base/src/com/fr/design/images/m_web/privilegeManager.gif -text +designer_base/src/com/fr/design/images/m_web/reportletdemo.png -text +designer_base/src/com/fr/design/images/m_web/schedule.png -text +designer_base/src/com/fr/design/images/m_web/server.png -text +designer_base/src/com/fr/design/images/m_web/style.png -text +designer_base/src/com/fr/design/images/m_web/sync.png -text +designer_base/src/com/fr/design/images/m_window/cascade.png -text +designer_base/src/com/fr/design/images/m_window/formdesign.png -text +designer_base/src/com/fr/design/images/m_window/frozen.png -text +designer_base/src/com/fr/design/images/m_window/generaldesign.png -text +designer_base/src/com/fr/design/images/m_window/next.png -text +designer_base/src/com/fr/design/images/m_window/previous.png -text +designer_base/src/com/fr/design/images/m_window/title_hor.png -text +designer_base/src/com/fr/design/images/m_window/title_ver.png -text +designer_base/src/com/fr/design/images/mainframe/attribute.png -text +designer_base/src/com/fr/design/images/mainframe/class.png -text +designer_base/src/com/fr/design/images/mainframe/datasource.png -text +designer_base/src/com/fr/design/images/mainframe/fpt.png -text +designer_base/src/com/fr/design/images/mainframe/jar.png -text +designer_base/src/com/fr/design/images/mainframe/java.png -text +designer_base/src/com/fr/design/images/mainframe/server.png -text +designer_base/src/com/fr/design/images/mainframe/xml.png -text +designer_base/src/com/fr/design/images/minimize.gif -text +designer_base/src/com/fr/design/images/parameter.png -text +designer_base/src/com/fr/design/images/poly/Chart-Map/Chart-Map-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-4.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Area/ChartF-Area-5.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-4.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-5.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Bar/ChartF-Bar-6.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-4.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-5.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Column/ChartF-Column-6.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Comb_Chart/ChartF-Comb_Chart-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Comb_Chart/ChartF-Comb_Chart-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Donut/ChartF-Donut-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Donut/ChartF-Donut-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Gantt/ChartF-Gantt-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Gis/ChartF-Gis-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-4.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Line/ChartF-Line-5.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Meter/ChartF-Meter-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Meter/ChartF-Meter-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-4.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Pie/ChartF-Pie-5.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Radar/ChartF-Radar-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Range_Chart/ChartF-Range_Chart-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-2.png -text +designer_base/src/com/fr/design/images/poly/ChartF-Stock/ChartF-Stock-3.png -text +designer_base/src/com/fr/design/images/poly/ChartF-XYScatter/ChartF-XYScatter-0.png -text +designer_base/src/com/fr/design/images/poly/ChartF-XYScatter/ChartF-XYScatter-1.png -text +designer_base/src/com/fr/design/images/poly/ChartF-XYScatter/ChartF-XYScatter-2.png -text +designer_base/src/com/fr/design/images/poly/Chart_BubbleChart/Chart_BubbleChart-0.png -text +designer_base/src/com/fr/design/images/poly/Chart_BubbleChart/FR-Chart-Chart_BubbleChart-0.png -text +designer_base/src/com/fr/design/images/poly/normal.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Chart-Map.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Chart-SVG_MAP.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Area.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Bar.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Column.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Comb_Chart.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Donut.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Funnel.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Gantt.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Gis.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Line.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Meter.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Pie.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Radar.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Range_Chart.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-Stock.png -text +designer_base/src/com/fr/design/images/poly/toolbar/ChartF-XYScatter.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Chart_BubbleChart.png -text +designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart-Bit_Map.png -text +designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart-Chart_BubbleChart.png -text +designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart-ThreeD_Custom_Chart.png -text +designer_base/src/com/fr/design/images/poly/toolbar/FR-Chart_Bit_Map.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewArea.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewBar.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewColumn.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewLine.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_NewPie.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Plugin-ChartF_VerticalLine.png -text +designer_base/src/com/fr/design/images/poly/toolbar/Poly-Report_Block.png -text +designer_base/src/com/fr/design/images/report/form.png -text +designer_base/src/com/fr/design/images/report/groupReport.png -text +designer_base/src/com/fr/design/images/report/position.png -text +designer_base/src/com/fr/design/images/reportcolumns/col.png -text +designer_base/src/com/fr/design/images/reportcolumns/row.png -text +designer_base/src/com/fr/design/images/server/change.png -text +designer_base/src/com/fr/design/images/server/manage.png -text +designer_base/src/com/fr/design/images/server/plugin.png -text +designer_base/src/com/fr/design/images/server/printerconf.png -text +designer_base/src/com/fr/design/images/server/start.png -text +designer_base/src/com/fr/design/images/server/stop.png -text +designer_base/src/com/fr/design/images/server/view.png -text +designer_base/src/com/fr/design/images/serverM/fs.png -text +designer_base/src/com/fr/design/images/serverM/org.png -text +designer_base/src/com/fr/design/images/serverM/organization.png -text +designer_base/src/com/fr/design/images/serverM/role.png -text +designer_base/src/com/fr/design/images/serverM/roleAdd.png -text +designer_base/src/com/fr/design/images/serverM/roleRemove.png -text +designer_base/src/com/fr/design/images/serverM/rtr.png -text +designer_base/src/com/fr/design/images/serverM/use.png -text +designer_base/src/com/fr/design/images/serverM/user.png -text +designer_base/src/com/fr/design/images/sheet/addpolysheet.png -text +designer_base/src/com/fr/design/images/sheet/left_right_btn.png -text +designer_base/src/com/fr/design/images/sheet/polysheet.png -text +designer_base/src/com/fr/design/images/toolbarbtn/chart.png -text +designer_base/src/com/fr/design/images/toolbarbtn/chartChangeClose.png -text +designer_base/src/com/fr/design/images/toolbarbtn/close.png -text +designer_base/src/com/fr/design/images/toolbarbtn/close_tags.png -text +designer_base/src/com/fr/design/images/toolbarbtn/closehover.png -text +designer_base/src/com/fr/design/images/toolbarbtn/connector.png -text +designer_base/src/com/fr/design/images/toolbarbtn/down.png -text +designer_base/src/com/fr/design/images/toolbarbtn/parameter-hover.png -text +designer_base/src/com/fr/design/images/toolbarbtn/parametersetting.png -text +designer_base/src/com/fr/design/images/toolbarbtn/pop.gif -text +designer_base/src/com/fr/design/images/toolbarbtn/setting.png -text +designer_base/src/com/fr/design/images/toolbarbtn/toolbarbtnclear.png -text +designer_base/src/com/fr/design/images/toolbarbtn/toolbarbtnsetting.png -text +designer_base/src/com/fr/design/images/toolbarbtn/up.png -text +designer_base/src/com/fr/design/images/toolbarbtn/xiala.png -text +designer_base/src/com/fr/design/images/tree/close.png -text +designer_base/src/com/fr/design/images/tree/open.png -text +designer_base/src/com/fr/design/images/wait.gif -text +designer_base/src/com/fr/design/images/warnings/warning[!!-~]2.png -text +designer_base/src/com/fr/design/images/warnings/warning.png -text +designer_base/src/com/fr/design/images/warnings/warning3.png -text +designer_base/src/com/fr/design/insert/formula/variable/cn/$$$.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/$$page_number.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/$$totalPage_number.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/$fr_authority.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/$fr_username.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/$fr_userposition.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/NOFILTER.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/NULL.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/contextPath.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/curReport.txt -text svneol=unset#application/octet-stream +designer_base/src/com/fr/design/insert/formula/variable/cn/fr_submitinfo.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/reportName.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/serverName.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/serverPort.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/serverSchema.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/serverURL.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/servletURL.txt -text +designer_base/src/com/fr/design/insert/formula/variable/cn/sessionID.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/$$$.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/$$page_number.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/$$totalPage_number.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/$fr_authority.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/$fr_username.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/$fr_userposition.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/NOFILTER.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/NULL.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/contextPath.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/curReport.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/fr_submitinfo.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/reportName.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/serverName.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/serverPort.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/serverSchema.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/serverURL.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/servletURL.txt -text +designer_base/src/com/fr/design/insert/formula/variable/en/sessionID.txt -text +designer_base/src/com/fr/design/javascript/Commit2DBJavaScriptPane.java -text +designer_base/src/com/fr/design/javascript/CustomActionPane.java -text +designer_base/src/com/fr/design/javascript/EmailPane.java -text +designer_base/src/com/fr/design/javascript/FormSubmitJavaScriptPane.java -text +designer_base/src/com/fr/design/javascript/JSContentPane.java -text +designer_base/src/com/fr/design/javascript/JavaScriptActionPane.java -text +designer_base/src/com/fr/design/javascript/JavaScriptImplPane.java -text +designer_base/src/com/fr/design/javascript/ParameterJavaScriptPane.java -text +designer_base/src/com/fr/design/javascript/ProcessJSImplPane.java -text +designer_base/src/com/fr/design/javascript/ProcessParameterTableModel.java -text +designer_base/src/com/fr/design/javascript/ProcessTransitionAdapter.java -text +designer_base/src/com/fr/design/layout/FRGUIPaneFactory.java -text +designer_base/src/com/fr/design/layout/FRGridLayout.java -text +designer_base/src/com/fr/design/layout/FRLeftFlowLayout.java -text +designer_base/src/com/fr/design/layout/LeftCenterRightLayout.java -text +designer_base/src/com/fr/design/layout/TableLayout.java -text +designer_base/src/com/fr/design/layout/TableLayoutConstraints.java -text +designer_base/src/com/fr/design/layout/TableLayoutHelper.java -text +designer_base/src/com/fr/design/layout/TableLayoutTest.java -text +designer_base/src/com/fr/design/layout/VerticalFlowLayout.java -text +designer_base/src/com/fr/design/mainframe/AbstractAppProvider.java -text +designer_base/src/com/fr/design/mainframe/App.java -text +designer_base/src/com/fr/design/mainframe/AuthorityEditPane.java -text +designer_base/src/com/fr/design/mainframe/AuthorityPropertyPane.java -text +designer_base/src/com/fr/design/mainframe/BaseFormDesigner.java -text +designer_base/src/com/fr/design/mainframe/BaseJForm.java -text +designer_base/src/com/fr/design/mainframe/BaseUndoState.java -text +designer_base/src/com/fr/design/mainframe/BaseWidgetPropertyPane.java -text +designer_base/src/com/fr/design/mainframe/DecodeDialog.java -text +designer_base/src/com/fr/design/mainframe/DesignerBean.java -text +designer_base/src/com/fr/design/mainframe/DesignerContext.java -text +designer_base/src/com/fr/design/mainframe/DesignerFrame.java -text +designer_base/src/com/fr/design/mainframe/DesignerFrameFileDealerPane.java -text +designer_base/src/com/fr/design/mainframe/DesktopCardPane.java -text +designer_base/src/com/fr/design/mainframe/DockingView.java -text +designer_base/src/com/fr/design/mainframe/DottedLine.java -text +designer_base/src/com/fr/design/mainframe/EastRegionContainerPane.java -text +designer_base/src/com/fr/design/mainframe/FormScrollBar.java -text +designer_base/src/com/fr/design/mainframe/JTemplate.java -text +designer_base/src/com/fr/design/mainframe/JTemplateActionListener.java -text +designer_base/src/com/fr/design/mainframe/JTemplateProvider.java -text +designer_base/src/com/fr/design/mainframe/JViewContainer.java -text +designer_base/src/com/fr/design/mainframe/NoSupportAuthorityEdit.java -text +designer_base/src/com/fr/design/mainframe/TemplatePane.java -text +designer_base/src/com/fr/design/mainframe/UndoStateEdit.java -text +designer_base/src/com/fr/design/mainframe/WestRegionContainerPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/BackgroundSettingPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/ColorBackgroundPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/ImageBackgroundPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/ImagePreviewPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/NullBackgroundPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/PatternBackgroundPane.java -text +designer_base/src/com/fr/design/mainframe/backgroundpane/TextureBackgroundPane.java -text +designer_base/src/com/fr/design/mainframe/dnd/ArrayListTransferHandler.java -text +designer_base/src/com/fr/design/mainframe/dnd/ArrayListTransferable.java -text +designer_base/src/com/fr/design/mainframe/dnd/ArrayTransferable.java -text +designer_base/src/com/fr/design/mainframe/dnd/SerializableTransferable.java -text +designer_base/src/com/fr/design/mainframe/form/FormECCompositeProvider.java -text +designer_base/src/com/fr/design/mainframe/form/FormECDesignerProvider.java -text +designer_base/src/com/fr/design/mainframe/hold/DefaultTitlePlace.java -text +designer_base/src/com/fr/design/mainframe/loghandler/DesignerLogHandler.java -text +designer_base/src/com/fr/design/mainframe/loghandler/DesignerLogImpl.java -text +designer_base/src/com/fr/design/mainframe/loghandler/LogDetailPane.java -text +designer_base/src/com/fr/design/mainframe/loghandler/LogHandlerBar.java -text +designer_base/src/com/fr/design/mainframe/loghandler/LogHandlerBarUI.java -text +designer_base/src/com/fr/design/mainframe/loghandler/LogMessageBar.java -text +designer_base/src/com/fr/design/mainframe/toolbar/AuthorityEditToolBarComponent.java -text +designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDock.java -text +designer_base/src/com/fr/design/mainframe/toolbar/ToolBarMenuDockPlus.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/AbstractPropertyEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/DataBindingEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/DataTableEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/ExtendedPropertyEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/FormattedEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/IntegerPropertyEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/PropertyCellEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/ServerDataBindingEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/ServerDataTableEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/StringEditor.java -text +designer_base/src/com/fr/design/mainframe/widget/editors/WidgetValueEditor.java -text +designer_base/src/com/fr/design/menu/DottedSeparator.java -text +designer_base/src/com/fr/design/menu/DottedSeparatorUI.java -text +designer_base/src/com/fr/design/menu/KeySetUtils.java -text +designer_base/src/com/fr/design/menu/LineSeparator.java -text +designer_base/src/com/fr/design/menu/MenuDef.java -text +designer_base/src/com/fr/design/menu/MenuKeySet.java -text +designer_base/src/com/fr/design/menu/MenuManager.java -text +designer_base/src/com/fr/design/menu/NameSeparator.java -text +designer_base/src/com/fr/design/menu/SeparatorDef.java -text +designer_base/src/com/fr/design/menu/ShortCut.java -text +designer_base/src/com/fr/design/menu/ToolBarDef.java -text +designer_base/src/com/fr/design/menu/TwoDottedSeparatorUI.java -text +designer_base/src/com/fr/design/menu/UISeparatorUI.java -text +designer_base/src/com/fr/design/module/DesignModule.java -text +designer_base/src/com/fr/design/module/DesignModuleFactory.java -text +designer_base/src/com/fr/design/object/NameObject.java -text +designer_base/src/com/fr/design/parameter/AbstractParameterReader.java -text +designer_base/src/com/fr/design/parameter/HierarchyTreePane.java -text +designer_base/src/com/fr/design/parameter/ParaDefinitePane.java -text +designer_base/src/com/fr/design/parameter/ParameterArrayPane.java -text +designer_base/src/com/fr/design/parameter/ParameterBridge.java -text +designer_base/src/com/fr/design/parameter/ParameterDesignerProvider.java -text +designer_base/src/com/fr/design/parameter/ParameterGroup.java -text +designer_base/src/com/fr/design/parameter/ParameterInputPane.java -text +designer_base/src/com/fr/design/parameter/ParameterManagerPane.java -text +designer_base/src/com/fr/design/parameter/ParameterPane.java -text +designer_base/src/com/fr/design/parameter/ParameterReader.java -text +designer_base/src/com/fr/design/present/DictPresentPane.java -text +designer_base/src/com/fr/design/present/FormulaPresentPane.java -text +designer_base/src/com/fr/design/present/NonePresentPane.java -text +designer_base/src/com/fr/design/present/dict/AbstractDicPane.java -text +designer_base/src/com/fr/design/present/dict/CustomDictCorrelationPane.java -text +designer_base/src/com/fr/design/present/dict/CustomDictPane.java -text +designer_base/src/com/fr/design/present/dict/DatabaseDictPane.java -text +designer_base/src/com/fr/design/present/dict/DictionaryPane.java -text +designer_base/src/com/fr/design/present/dict/FormulaDictPane.java -text +designer_base/src/com/fr/design/present/dict/TableDataDictPane.java -text +designer_base/src/com/fr/design/preview/PagePreview.java -text +designer_base/src/com/fr/design/preview/ViewPreview.java -text +designer_base/src/com/fr/design/preview/WritePreview.java -text +designer_base/src/com/fr/design/roleAuthority/ReportAndFSManagePane.java -text +designer_base/src/com/fr/design/roleAuthority/RoleDataWrapper.java -text +designer_base/src/com/fr/design/roleAuthority/RoleSourceOP.java -text +designer_base/src/com/fr/design/roleAuthority/RoleTree.java -text +designer_base/src/com/fr/design/roleAuthority/RolesAlreadyEditedPane.java -text +designer_base/src/com/fr/design/roleAuthority/RolesEditedSourceOP.java -text +designer_base/src/com/fr/design/roleAuthority/UIRoleTreeUI.java -text +designer_base/src/com/fr/design/scrollruler/BaseRuler.java -text +designer_base/src/com/fr/design/scrollruler/HorizontalRuler.java -text +designer_base/src/com/fr/design/scrollruler/HorizontalRulerUI.java -text +designer_base/src/com/fr/design/scrollruler/ModLineBorder.java -text +designer_base/src/com/fr/design/scrollruler/RulerLayout.java -text +designer_base/src/com/fr/design/scrollruler/RulerUI.java -text +designer_base/src/com/fr/design/scrollruler/ScrollRulerComponent.java -text +designer_base/src/com/fr/design/scrollruler/VerticalRuler.java -text +designer_base/src/com/fr/design/scrollruler/VerticalRulerUI.java -text +designer_base/src/com/fr/design/selection/QuickEditor.java -text +designer_base/src/com/fr/design/selection/SelectableElement.java -text +designer_base/src/com/fr/design/selection/Selectedable.java -text +designer_base/src/com/fr/design/selection/SelectionEvent.java -text +designer_base/src/com/fr/design/selection/SelectionListener.java -text +designer_base/src/com/fr/design/style/AbstractPopBox.java -text +designer_base/src/com/fr/design/style/AbstractSelectBox.java -text +designer_base/src/com/fr/design/style/AlignmentPane.java -text +designer_base/src/com/fr/design/style/AlphaPane.java -text +designer_base/src/com/fr/design/style/BorderPane.java -text +designer_base/src/com/fr/design/style/ChooseFileView.java -text +designer_base/src/com/fr/design/style/CustomSelectBox.java -text +designer_base/src/com/fr/design/style/FRFontPane.java -text +designer_base/src/com/fr/design/style/FRFontPreviewArea.java -text +designer_base/src/com/fr/design/style/FontFamilyPane.java -text +designer_base/src/com/fr/design/style/FontSizeStylePane.java -text +designer_base/src/com/fr/design/style/FormatBox.java -text +designer_base/src/com/fr/design/style/FormatPane.java -text +designer_base/src/com/fr/design/style/background/BackgroundCustomJComponent.java -text +designer_base/src/com/fr/design/style/background/BackgroundJComponent.java -text +designer_base/src/com/fr/design/style/background/BackgroundPane.java -text +designer_base/src/com/fr/design/style/background/BackgroundPane4BoxChange.java -text +designer_base/src/com/fr/design/style/background/BackgroundPreviewLabel.java -text +designer_base/src/com/fr/design/style/background/BackgroundSelectPane.java -text +designer_base/src/com/fr/design/style/background/BackgroundUIComboBoxNoImagePane.java -text +designer_base/src/com/fr/design/style/background/BackgroundUIComboBoxPane.java -text +designer_base/src/com/fr/design/style/background/gradient/GradientBackgroundSelectPane.java -text +designer_base/src/com/fr/design/style/background/gradient/GradientBar.java -text +designer_base/src/com/fr/design/style/background/gradient/GradientChangeBoxPane.java -text +designer_base/src/com/fr/design/style/background/gradient/GradientFromToPixPane.java -text +designer_base/src/com/fr/design/style/background/gradient/GradientPane.java -text +designer_base/src/com/fr/design/style/background/gradient/GradientSelectBox.java -text +designer_base/src/com/fr/design/style/background/gradient/SelectColorPointBtn.java -text +designer_base/src/com/fr/design/style/background/image/ImageFileChooser.java -text +designer_base/src/com/fr/design/style/background/image/ImagePreviewPane.java -text +designer_base/src/com/fr/design/style/background/image/ImageSelectPane.java -text +designer_base/src/com/fr/design/style/background/pattern/PatternSelectBox.java -text +designer_base/src/com/fr/design/style/background/pattern/PatternSelectPane.java -text +designer_base/src/com/fr/design/style/background/pattern/PatternUIComboBoxPane.java -text +designer_base/src/com/fr/design/style/background/texture/TextureSelectBox.java -text +designer_base/src/com/fr/design/style/background/texture/TextureSelectPane.java -text +designer_base/src/com/fr/design/style/background/texture/TextureUIComboBoxPane.java -text +designer_base/src/com/fr/design/style/color/ColorCell.java -text +designer_base/src/com/fr/design/style/color/ColorChooserPreview.java -text +designer_base/src/com/fr/design/style/color/ColorControlWindow.java -text +designer_base/src/com/fr/design/style/color/ColorFactory.java -text +designer_base/src/com/fr/design/style/color/ColorSelectBox.java -text +designer_base/src/com/fr/design/style/color/ColorSelectConfigManager.java -text +designer_base/src/com/fr/design/style/color/ColorSelectDetailPane.java -text +designer_base/src/com/fr/design/style/color/ColorSelectDialog.java -text +designer_base/src/com/fr/design/style/color/ColorSelectPane.java -text +designer_base/src/com/fr/design/style/color/ColorSelectable.java -text +designer_base/src/com/fr/design/style/color/ColorUIComboBoxPane.java -text +designer_base/src/com/fr/design/style/color/CustomChooserPanel.java -text +designer_base/src/com/fr/design/style/color/DetailColorSelectPane.java -text +designer_base/src/com/fr/design/style/color/NewColorSelectBox.java -text +designer_base/src/com/fr/design/style/color/NewColorSelectPane.java -text +designer_base/src/com/fr/design/style/color/RecentUseColorPane.java -text +designer_base/src/com/fr/design/style/color/SwatchChooserPanel.java -text +designer_base/src/com/fr/design/style/color/TransparentColorControlWindow.java -text +designer_base/src/com/fr/design/style/color/TransparentPane.java -text +designer_base/src/com/fr/design/style/color/UIToolbarColorButton.java -text +designer_base/src/com/fr/design/style/color/UsedColorPane.java -text +designer_base/src/com/fr/design/utils/ColorRoutines.java -text +designer_base/src/com/fr/design/utils/ComponentUtils.java -text +designer_base/src/com/fr/design/utils/DesignUtils.java -text +designer_base/src/com/fr/design/utils/DrawRoutines.java -text +designer_base/src/com/fr/design/utils/ThemeUtils.java -text +designer_base/src/com/fr/design/utils/gui/GUICoreUtils.java -text +designer_base/src/com/fr/design/utils/gui/GUIPaintUtils.java -text +designer_base/src/com/fr/design/utils/gui/JListUtils.java -text +designer_base/src/com/fr/design/utils/gui/LayoutUtils.java -text +designer_base/src/com/fr/design/web/CustomIconPane.java -text +designer_base/src/com/fr/design/widget/Appearance.java -text +designer_base/src/com/fr/design/widget/IconDefinePane.java -text +designer_base/src/com/fr/design/widget/btn/ButtonConstants.java -text +designer_base/src/com/fr/design/widget/btn/ButtonDetailPane.java -text +designer_base/src/com/fr/design/widget/btn/ButtonWithHotkeysDetailPane.java -text +designer_base/src/com/fr/design/write/submit/CustomJobPane.java -text +designer_base/src/com/fr/design/write/submit/CustomSubmitJobPane.java -text +designer_base/src/com/fr/design/write/submit/DBManipulationInWidgetEventPane.java -text +designer_base/src/com/fr/design/write/submit/DBManipulationPane.java -text +designer_base/src/com/fr/design/write/submit/DMLJobPane.java -text +designer_base/src/com/fr/design/write/submit/SubmitJobListPane.java -text +designer_base/src/com/fr/env/EnvListPane.java -text +designer_base/src/com/fr/env/RemoteEnv.java -text +designer_base/src/com/fr/env/RemoteSignInPane.java -text +designer_base/src/com/fr/env/SignIn.java -text +designer_base/src/com/fr/file/FILE.java -text +designer_base/src/com/fr/file/FILEChooserPane.java -text +designer_base/src/com/fr/file/FILEFactory.java -text +designer_base/src/com/fr/file/FileFILE.java -text +designer_base/src/com/fr/file/FileNodeFILE.java -text +designer_base/src/com/fr/file/MemFILE.java -text +designer_base/src/com/fr/file/filter/ChooseFileFilter.java -text +designer_base/src/com/fr/file/filter/FILEFilter.java -text +designer_base/src/com/fr/file/filter/OnlyShowDirectoryFileFilter.java -text +designer_base/src/com/fr/plugin/PluginManager.java -text +designer_base/src/com/fr/start/BBSGuestPaneProvider.java -text +designer_base/src/com/fr/start/BaseDesigner.java -text +designer_base/src/com/fr/start/Demo.java -text +designer_base/src/com/fr/start/JettyFRHost.java -text +designer_base/src/com/fr/start/SplashPane.java -text +designer_base/src/com/fr/start/SplashWindow.java -text +designer_base/src/com/fr/start/StartDocURL.java -text +designer_base/src/com/fr/start/StartServer.java -text +designer_base/src/com/fr/start/server/JettyHost.java -text +designer_base/src/com/fr/start/server/JettyServerListener.java -text +designer_base/src/com/fr/start/server/MultiOutputStream.java -text +designer_base/src/com/fr/start/server/ServerManageFrame.java -text +designer_base/src/com/fr/start/server/ServerTray.java -text designer_chart/.classpath -text designer_chart/.project -text designer_chart/designer_chart.iml -text diff --git a/.gitignore b/.gitignore index b5e1bcf135..ebfc6188b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ designer/bin +designer_base/bin designer_chart/bin designer_form/bin diff --git a/designer_base/.classpath b/designer_base/.classpath new file mode 100644 index 0000000000..b7ba91ed1f --- /dev/null +++ b/designer_base/.classpath @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/designer_base/.project b/designer_base/.project new file mode 100644 index 0000000000..634f6ba317 --- /dev/null +++ b/designer_base/.project @@ -0,0 +1 @@ + designer_base org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature \ No newline at end of file diff --git a/designer_base/designer_base.iml b/designer_base/designer_base.iml new file mode 100644 index 0000000000..9f8c89a0b5 --- /dev/null +++ b/designer_base/designer_base.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/designer_base/src/com/fr/design/DesignModelAdapter.java b/designer_base/src/com/fr/design/DesignModelAdapter.java new file mode 100644 index 0000000000..7c2c718068 --- /dev/null +++ b/designer_base/src/com/fr/design/DesignModelAdapter.java @@ -0,0 +1,141 @@ +package com.fr.design; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.fr.base.Parameter; +import com.fr.base.io.IOFile; +import com.fr.data.TableDataSource; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.JTemplateProvider; +import com.fr.form.ui.Widget; +import com.fr.general.ComparatorUtils; +import com.fr.stable.js.WidgetName; + +/** + * 当前的设计器模式 + * + * @author zhou + * @since 2012-7-26上午11:24:54 + */ +public abstract class DesignModelAdapter { + + private static DesignModelAdapter currentModelAdapter; + protected S jTemplate; + + public DesignModelAdapter(S jTemplate) { + this.jTemplate = jTemplate; + setCurrentModelAdapter(this); + } + + public T getBook() { + return (T) ((JTemplate) jTemplate).getTarget(); + } + + public static void setCurrentModelAdapter(DesignModelAdapter model) { + currentModelAdapter = model; + } + + public static DesignModelAdapter getCurrentModelAdapter() { + return currentModelAdapter; + } + + /** + * 响应目标改变事件. + */ + public void fireTargetModified() { + ((JTemplate) this.jTemplate).fireTargetModified(); + } + + public String[] getFloatNames() { + return new String[0]; + } + + public Parameter[] getParameters() { + return new Parameter[0]; + } + + // 报表参数 + public Parameter[] getReportParameters() { + return new Parameter[0]; + } + + /** + * 数据源参数 + * + * @return + */ + public Parameter[] getTableDataParameters() { + return new Parameter[0]; + } + + /** + * 重命名数据集 + * + * @param oldName 旧名字 + * @param newName 新名字 + * @param isNeedFireModified 是否需要触发保存 + * @return 重命名成功返回True + */ + public boolean renameTableData(String oldName, String newName, boolean isNeedFireModified) { + if (!ComparatorUtils.equals(oldName, newName)) { + TableDataSource tds = getBook(); + boolean b; + b = tds.renameTableData(oldName, newName); + if (!b) { + return b; + } + if (isNeedFireModified) { + fireTargetModified(); + } + } + return true; + } + + /** + * 重命名TableData后的一些操作 + * + * @param oldName 旧名字 + * @param newName 新名字. + * @return 返回是否名字一样. + */ + public boolean renameTableData(String oldName, String newName) { + return renameTableData(oldName, newName, true); + } + + /** + * 重命名tabledata + * + * @param map 新名字 + */ + public void renameTableData(Map map) { + if (map.isEmpty()) { + return; + } + Iterator iterator = map.keySet().iterator(); + while (iterator.hasNext()) { + String key = iterator.next(); + renameTableData(key, map.get(key)); + } + } + + public abstract Widget[] getLinkableWidgets() ; + + public abstract List getWidgetsName(); + + /** + * 环境改变. + */ + public abstract void envChanged(); + + /** + * 参数改变. + */ + public abstract void parameterChanged(); + + /** + * 控件配置改变. + */ + public abstract void widgetConfigChanged(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/DesignState.java b/designer_base/src/com/fr/design/DesignState.java new file mode 100644 index 0000000000..0a74f52e2f --- /dev/null +++ b/designer_base/src/com/fr/design/DesignState.java @@ -0,0 +1,73 @@ +package com.fr.design; + +import com.fr.base.BaseUtils; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.env.RemoteEnv; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-24 + * Time: 上午9:36 + * 记录现在设计器的设计状态 + */ +public class DesignState { + + //菜单的几种情况 + //Jwrok + + //worksheet + public static final int WORK_SHEET = 0; + //polyDesogner + public static final int POLY_SHEET = 1; + //参数面板 + public static final int PARAMETER_PANE = 2; + + + //From + public static final int JFORM = 4; + + + //是不是在远程 + public static final int REMOTE = 8; + + //设计状态 + private int designState = -1; + private boolean isRoot = true;//默认是管理员登陆 + private boolean isAuthority = false; + + public DesignState(ToolBarMenuDockPlus plus) { + designState = plus.getMenuState(); + Env env = FRContext.getCurrentEnv(); + if (env != null && env instanceof RemoteEnv) { + designState += REMOTE; + } + isRoot = env != null && env.isRoot(); + isAuthority = BaseUtils.isAuthorityEditing(); + } + + public int getDesignState() { + return designState; + } + + /** + * 是否是管理员 + * @return 是管理员返回true + */ + public boolean isRoot() { + return this.isRoot; + } + + /** + * 是否处于权限编辑状态 + * @return 是则返回true + */ + public boolean isAuthority() { + return isAuthority; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/DesignerEnvManager.java b/designer_base/src/com/fr/design/DesignerEnvManager.java new file mode 100644 index 0000000000..f43096c61c --- /dev/null +++ b/designer_base/src/com/fr/design/DesignerEnvManager.java @@ -0,0 +1,1795 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design; + +import com.fr.base.BaseXMLUtils; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.base.Utils; +import com.fr.dav.LocalEnv; +import com.fr.design.constants.UIConstants; +import com.fr.env.RemoteEnv; +import com.fr.env.SignIn; +import com.fr.file.FILEFactory; +import com.fr.general.*; +import com.fr.stable.*; +import com.fr.stable.core.UUID; +import com.fr.stable.project.ProjectConstants; +import com.fr.stable.xml.*; + +import javax.swing.*; +import javax.swing.SwingWorker.StateValue; +import java.awt.*; +import java.io.*; +import java.util.*; +import java.util.List; +import java.util.Map.Entry; +import java.util.logging.FileHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.SimpleFormatter; + +/** + * The manager of Designer GUI. + */ +public class DesignerEnvManager implements XMLReadable, XMLWriter { + + private static final int MAX_SHOW_NUM = 10; + + private static DesignerEnvManager designerEnvManager; // gui. + private String activationKey = null; + private String logLocation = null; + private Rectangle windowBounds = null; // window bounds. + private String DialogCurrentDirectory = null; + private String CurrentDirectoryPrefix = null; + private List recentOpenedFilePathList = new ArrayList(); + private boolean showPaintToolBar = true; + private int maxNumberOrPreviewRow = 200; + // name和Env的键值对 + private Map nameEnvMap = new ListMap(); + // marks: 当前报表服务器名字 + private String curEnvName = null; + private boolean showProjectPane = true; + private boolean showDataPane = true; + //p:这是当前选择的数据库连接的名字,这个在新建数据源的时候用到. + private String recentSelectedConnection = null; + // 设计器预览时的Jetty端口 + public int jettyServerPort = 8075; + // eason: + private boolean supportUndo = true; + private boolean supportDefaultParentCalculate = true; + //samuel:支持字符串编辑为公式 + private boolean supportStringToFormula = true; + private boolean defaultStringToFormula = false; + private String autoCompleteShortcuts = UIConstants.DEFAULT_AUTO_COMPLETE; + private boolean columnHeaderVisible = true; + private boolean rowHeaderVisible = true; + private boolean verticalScrollBarVisible = true; + private boolean horizontalScrollBarVisible = true; + private Color gridLineColor = Color.lightGray; // line color. + private Color paginationLineColor = Color.black; // line color of paper + private boolean supportCellEditorDef = false; + private boolean isDragPermited = false; + private Level level = Level.INFO; + private int language; + //2014-8-26默认显示全部, 因为以前的版本, 虽然是false, 实际上是显示所有表, 因此这边要兼容 + private boolean useOracleSystemSpace = true; + private boolean autoBackUp = true; + private int undoLimit = 5; + private short pageLengthUnit = Constants.UNIT_MM; + private short reportLengthUnit = Constants.UNIT_MM; + private boolean templateTreePaneExpanded = false; + private String lastOpenFilePath = null; + + private int eastRegionToolPaneY = 300; + private int eastRegionContainerWidth = 260; + + private int westRegionToolPaneY = 300; + private int westRegionContainerWidth = 240; + private String encryptionKey; + private String jdkHome; + //当前设计器用户的论坛昵称 + private String bbsName; + //当前设计器用户的论坛密码 + private String bbsPassword; + //上一次登录弹窗的时间, 为了控制一天只弹一次窗口 + private String lastShowBBSTime; + //上一次资讯弹窗时间, 为了控制一天只弹一次 + private String lastShowBBSNewsTime; + //设计器的唯一ID, 用于远程设计和在线验证激活码 + private String uuid; + //记录当前激活码的在线激活状态. + private int activeKeyStatus = -1; + private boolean joinProductImprove = true; + + + public static final String CAS_CERTIFICATE_PATH = "certificatePath"; + + public static final String CAS_CERTIFICATE_PASSWORD = "certificatePass"; + + public static final String CAS_PARAS = "CASParas"; + + //https链接所需的证书路径 + private String certificatePath = StringUtils.EMPTY; + + //https链接所需的证书密码 + private String certificatePass = StringUtils.EMPTY; + + //是否启用https连接 + private boolean isHttps = false; + + private static List mapWorkerList = new ArrayList(); + + /** + * DesignerEnvManager. + */ + public static DesignerEnvManager getEnvManager() { + if (designerEnvManager == null) { + designerEnvManager = new DesignerEnvManager(); + try { + XMLTools.readFileXML(designerEnvManager, designerEnvManager.getDesignerEnvFile()); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + // james:如果没有env定义,要设置一个默认的 + if (designerEnvManager.nameEnvMap.size() <= 0) { + String installHome = StableUtils.getInstallHome(); + if (installHome != null) { + String name = Inter.getLocText("Default"); + String envPath = StableUtils.pathJoin(new String[]{installHome, ProjectConstants.WEBAPP_NAME, ProjectConstants.WEBINF_NAME}); + designerEnvManager.putEnv(name, LocalEnv.createEnv(envPath)); + designerEnvManager.setCurEnvName(name); + } + } + } + + GeneralContext.addEnvChangedListener(new EnvChangedListener() { + @Override + public void envChanged() { + + designerEnvManager.setCurrentDirectoryPrefix(FILEFactory.ENV_PREFIX); + designerEnvManager.setDialogCurrentDirectory(ProjectConstants.REPORTLETS_NAME); + } + }); + + return designerEnvManager; + } + + /** + * 添加设计器中相关的worker + * + * @param worker 相关的worker + */ + public static void addWorkers(SwingWorker worker) { + mapWorkerList.add(worker); + } + + /** + * 删除设计器中相关的worker. + * + * @param worker 相关的worker + */ + public static void removeWorkers(SwingWorker worker) { + if (mapWorkerList.contains(worker)) { + mapWorkerList.remove(worker); + } + } + + /** + * 做完设计器中现存的地图worker + */ + public static void doEndMapSaveWorkersIndesign() { + for (int i = 0; i < mapWorkerList.size(); i++) { + SwingWorker worker = mapWorkerList.get(i); + if (worker.getState() != StateValue.DONE) { + worker.execute(); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + FRLogger.getLogger().error("Map Save Error"); + } + } + } + } + + /** + * richer:载入log设置 + */ + public static void loadLogSetting() { + DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager(); + Level logLevel = designerEnvManager.getLogLevel(); + if (logLevel != null) { + FRContext.getLogger().setLogLevel(logLevel, true); + } + if (StringUtils.isNotEmpty(designerEnvManager.getJdkHome())) { + System.setProperty("java.home", designerEnvManager.getJdkHome()); + } + + // 写文件的LogLocation + String logLocation = DesignerEnvManager.getEnvManager().getLogLocation(); + if (logLocation != null) { + try { + Calendar calender = GregorianCalendar.getInstance(); + calender.setTimeInMillis(System.currentTimeMillis()); + String today = calender.get(Calendar.YEAR) + "-" + (calender.get(Calendar.MONTH) + 1) + "-" + calender.get(Calendar.DAY_OF_MONTH); + + String fileName = StableUtils.pathJoin(new String[]{ + logLocation, "fr_" + today + "_%g.log" + }); + if (!new java.io.File(fileName).exists()) { + StableUtils.makesureFileExist(new java.io.File(fileName)); + } + Handler handler = new FileHandler(fileName, true); + handler.setFormatter(new SimpleFormatter()); + FRContext.getLogger().addLogHandler(handler); + } catch (SecurityException e) { + FRContext.getLogger().error(e.getMessage(), e); + } catch (IOException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + } + + private File getDesignerEnvFile() { + File envFile = getEnvFile(); + // james:FineReportEnv.xml文件没有必要做兼容,里面保存的主要是界面布局以及设计器激活的信息 + // 对于这些内容,除了激活码以外,其他的兼容毫无意义。对于激活码,也可以不兼容,正好知道用户是否进行了升级呢 + // 对于自己升级的用户,正好知道有升级的用户呢。对于我们帮助升级的,给用户一个激活码就是啦 + if (!envFile.exists()) { + createEnvFile(envFile); + } + + return envFile; + } + + private void createEnvFile(File envFile) { + try { + FileWriter fileWriter = new FileWriter(envFile); + File oldEnvFile = new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "6-1" + "Env.xml"); + if (oldEnvFile.exists()) { + // marks:兼容DesignerEnv6-1.xml + FileReader fileReader = new FileReader(oldEnvFile); + Utils.copyCharTo(fileReader, fileWriter); + fileReader.close(); + } else { + // marks:生成一个新的xml文件 + StringReader stringReader = new StringReader(""); + Utils.copyCharTo(stringReader, fileWriter); + stringReader.close(); + } + fileWriter.close(); + } catch (IOException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + + public static void setEnvFile(File envFile) { + DesignerEnvManager.envFile = envFile; + } + + private static File envFile = null; + + private File getEnvFile() { + if (envFile == null) { + envFile = new File(ProductConstants.getEnvHome() + File.separator + ProductConstants.APP_NAME + "Env.xml"); + } + return envFile; + } + + /** + * 是否启用了https + * @return 同上 + */ + public boolean isHttps() { + return isHttps; + } + + + public void setHttps(boolean isHttps) { + this.isHttps = isHttps; + } + + + public String getCertificatePath() { + return certificatePath; + } + + + public void setCertificatePath(String certificatePath) { + this.certificatePath = certificatePath; + } + + + public String getCertificatePass() { + return certificatePass; + } + + public void setCertificatePass(String certificatePass){ + this.certificatePass = certificatePass; + } + + /** + * 返回上次打开的模板文件 + */ + public String getLastOpenFile() { + return lastOpenFilePath; + } + + /** + * 设置记录 上次打开的模板文件 + */ + public void setLastOpenFile(String lastOpenFilePath) { + this.lastOpenFilePath = lastOpenFilePath; + } + + + /** + * 得到西面板的上下子面板的高度区分 + * + * @return + */ + public int getLastWestRegionToolPaneY() { + return this.westRegionToolPaneY; + } + + /** + * 得到上次关闭设计器时的西边面板的宽度 + * + * @return + */ + public int getLastWestRegionContainerWidth() { + return this.westRegionContainerWidth; + } + + /** + * 设置西面板的上下子面板的高度区分 + * + * @param toolPaneY + */ + public void setLastWestRegionToolPaneY(int toolPaneY) { + this.westRegionToolPaneY = toolPaneY; + } + + /** + * 设置上次关闭设计器时的西边面板的宽度 + * + * @param westRegionContainerWidth + */ + public void setLastWestRegionContainerWidth(int westRegionContainerWidth) { + this.westRegionContainerWidth = westRegionContainerWidth; + } + + + /** + * 得到上次关闭设计器前东部面板的上下子面板的高度区分 + * + * @return + */ + public int getLastEastRegionToolPaneY() { + return this.eastRegionToolPaneY; + } + + /** + * 得到上次关闭设计器前东部面板的宽度 + * + * @return + */ + public int getLastEastRegionContainerWidth() { + return this.eastRegionContainerWidth; + } + + /** + * 设置上次关闭设计器前东部面板的上下子面板的高度区分 + * + * @param toolPaneY + */ + public void setLastEastRegionToolPaneY(int toolPaneY) { + this.eastRegionToolPaneY = toolPaneY; + } + + /** + * 设置上次关闭设计器前东部面板的宽度 + * + * @param eastRegionContainerWidth + */ + public void setLastEastRegionContainerWidth(int eastRegionContainerWidth) { + this.eastRegionContainerWidth = eastRegionContainerWidth; + } + + + /** + * 判断当前环境是否为默认 + * + * @return 是默认则返回true + */ + public boolean isCurrentEnvDefault() { + Env currentEnv = this.getEnv(curEnvName); + String defaultEnvPath = StableUtils.pathJoin(new String[]{StableUtils.getInstallHome(), ProjectConstants.WEBAPP_NAME, ProjectConstants.WEBINF_NAME}); + return ComparatorUtils.equals(new File(defaultEnvPath).getPath(), currentEnv.getPath()); + } + + /** + * 返回默认环境 + */ + public Env getDefaultEnv() { + String installHome = StableUtils.getInstallHome(); + String defaultenvPath = StableUtils.pathJoin(new String[]{installHome, ProjectConstants.WEBAPP_NAME, ProjectConstants.WEBINF_NAME}); + defaultenvPath = new File(defaultenvPath).getPath(); + if (nameEnvMap.size() >= 0) { + Iterator> entryIt = nameEnvMap.entrySet().iterator(); + while (entryIt.hasNext()) { + Entry entry = entryIt.next(); + Env env = entry.getValue(); + if (ComparatorUtils.equals(defaultenvPath, env.getPath())) { + return env; + } + } + } + Env newDefaultEnv = LocalEnv.createEnv(defaultenvPath); + this.putEnv(Inter.getLocText(new String[]{"Default", "Utils-Report_Runtime_Env"}), newDefaultEnv); + return newDefaultEnv; + } + + /** + * 返回默认环境名称 + */ + public String getDefaultEnvName() { + String installHome = StableUtils.getInstallHome(); + String defaultenvPath = StableUtils.pathJoin(new String[]{installHome, ProjectConstants.WEBAPP_NAME, ProjectConstants.WEBINF_NAME}); + defaultenvPath = new File(defaultenvPath).getPath(); + if (nameEnvMap.size() >= 0) { + Iterator> entryIt = nameEnvMap.entrySet().iterator(); + while (entryIt.hasNext()) { + Entry entry = entryIt.next(); + Env env = entry.getValue(); + if (ComparatorUtils.equals(defaultenvPath, env.getPath())) { + return entry.getKey(); + } + } + } + return Inter.getLocText(new String[]{"Default", "Utils-Report_Runtime_Env"}); + } + + /** + * 设置当前环境为默认 + */ + public void setCurrentEnv2Default() { + if (isCurrentEnvDefault()) { + return; + } + try { + SignIn.signIn(getDefaultEnv()); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + } + + /** + * 模板Tree是否展开 + * + * @return 展开则返回true + */ + public boolean isTemplateTreePaneExpanded() { + return templateTreePaneExpanded; + } + + /** + * 设置模板Tree是否展开 + */ + public void setTemplateTreePaneExpanded(boolean templateTreePaneExpanded) { + this.templateTreePaneExpanded = templateTreePaneExpanded; + } + + /** + * 知否自动备份 + * + * @return 是则返回true + */ + public boolean isAutoBackUp() { + return autoBackUp; + } + + /** + * 设置是否自动备份 + */ + public void setAutoBackUp(boolean autoBackUp) { + this.autoBackUp = autoBackUp; + } + + /** + * 返回页面长度单位 + */ + public short getPageLengthUnit() { + return pageLengthUnit; + } + + /** + * 设置页面长度单位 + */ + public void setPageLengthUnit(short pageLengthUnit) { + this.pageLengthUnit = pageLengthUnit; + } + + /** + * 返回报表长度单位 + */ + public short getReportLengthUnit() { + return reportLengthUnit; + } + + /** + * 设置报表长度单位 + */ + public void setReportLengthUnit(short reportLengthUnit) { + this.reportLengthUnit = reportLengthUnit; + } + + private void writeTempFile(File tempFile){ + try{ + OutputStream fout = new FileOutputStream(tempFile); + XMLTools.writeOutputStreamXML(this, fout); + fout.flush(); + fout.close(); + }catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + } + + /** + * 保存设计器的配置文件, 该文件不在env的resource目录下 + * 而是在Consts.getEnvHome() + File.separator + Consts.APP_NAME + * + * + * @date 2014-9-29-上午11:04:23 + * + */ + public void saveXMLFile() { + File xmlFile = this.getDesignerEnvFile(); + if (xmlFile == null) { + return; + } + if (!xmlFile.getParentFile().exists()) {//建立目录. + StableUtils.mkdirs(xmlFile.getParentFile()); + } + + String tempName = xmlFile.getName() + ProjectConstants.TEMP_SUFFIX; + File tempFile = new File(xmlFile.getParentFile(), tempName); + + writeTempFile(tempFile); + IOUtils.renameTo(tempFile, xmlFile); + } + + /** + * 设置是否使用磁盘空间 + */ + public void setOracleSystemSpace(boolean displayOracleSystem) { + this.useOracleSystemSpace = displayOracleSystem; + } + + /** + * 是否加入产品改良 + * + * @return 是否加入产品改良 + * + */ + public boolean isJoinProductImprove() { + return joinProductImprove; + } + + /** + * 设置加入产品改良 + * + */ + public void setJoinProductImprove(boolean joinProductImprove) { + this.joinProductImprove = joinProductImprove; + } + + /** + * 是否磁盘空间参数 + * + * @return 是则返回true + */ + public boolean isOracleSystemSpace() { + return this.useOracleSystemSpace; + } + + /** + * 返回语言类型 + */ + public int getLanguage() { + return this.language; + } + + /** + * 设置语言参数 + */ + public void setLanguage(int i) { + this.language = i; + } + + /** + * 返回环境名称迭代器 + */ + public Iterator getEnvNameIterator() { + return this.nameEnvMap.keySet().iterator(); + } + + /** + * 根据名称返回环境 + */ + public Env getEnv(String name) { + return this.nameEnvMap.get(name); + } + + /** + * 记录名称 和对应的环境 + * + * @param name 名称 + * @param env 对应的环境 + */ + public void putEnv(String name, Env env) { + this.nameEnvMap.put(name, env); + } + + /** + * 删除名称对应的环境 + * + * @param name 环境的名字 + */ + public void removeEnv(String name) { + this.nameEnvMap.remove(name); + } + + /** + * 清除全部环境 + */ + public void clearAllEnv() { + this.nameEnvMap.clear(); + } + + /** + * 返回界面的大小范围. + */ + public Rectangle getWindowBounds() { + return this.windowBounds; + } + + /** + * 设置界面的大小范围 + */ + public void setWindowBounds(Rectangle windowBounds) { + this.windowBounds = windowBounds; + } + + + /** + * 返回当前环境的名称. + */ + public String getCurEnvName() { + return this.curEnvName; + } + + /** + * 设置当前环境的名称 + */ + public void setCurEnvName(String envName) { + this.curEnvName = envName; + } + + /** + * 返回Jetty服务器的端口号 + */ + public int getJettyServerPort() { + return this.jettyServerPort; + } + + /** + * 设置Jetty服务器的端口号 + */ + public void setJettyServerPort(int jettyServerPort) { + if (jettyServerPort <= 0) { + return; + } + this.jettyServerPort = jettyServerPort; + } + + /** + * 返回对话框当前路径 + */ + public String getDialogCurrentDirectory() { + return DialogCurrentDirectory; + } + + /** + * 设置当前对话框路径 + */ + public void setDialogCurrentDirectory(String dialogCurrentDirectory) { + this.DialogCurrentDirectory = dialogCurrentDirectory; + } + + /** + * 返回当前路径前缀 + */ + public String getCurrentDirectoryPrefix() { + return CurrentDirectoryPrefix; + } + + /** + * 设置当前路径前缀 + */ + public void setCurrentDirectoryPrefix(String prefix) { + this.CurrentDirectoryPrefix = prefix; + } + + + /** + * 返回最近打开的文件路径列表 + */ + public List getRecentOpenedFilePathList() { + return this.recentOpenedFilePathList; + } + + /** + * 添加最近打开的文件路径 + * + * @param filePath 文件路径 + */ + public void addRecentOpenedFilePath(String filePath) { + // 先删除. + if (this.recentOpenedFilePathList.contains(filePath)) { + this.recentOpenedFilePathList.remove(filePath); + } + + this.recentOpenedFilePathList.add(0, filePath); + checkRecentOpenedFileNum(); + } + + /** + * 替换近期打开的文件路径 + * + * @param oldPath 旧的路径 + * @param newPath 新的路径 + */ + public void replaceRecentOpenedFilePath(String oldPath, String newPath) { + if (this.recentOpenedFilePathList.contains(oldPath)) { + int index = recentOpenedFilePathList.indexOf(oldPath); + this.recentOpenedFilePathList.remove(oldPath); + this.recentOpenedFilePathList.add(index, newPath); + } + } + + private void checkRecentOpenedFileNum() { + if (this.recentOpenedFilePathList == null) { + return; + } + while (this.recentOpenedFilePathList.size() > MAX_SHOW_NUM) { + this.recentOpenedFilePathList.remove(this.recentOpenedFilePathList.size() - 1); + } + } + + /** + * 移除最近打开的文件路径 + * + * @param filePath 文件路径 + */ + public void removeRecentOpenedFilePath(String filePath) { + if (this.recentOpenedFilePathList.contains(filePath)) { + this.recentOpenedFilePathList.remove(filePath); + } + } + + + /** + * 是否展示toolbar + * + * @return 是则返回true + */ + public boolean isShowPaintToolBar() { + return showPaintToolBar; + } + + /** + * 设置是否展示toolbar + */ + public void setShowPaintToolBar(boolean showPaintToolBar) { + this.showPaintToolBar = showPaintToolBar; + } + + /** + * 是否支持撤销 + * + * @return 是则返回true + */ + public boolean isSupportUndo() { + return supportUndo; + } + + /** + * 设置是否支持撤销 + */ + public void setSupportUndo(boolean supportUndo) { + this.supportUndo = supportUndo; + } + + /** + * 是否支持默认父类计算 + * + * @return 是则返回true + */ + public boolean isSupportDefaultParentCalculate() { + return supportDefaultParentCalculate; + } + + /** + * 设置是否支持默认父类计算 + */ + public void setSupportDefaultParentCalculate(boolean supportDefaultParentCalculate) { + this.supportDefaultParentCalculate = supportDefaultParentCalculate; + } + + /** + * 设置是否支持字符串转为公式 + * + * @return 支持则返回true + */ + public boolean isSupportStringToFormula() { + return supportStringToFormula; + } + + /** + * 设置是否支持字符串转为公式 + */ + public void setSupportStringToFormula(boolean supportStringToFormula) { + this.supportStringToFormula = supportStringToFormula; + } + + /** + * 是否默认字符串转为公式 + * + * @return 是则返回true + */ + public boolean isDefaultStringToFormula() { + return defaultStringToFormula; + } + + /** + * 设置是否支持字符串转为公式 + */ + public void setDefaultStringToFormula(boolean defaultStringToFormula) { + this.defaultStringToFormula = defaultStringToFormula; + } + + /** + * 获取快捷键名称 + */ + public String getAutoCompleteShortcuts() { + return autoCompleteShortcuts; + } + + /** + * 设置快捷键名称 + */ + public void setAutoCompleteShortcuts(String autoCompleteShortcuts) { + this.autoCompleteShortcuts = autoCompleteShortcuts; + } + + + /** + * 列表头是否可见 + * + * @return 是则返回true + */ + public boolean isColumnHeaderVisible() { + return columnHeaderVisible; + } + + /** + * 设置列表头是否可见 + */ + public void setColumnHeaderVisible(boolean columnHeaderVisible) { + this.columnHeaderVisible = columnHeaderVisible; + } + + /** + * 行表头是否可见 + * + * @return 是则返回true + */ + public boolean isRowHeaderVisible() { + return rowHeaderVisible; + } + + /** + * 设置行表头是否可见 + */ + public void setRowHeaderVisible(boolean rowHeaderVisible) { + this.rowHeaderVisible = rowHeaderVisible; + } + + /** + * 垂直滚动条是否可见 + * + * @return 是则返回true + */ + public boolean isVerticalScrollBarVisible() { + return verticalScrollBarVisible; + } + + /** + * 设置垂直滚动条可见 + */ + public void setVerticalScrollBarVisible(boolean verticalScrollBarVisible) { + this.verticalScrollBarVisible = verticalScrollBarVisible; + } + + /** + * 水平滚动条是否可见 + * + * @return 是则返回true + */ + public boolean isHorizontalScrollBarVisible() { + return horizontalScrollBarVisible; + } + + /** + * 设置水平滚动条是否可见 + */ + public void setHorizontalScrollBarVisible(boolean horizontalScrollBarVisible) { + this.horizontalScrollBarVisible = horizontalScrollBarVisible; + } + + /** + * 返回网格线的颜色 + */ + public Color getGridLineColor() { + return gridLineColor; + } + + /** + * 设置网格线的颜色 + */ + public void setGridLineColor(Color gridLineColor) { + this.gridLineColor = gridLineColor; + } + + /** + * 返回页面的线颜色 + */ + public Color getPaginationLineColor() { + return paginationLineColor; + } + + /** + * 设置页面的线颜色 + */ + public void setPaginationLineColor(Color paginationLineColor) { + this.paginationLineColor = paginationLineColor; + + } + + /** + * 是否支持单元格编辑器 + * + * @return 是则返回true + */ + public boolean isSupportCellEditorDef() { + return supportCellEditorDef; + } + + /** + * 设置是否支持单元格编辑器 + */ + public void setSupportCellEditorDef(boolean supportCellEditorDef) { + this.supportCellEditorDef = supportCellEditorDef; + } + + /** + * 是否允许拖拽 + * + * @return 是则返回true + */ + public boolean isDragPermited() { + return isDragPermited; + } + + /** + * 设置是否允许拖拽 + */ + public void setDragPermited(boolean isDragPermited) { + this.isDragPermited = isDragPermited; + } + + /** + * 返回最大预览的行数 + */ + public int getMaxNumberOrPreviewRow() { + return maxNumberOrPreviewRow; + } + + /** + * 设置最大预览的行数 + */ + public void setMaxNumberOrPreviewRow(int maxNumberOrPreviewRow) { + this.maxNumberOrPreviewRow = maxNumberOrPreviewRow; + } + + /** + * 是否展示工程界面 + * + * @return 是则返回true + */ + public boolean isShowProjectPane() { + return showProjectPane; + } + + /** + * 设置是否显示工程界面. + */ + public void setShowProjectPane(boolean showProjectPane) { + this.showProjectPane = showProjectPane; + } + + /** + * 是否展示数据界面 + * + * @return 是则返回true + */ + public boolean isShowDataPane() { + return showDataPane; + } + + /** + * 设置是否显示数据界面 + */ + public void setShowDataPane(boolean showDataPane) { + this.showDataPane = showDataPane; + } + + /** + * 返回最近选择的链接 + */ + public String getRecentSelectedConnection() { + return recentSelectedConnection; + } + + /** + * 设置最近选择的链接 + */ + public void setRecentSelectedConnection(String recentlySelectedConnectionName) { + this.recentSelectedConnection = recentlySelectedConnectionName; + } + + /** + * 返回激活码 + */ + public String getActivationKey() { + return activationKey; + } + + /** + * 设置激活码 + */ + public void setActivationKey(String activationKey) { + this.activationKey = activationKey; + } + + /** + * 返回Log的位置 + */ + public String getLogLocation() { + return logLocation; + } + + /** + * 设置Log的位置 + */ + public void setLogLocation(String logsLocation) { + this.logLocation = logsLocation; + } + + /** + * 返回日志的等级 + */ + public Level getLogLevel() { + return this.level; + } + + /** + * 设置log的等级 + */ + public void setLogLevel(Level level) { + this.level = level; + } + + /** + * 设置撤销的限制次数 + */ + public void setUndoLimit(int undoLimit) { + this.undoLimit = undoLimit; + } + + /** + * 返回撤销的限制次数 + */ + public int getUndoLimit() { + return undoLimit; + } + + public String getEncryptionKey() { + return encryptionKey; + } + + public void setEncryptionKey(String encryptionKey) { + this.encryptionKey = encryptionKey; + } + + public String getJdkHome() { + return this.jdkHome; + } + + public void setJdkHome(String home) { + this.jdkHome = home; + } + + public String getBBSName() { + return bbsName; + } + + public void setBBSName(String bbsName) { + this.bbsName = bbsName; + } + + public String getBBSPassword() { + return bbsPassword; + } + + public void setBBSPassword(String bbsPassword) { + this.bbsPassword = bbsPassword; + } + + public String getLastShowBBSTime() { + return lastShowBBSTime; + } + + public void setLastShowBBSTime(String lastShowBBSTime) { + this.lastShowBBSTime = lastShowBBSTime; + } + + public String getLastShowBBSNewsTime() { + return lastShowBBSNewsTime; + } + + public void setLastShowBBSNewsTime(String lastShowBBSNewsTime) { + this.lastShowBBSNewsTime = lastShowBBSNewsTime; + } + + private void readXMLVersion(XMLableReader reader){ + String tmpVal; + if ((tmpVal = reader.getElementValue()) != null) { + reader.setXmlVersionByString(tmpVal); + } + } + + private void readActiveKey(XMLableReader reader){ + String tmpVal; + if ((tmpVal = reader.getElementValue()) != null) { + this.setActivationKey(tmpVal); + } + } + + private void readLogLocation(XMLableReader reader){ + String tmpVal; + if ((tmpVal = reader.getElementValue()) != null) { + this.setLogLocation(tmpVal); + } + } + + private void readLanguage(XMLableReader reader){ + String tmpVal; + if ((tmpVal = reader.getElementValue()) != null) { + this.setLanguage(Integer.parseInt(tmpVal)); + } + } + + private void readJettyPort(XMLableReader reader){ + String tmpVal; + if ((tmpVal = reader.getElementValue()) != null) { + this.setJettyServerPort(Integer.parseInt(tmpVal)); + } + } + + private void readPageLengthUnit(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.pageLengthUnit = Short.parseShort(tmpVal); + } + } + + private void readReportLengthUnit(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.reportLengthUnit = Short.parseShort(tmpVal); + } + } + + private void readLastOpenFile(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.lastOpenFilePath = tmpVal; + } + } + + private void readEncrytionKey(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.encryptionKey = tmpVal; + } + } + + private void readBBSName(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.bbsName = tmpVal; + } + } + + private void readBBSPassword(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.bbsPassword = CodeUtils.passwordDecode(tmpVal); + } + } + + private void readLastBBSTime(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.lastShowBBSTime = tmpVal; + } + } + + private void readLastBBSNewsTime(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.lastShowBBSNewsTime = tmpVal; + } + } + + /** + * Read XML.
+ * The method will be invoked when read data from XML file.
+ * May override the method to read the data that you saved. + * + * @param reader the reader. + */ + @Override + public void readXML(XMLableReader reader) { + if (reader.isChildNode()) { + String name = reader.getTagName(); + if (name.equals("XMLVersion")) {// 兼容09.12.30前把XMLVersion写在根目录下的第一个标签中 + readXMLVersion(reader); + } else if (name.equals("Attributes")) { + this.readAttributes(reader); + } else if (name.equals("ReportPaneAttributions")) { + this.readReportPaneAttributions(reader); + } else if ("RecentOpenedFilePathList".equals(name) || "ResentOpenedFilePathList".equals(name)) { + this.readRecentOpenFileList(reader); + } else if ("Envs".equals(name) || name.equals("ReportServerMap")) { + this.readCurEnv(reader); + } else if (name.equals("ActivationKey")) { + readActiveKey(reader); + } else if ("LogLocation".equals(name)) { + readLogLocation(reader); + } else if ("LogLevel".equals(name)) { + this.readLogLevel(reader); + } else if ("Language".equals(name)) { + readLanguage(reader); + } else if ("JettyServerPort".equals(name)) { + readJettyPort(reader); + } else if ("PLengthUnit".equals(name)) { + readPageLengthUnit(reader); + } else if ("RLengthUnit".equals(name)) { + readReportLengthUnit(reader); + } else if ("LastOpenFilePath".equals(name)) { + readLastOpenFile(reader); + } else if ("EncryptionKey".equals(name)) { + readEncrytionKey(reader); + } else if ("jdkHome".equals(name)) { + this.jdkHome = reader.getElementValue(); + } else if ("bbsName".equals(name)){ + readBBSName(reader); + } else if ("bbsPassword".equals(name)){ + readBBSPassword(reader); + } else if ("lastBBSTime".equals(name)){ + readLastBBSTime(reader); + } else if ("lastBBSNewsTime".equals(name)){ + readLastBBSNewsTime(reader); + }else if ("uuid".equals(name)){ + readUUID(reader); + } else if ("status".equals(name)){ + readActiveStatus(reader); + } else if (ComparatorUtils.equals(CAS_PARAS,name)){ + readHttpsParas(reader); + }else { + readLayout(reader, name); + } + } + } + + private void readHttpsParas(XMLableReader reader){ + String tempVal; + if((tempVal = reader.getAttrAsString(CAS_CERTIFICATE_PATH, null)) != null){ + this.setCertificatePath(tempVal); + } + if((tempVal = reader.getAttrAsString(CAS_CERTIFICATE_PASSWORD, null)) != null){ + this.setCertificatePass(tempVal); + } + + this.setHttps(reader.getAttrAsBoolean("enable", false)); + } + + + private void readLayout(XMLableReader reader, String name) { + if ("LastEastRegionLayout".equals(name)) { + this.readLastEastRegionLayout(reader); + } else if ("LastWestRegionLayout".equals(name)) { + this.readLastWestRegionLayout(reader); + } + } + + private void readLastEastRegionLayout(XMLableReader reader) { + String tmpVal; + if ((tmpVal = reader.getAttrAsString("toolPaneY", null)) != null) { + this.setLastEastRegionToolPaneY(Integer.parseInt(tmpVal)); + } + if ((tmpVal = reader.getAttrAsString("containerWidth", null)) != null) { + // bug33217,705是好的,不知道711里因为什么把这段代码注释了,现打开 + this.setLastEastRegionContainerWidth(Integer.parseInt(tmpVal)); + } + } + + private void readLastWestRegionLayout(XMLableReader reader) { + String tmpVal; + if ((tmpVal = reader.getAttrAsString("toolPaneY", null)) != null) { + this.setLastWestRegionToolPaneY(Integer.parseInt(tmpVal)); + } + if ((tmpVal = reader.getAttrAsString("containerWidth", null)) != null) { + this.setLastWestRegionContainerWidth(Integer.parseInt(tmpVal)); + } + } + + + private void readAttributes(XMLableReader reader) { + String tmpVal; + if ((tmpVal = reader.getAttrAsString("windowBounds", null)) != null) { + this.setWindowBounds(BaseXMLUtils.readRectangle(tmpVal)); + } + if ((tmpVal = reader.getAttrAsString("DialogCurrentDirectory", null)) != null) { + this.setDialogCurrentDirectory(tmpVal); + } + if ((tmpVal = reader.getAttrAsString("CurrentDirectoryPrefix", null)) != null) { + this.setCurrentDirectoryPrefix(tmpVal); + } + this.setShowPaintToolBar(reader.getAttrAsBoolean("showPaintToolBar", true)); + this.setMaxNumberOrPreviewRow(reader.getAttrAsInt("maxNumberOrPreviewRow", 200)); + + this.setOracleSystemSpace(reader.getAttrAsBoolean("useOracleSystemSpace", true)); + this.setJoinProductImprove(reader.getAttrAsBoolean("joinProductImprove", true)); + this.setAutoBackUp(reader.getAttrAsBoolean("autoBackUp", true)); + this.setTemplateTreePaneExpanded(reader.getAttrAsBoolean("templateTreePaneExpanded", false)); + // peter:读取webinfLocation + if ((tmpVal = reader.getAttrAsString("webinfLocation", null)) != null) { + // marks:兼容6.1的 + // marks:设置默认的目录. + Env reportServer = LocalEnv.createEnv(tmpVal); + + String curReportServerName = Inter.getLocText("Server-Embedded_Server"); + this.putEnv(curReportServerName, reportServer); + this.setCurEnvName(curReportServerName); + } + + this.setShowProjectPane(reader.getAttrAsBoolean("showProjectPane", true)); + this.setShowDataPane(reader.getAttrAsBoolean("showDataPane", true)); + + if ((tmpVal = reader.getAttrAsString("recentSelectedConnection", null)) != null) { + this.setRecentSelectedConnection(tmpVal); + } + } + + private void readReportPaneAttributions(XMLableReader reader) { + String tmpVal; + this.setSupportUndo(reader.getAttrAsBoolean("supportUndo", true)); + this.setSupportDefaultParentCalculate(reader.getAttrAsBoolean("supportDefaultParentCalculate", true)); + this.setSupportStringToFormula(reader.getAttrAsBoolean("supportStringToFormula", true)); + this.setColumnHeaderVisible(reader.getAttrAsBoolean("columnHeaderVisible", true)); + this.setAutoCompleteShortcuts(reader.getAttrAsString("autoCompleteShortcuts", UIConstants.DEFAULT_AUTO_COMPLETE)); + this.setRowHeaderVisible(reader.getAttrAsBoolean("rowHeaderVisible", true)); + this.setVerticalScrollBarVisible(reader.getAttrAsBoolean("verticalScrollBarVisible", true)); + this.setHorizontalScrollBarVisible(reader.getAttrAsBoolean("horizontalScrollBarVisible", true)); + this.setSupportCellEditorDef(reader.getAttrAsBoolean("supportCellEditorDef", false)); + this.setDragPermited(reader.getAttrAsBoolean("isDragPermited", false)); + this.setUndoLimit(reader.getAttrAsInt("undoLimit", 5)); + this.setDefaultStringToFormula(reader.getAttrAsBoolean("defaultStringToFormula", false)); + if ((tmpVal = reader.getAttrAsString("gridLineColor", null)) != null) { + this.setGridLineColor(new Color(Integer.parseInt(tmpVal))); + } + if ((tmpVal = reader.getAttrAsString("paginationLineColor", null)) != null) { + this.setPaginationLineColor(new Color(Integer.parseInt(tmpVal))); + } + } + + private void readCurEnv(XMLableReader reader) { + String tmpVal; + // marks:设置默认的webInf名字 + if ((tmpVal = reader.getAttrAsString("currentEnv", null)) != null) { + this.setCurEnvName(tmpVal); + } + + reader.readXMLObject(new XMLReadable() { + + @Override + public void readXML(XMLableReader reader) { + if (reader.isAttr()) { + DesignerEnvManager.this.clearAllEnv(); + } + + if (reader.isChildNode()) { + if (reader.getTagName().equals("Env")) { // description. + // marks:获取名字 + String reportServerName = reader.getAttrAsString("name", null); + + Env env = readEnv(reader); + if (env == null) { + return; + } + + DesignerEnvManager.this.putEnv(reportServerName, env); + } + } + } + }); + + // xml读完之后,看一下nameEnvMap是不是长度为0 + if (nameEnvMap.isEmpty() && StableUtils.getInstallHome() != null) { + String install_home = StableUtils.getInstallHome(); + if (install_home != null && new java.io.File(install_home).exists()) { + nameEnvMap.put("Default", LocalEnv.createEnv(StableUtils.pathJoin(new String[]{ + install_home, ProjectConstants.WEBAPP_NAME, ProjectConstants.WEBINF_NAME + }))); + + curEnvName = "Default"; + } + } + } + + private void readRecentOpenFileList(XMLableReader reader) { + reader.readXMLObject(new XMLReadable() { + + @Override + public void readXML(XMLableReader reader) { + if (reader.isAttr()) { + DesignerEnvManager.this.recentOpenedFilePathList.clear(); + } + + if (reader.isChildNode()) { + String tmpVal; + String name = reader.getTagName(); + // alex:以前一直是写ResentOpenedFilePath + if ("ResentOpenedFilePath".equals(name) || "Path".equals(name)) { // description. + if ((tmpVal = reader.getElementValue()) != null) { + DesignerEnvManager.this.recentOpenedFilePathList.add(tmpVal); + } + } + } + } + }); + checkRecentOpenedFileNum(); + } + + + private void readLogLevel(XMLableReader reader) { + String level; + if ((level = reader.getElementValue()) != null) { + this.setLogLevel(FRLevel.getByName(level).getLevel()); + } + } + + + /** + * Write XML.
+ * The method will be invoked when save data to XML file.
+ * May override the method to save your own data. + * + * @param writer the PrintWriter. + */ + @Override + public void writeXML(XMLPrintWriter writer) { + writer.startTAG("Designer"); + + writeAttrues(writer); + writeReportPaneAttributions(writer); + writeRecentOpenFileAndEnvList(writer); + writeSomeAttr(writer); + writeLastEastRegionLayout(writer); + writeLastWestRegionLayout(writer); + writeUUID(writer); + writeActiveStatus(writer); + writeHttpsParas(writer); + writer.end(); + } + + public String getUUID() { + return StringUtils.isEmpty(uuid) ? UUID.randomUUID().toString() : uuid; + } + + public int getActiveKeyStatus() { + return activeKeyStatus; + } + + public void setActiveKeyStatus(int activeKeyStatus) { + this.activeKeyStatus = activeKeyStatus; + } + + //写入uuid + private void writeUUID(XMLPrintWriter writer){ + writer.startTAG("uuid"); + writer.textNode(getUUID()); + writer.end(); + } + + //读取uuid + private void readUUID(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.uuid = tmpVal; + } + } + + //写入激活状态 + private void writeActiveStatus(XMLPrintWriter writer){ + if (this.activeKeyStatus == 0){ + writer.startTAG("status"); + writer.textNode(this.activeKeyStatus + ""); + writer.end(); + } + } + + //读取激活状态 + private void readActiveStatus(XMLableReader reader){ + String tmpVal; + if (StringUtils.isNotBlank(tmpVal = reader.getElementValue())) { + this.activeKeyStatus = Integer.parseInt(tmpVal); + } + } + + private void writeRecentOpenFileAndEnvList(XMLPrintWriter writer) { + checkRecentOpenedFileNum(); + writer.startTAG("RecentOpenedFilePathList"); + int resentOpenedFilePathCount = Math.min(12, this.recentOpenedFilePathList.size()); + for (int i = 0; i < resentOpenedFilePathCount; i++) { + writer.startTAG("Path").textNode(recentOpenedFilePathList.get(i)).end(); + } + writer.end(); + + writer.startTAG("Envs"); + if (this.curEnvName != null) { + writer.attr("currentEnv", this.curEnvName); + } + Iterator nameIt = this.getEnvNameIterator(); + while (nameIt.hasNext()) { + String envName = nameIt.next(); + Env env = this.getEnv(envName); + + writeEnv(writer, envName, env); + } + + writer.end(); + } + + private void writeAttrues(XMLPrintWriter writer) { + writer.startTAG("Attributes"); + if (this.getWindowBounds() != null) { + writer.attr("windowBounds", BaseXMLUtils.getRectangleText(this.getWindowBounds())); + } + // Open directory. + if (this.getDialogCurrentDirectory() != null) { + writer.attr("DialogCurrentDirectory", this.getDialogCurrentDirectory()); + } + if (this.getCurrentDirectoryPrefix() != null) { + writer.attr("CurrentDirectoryPrefix", this.getCurrentDirectoryPrefix()); + } + writer.attr("showPaintToolBar", this.isShowPaintToolBar()) + .attr("maxNumberOrPreviewRow", this.getMaxNumberOrPreviewRow()) + .attr("showProjectPane", this.isShowProjectPane()) + .attr("showDataPane", this.isShowDataPane()); + if (StringUtils.isNotBlank(this.getRecentSelectedConnection())) { + writer.attr("recentSelectedConnection", this.getRecentSelectedConnection()); + } + if (!this.isOracleSystemSpace()) { + writer.attr("useOracleSystemSpace", this.isOracleSystemSpace()); + } + if (!this.isJoinProductImprove()){ + writer.attr("joinProductImprove", this.isJoinProductImprove()); + } + if (!this.isAutoBackUp()) { + writer.attr("autoBackUp", this.isAutoBackUp()); + } + if (this.isTemplateTreePaneExpanded()) { + writer.attr("templateTreePaneExpanded", this.isTemplateTreePaneExpanded()); + } + writer.end(); + } + + + private void writeLastEastRegionLayout(XMLPrintWriter writer) { + writer.startTAG("LastEastRegionLayout"); + if (this.getLastEastRegionToolPaneY() >= 0) { + writer.attr("toolPaneY ", this.getLastEastRegionToolPaneY()); + } + if (this.getLastEastRegionContainerWidth() >= 0) { + writer.attr("containerWidth", this.getLastEastRegionContainerWidth()); + } + writer.end(); + } + + private void writeLastWestRegionLayout(XMLPrintWriter writer) { + writer.startTAG("LastWestRegionLayout"); + if (this.getLastWestRegionToolPaneY() >= 0) { + writer.attr("toolPaneY ", this.getLastWestRegionToolPaneY()); + } + if (this.getLastWestRegionContainerWidth() >= 0) { + writer.attr("containerWidth", this.getLastWestRegionContainerWidth()); + } + writer.end(); + } + + + private void writeSomeAttr(XMLPrintWriter writer) { + if (this.activationKey != null) { + writer.startTAG("ActivationKey"); + writer.textNode(this.getActivationKey()); + writer.end(); + } + + if (this.encryptionKey != null && (!this.encryptionKey.equals(""))) { + writer.startTAG("EncryptionKey"); + writer.textNode(this.getEncryptionKey()); + writer.end(); + } + + if (this.logLocation != null && this.logLocation.length() > 0) { + writer.startTAG("LogLocation"); + writer.textNode(this.logLocation); + writer.end(); + } + + if (this.level != null) { + writer.startTAG("LogLevel"); + writer.textNode(FRLevel.getByLevel(this.level).getName()); + writer.end(); + } + if (StringUtils.isNotBlank(jdkHome)) { + writer.startTAG("jdkHome"); + writer.textNode(jdkHome); + writer.end(); + } + + writeBBSRelated(writer); + + writer.startTAG("PLengthUnit"); + writer.textNode("" + this.pageLengthUnit); + writer.end(); + + writer.startTAG("RLengthUnit"); + writer.textNode("" + this.reportLengthUnit); + writer.end(); + + writer.startTAG("LastOpenFilePath"); + writer.textNode("" + this.lastOpenFilePath); + writer.end(); + + writer.startTAG("Language").textNode(String.valueOf(this.language)).end() + .startTAG("JettyServerPort").textNode(String.valueOf(this.jettyServerPort)).end(); + } + + //写论坛相关的两个属性 + private void writeBBSRelated(XMLPrintWriter writer){ + if (StringUtils.isNotBlank(bbsName)) { + writer.startTAG("bbsName"); + writer.textNode(bbsName); + writer.end(); + } + + if (StringUtils.isNotBlank(bbsPassword)){ + writer.startTAG("bbsPassword"); + writer.textNode(CodeUtils.passwordEncode(bbsPassword)); + writer.end(); + } + + if (StringUtils.isNotEmpty(this.lastShowBBSTime)){ + writer.startTAG("lastBBSTime"); + writer.textNode(lastShowBBSTime); + writer.end(); + } + + if (StringUtils.isNotEmpty(this.lastShowBBSNewsTime)){ + writer.startTAG("lastBBSNewsTime"); + writer.textNode(lastShowBBSNewsTime); + writer.end(); + } + } + + private void writeHttpsParas(XMLPrintWriter writer){ + writer.startTAG(CAS_PARAS); + if(StringUtils.isNotBlank(certificatePath)){ + writer.attr(CAS_CERTIFICATE_PATH, certificatePath); + } + if(StringUtils.isNotBlank(certificatePass)){ + writer.attr(CAS_CERTIFICATE_PASSWORD, certificatePass); + } + if(isHttps){ + writer.attr("enable", true); + } + writer.end(); + } + + private void writeReportPaneAttributions(XMLPrintWriter writer) { + // eason: ReportPaneAttributions报表支持的 一些功能和Grid的GUI属性等等 + writer.startTAG("ReportPaneAttributions") + .attr("supportUndo", this.isSupportUndo()) + .attr("supportDefaultParentCalculate", this.isSupportDefaultParentCalculate()) + .attr("supportStringToFormula", this.isSupportStringToFormula()) + .attr("defaultStringToFormula", this.isDefaultStringToFormula()) + .attr("columnHeaderVisible", this.isColumnHeaderVisible()) + .attr("autoCompleteShortcuts", this.getAutoCompleteShortcuts()) + .attr("rowHeaderVisible", this.isRowHeaderVisible()) + .attr("verticalScrollBarVisible", this.isVerticalScrollBarVisible()) + .attr("horizontalScrollBarVisible", this.isHorizontalScrollBarVisible()) + .attr("supportCellEditorDef", this.isSupportCellEditorDef()) + .attr("isDragPermited", this.isDragPermited()) + .attr("gridLineColor", this.getGridLineColor().getRGB()) + .attr("paginationLineColor", this.getPaginationLineColor().getRGB()) + .attr("undoLimit", this.getUndoLimit()) + .end(); + } + + /* + * 写Env为xml + */ + private static void writeEnv(XMLPrintWriter writer, String name, Env env) { + if (env == null) { + return; + } + + writer.startTAG("Env").attr("class", env.getClass().getName()).attr("name", name); + + env.writeXML(writer); + + writer.end(); + } + + /* + * 从xml读Env + */ + private static Env readEnv(XMLableReader reader) { + Env env = null; + + String tmpVal; //temp value + if ((tmpVal = reader.getAttrAsString("class", null)) != null) { + if (tmpVal.endsWith(".LocalEnv")) { + env = LocalEnv.createEnv(); + } else if (tmpVal.endsWith(".RemoteEnv")) { + env = new RemoteEnv(); + } + } + + if (env == null) { + return env; + } + + reader.readXMLObject(env); + + return env; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/Exception/ValidationException.java b/designer_base/src/com/fr/design/Exception/ValidationException.java new file mode 100644 index 0000000000..0d56d9d187 --- /dev/null +++ b/designer_base/src/com/fr/design/Exception/ValidationException.java @@ -0,0 +1,11 @@ +package com.fr.design.Exception; + +public class ValidationException extends Exception { + + public ValidationException() { + } + + public ValidationException(String msg) { + super(msg); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/ExtraDesignClassManager.java b/designer_base/src/com/fr/design/ExtraDesignClassManager.java new file mode 100644 index 0000000000..9e557519d4 --- /dev/null +++ b/designer_base/src/com/fr/design/ExtraDesignClassManager.java @@ -0,0 +1,827 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.design.data.datapane.TableDataNameObjectCreator; +import com.fr.design.data.tabledata.wrapper.TableDataFactory; +import com.fr.design.fun.*; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.gui.core.WidgetOption; +import com.fr.design.gui.core.WidgetOptionFactory; +import com.fr.design.mainframe.App; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.menu.ShortCut; +import com.fr.design.widget.Appearance; +import com.fr.file.XMLFileManager; +import com.fr.form.ui.Widget; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.GeneralContext; +import com.fr.general.GeneralUtils; +import com.fr.plugin.PluginCollector; +import com.fr.plugin.PluginInvalidLevelException; +import com.fr.plugin.PluginLicenseManager; +import com.fr.plugin.PluginMessage; +import com.fr.stable.EnvChangedListener; +import com.fr.stable.StringUtils; +import com.fr.stable.fun.Authorize; +import com.fr.stable.fun.Level; +import com.fr.stable.plugin.ExtraDesignClassManagerProvider; +import com.fr.stable.plugin.PluginSimplify; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLableReader; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author : richie + * @since : 8.0 + * 用于设计器扩展的管理类 + */ +public class ExtraDesignClassManager extends XMLFileManager implements ExtraDesignClassManagerProvider { + + private static final String XML_TAG = "ExtraDesignClassManager"; + private static final String TEMPLATE_TREE_TAG = "TemplateTreeShortCut"; + + private static ClassLoader loader = Thread.currentThread().getContextClassLoader(); + + private static ExtraDesignClassManager classManager; + + public synchronized static ExtraDesignClassManager getInstance() { + if (classManager == null) { + classManager = new ExtraDesignClassManager(); + classManager.readXMLFile(); + } + + return classManager; + } + + static { + GeneralContext.addEnvChangedListener(new EnvChangedListener() { + public void envChanged() { + ExtraDesignClassManager.envChanged(); + } + }); + } + + + private synchronized static void envChanged() { + classManager = null; + } + + private List reportTDCreators; + private List serverTDCreators; + + private List parameterWidgetOptions; + private Map, Class> parameterWidgetOptionsMap; + private List webWidgetOptions; + + private List formWidgetOptions; + private List formWidgetContainerOptions; + private Map, Class> formWidgetOptionsMap; + + private List cellWidgetOptions; + private Map, Appearance> cellWidgetOptionMap; + private List connectionCreators; + private Set previewProviders; + + private Set highlightProviders; + + private TableDataCreatorProvider tableDataCreatorProvider; + + private List menuHandlers; + + private UIFormulaProcessor uiFormulaProcessor; + + private List presentKindProviders; + + private List exportToolBarProviders; + + private Set templateTreeShortCutProviders; + + private List submitProviders; + + private List globalListenerProviders; + + private List javaScriptActionProviders; + + private TitlePlaceProcessor titlePlaceProcessor; + + private FormElementCaseEditorProcessor formElementCaseEditorProcessor; + + private IndentationUnitProcessor indentationUnitProcessor; + + private CellAttributeProvider cellAttributeProvider; + + private Set hyperlinkGroupProviders; + + public void addSupportDesignApps(Level level, PluginSimplify simplify) throws Exception { + validAPILevel(level, App.CURRENT_LEVEL, simplify.getPluginName()); + App provider = (App) level; + DesignerFrame.registApp(provider); + } + + private void validAPILevel(Level level, int targetLevel, String pluginName) { + if (PluginCollector.getCollector().isError(level, targetLevel, pluginName)) { + throw new PluginInvalidLevelException(pluginName, level.currentAPILevel()); + } + } + + public HyperlinkProvider[] getHyperlinkProvider() { + if (hyperlinkGroupProviders == null) { + return new HyperlinkProvider[0]; + } + return hyperlinkGroupProviders.toArray(new HyperlinkProvider[hyperlinkGroupProviders.size()]); + } + + public void addHyperlinkProvider(Level level, PluginSimplify simplify) throws Exception { + if (hyperlinkGroupProviders == null) { + hyperlinkGroupProviders = new HashSet(); + } + validAPILevel(level, HyperlinkProvider.CURRENT_LEVEL, simplify.getPluginName()); + HyperlinkProvider provider = (HyperlinkProvider) level; + hyperlinkGroupProviders.add(provider); + } + + public GlobalListenerProvider[] getGlobalListenerProvider() { + if (globalListenerProviders == null) { + return new GlobalListenerProvider[0]; + } + return globalListenerProviders.toArray(new GlobalListenerProvider[globalListenerProviders.size()]); + } + + /** + * 获取javaScriptPane + * + * @return javaScriptPane集合 + */ + public List getJavaScriptActionProvider() { + return javaScriptActionProviders; + } + + /** + * 添加一个javaScriptPane + */ + public void addJavaScriptActionProvider(Level level, PluginSimplify simplify) throws Exception { + if (javaScriptActionProviders == null) { + javaScriptActionProviders = new ArrayList(); + } + validAPILevel(level, JavaScriptActionProvider.CURRENT_LEVEL, simplify.getPluginName()); + JavaScriptActionProvider provider = (JavaScriptActionProvider) level; + if (!javaScriptActionProviders.contains(provider)) { + javaScriptActionProviders.add(provider); + } + } + + /** + * 添加全局监听 + */ + public void addGlobalListenerProvider(Level level, PluginSimplify simplify) throws Exception { + if (globalListenerProviders == null) { + globalListenerProviders = new ArrayList(); + } + validAPILevel(level, GlobalListenerProvider.CURRENT_LEVEL, simplify.getPluginName()); + GlobalListenerProvider provider = (GlobalListenerProvider) level; + if (!globalListenerProviders.contains(provider)) { + globalListenerProviders.add(provider); + } + } + + public TableDataCreatorProvider getTableDataCreatorProvider() { + return tableDataCreatorProvider; + } + + public void setTableDataCreatorProvider(String className) { + if (StringUtils.isNotBlank(className)) { + try { + Class clazz = Class.forName(className); + tableDataCreatorProvider = (TableDataCreatorProvider) clazz.newInstance(); + } catch (Exception e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + } + } + + public SubmitProvider[] getSubmitProviders() { + if (submitProviders == null) { + return new SubmitProvider[0]; + } + return submitProviders.toArray(new SubmitProvider[submitProviders.size()]); + } + + /** + * 添加提交接口 + */ + public void addSubmitProvider(Level level, PluginSimplify simplify) throws Exception { + if (submitProviders == null) { + submitProviders = new ArrayList(); + } + validAPILevel(level, SubmitProvider.CURRENT_LEVEL, simplify.getPluginName()); + SubmitProvider provider = (SubmitProvider) level; + if (!submitProviders.contains(provider)) { + submitProviders.add(provider); + } + } + + public TableDataNameObjectCreator[] getReportTableDataCreators() { + if (reportTDCreators == null) { + return new TableDataNameObjectCreator[0]; + } else { + return reportTDCreators.toArray(new TableDataNameObjectCreator[reportTDCreators.size()]); + } + } + + + /** + * 添加reportTDCreators + * + * @param className 类名 + */ + public void addTableDataNameObjectCreator(String className, PluginSimplify simplify) { + if (StringUtils.isNotBlank(className)) { + try { + if (reportTDCreators == null) { + reportTDCreators = new ArrayList(); + } + TableDataNameObjectCreator creator = createTableDataNameObjectCreator(className, simplify); + if (!reportTDCreators.contains(creator)) { + reportTDCreators.add(creator); + } + } catch (Exception e) { + PluginMessage.remindUpdate(className + e.getMessage()); + } + } + } + + + /** + * 添加serverTDCreators + * + * @return 类名 + */ + public TableDataNameObjectCreator[] getServerTableDataCreators() { + if (serverTDCreators == null) { + return new TableDataNameObjectCreator[0]; + } else { + return serverTDCreators.toArray(new TableDataNameObjectCreator[serverTDCreators.size()]); + } + } + + /** + * 添加serverTDCreators + * + * @param className 类名 + */ + public void addServerTableDataNameObjectCreator(String className, PluginSimplify simplify) { + if (StringUtils.isNotBlank(className)) { + try { + if (serverTDCreators == null) { + serverTDCreators = new ArrayList(); + } + TableDataNameObjectCreator creator = createTableDataNameObjectCreator(className, simplify); + if (!serverTDCreators.contains(creator)) { + serverTDCreators.add(creator); + } + } catch (Exception e) { + PluginMessage.remindUpdate(className + e.getMessage()); + } + } + } + + private TableDataNameObjectCreator createTableDataNameObjectCreator(String className, PluginSimplify simplify) throws Exception { + Class clazz = loader.loadClass(className); + TableDataDefineProvider provider = (TableDataDefineProvider) clazz.newInstance(); + validAPILevel(provider, TableDataDefineProvider.CURRENT_LEVEL, simplify.getPluginName()); + TableDataNameObjectCreator creator = new TableDataNameObjectCreator( + provider.nameForTableData(), + provider.prefixForTableData(), + provider.iconPathForTableData(), + provider.classForTableData(), + provider.classForInitTableData(), + provider.appearanceForTableData() + ); + TableDataFactory.register(provider.classForTableData(), creator); + return creator; + } + + public Map, Class> getParameterWidgetOptionsMap() { + if (parameterWidgetOptionsMap == null) { + return new HashMap, Class>(); + } else { + return parameterWidgetOptionsMap; + } + } + + public WidgetOption[] getParameterWidgetOptions() { + if (parameterWidgetOptions == null) { + return new WidgetOption[0]; + } else { + return parameterWidgetOptions.toArray(new WidgetOption[parameterWidgetOptions.size()]); + } + } + + /** + * 添加parameterWidgetOptionsMap + */ + public void addParameterWidgetOption(Level level, PluginSimplify simplify) throws Exception { + if (parameterWidgetOptions == null) { + parameterWidgetOptions = new ArrayList(); + } + if (parameterWidgetOptionsMap == null) { + parameterWidgetOptionsMap = new HashMap, Class>(); + } + validAPILevel(level, ParameterWidgetOptionProvider.CURRENT_LEVEL, simplify.getPluginName()); + + ParameterWidgetOptionProvider provider = (ParameterWidgetOptionProvider) level; + WidgetOption option = WidgetOptionFactory.createByWidgetClass( + provider.nameForWidget(), + BaseUtils.readIcon(provider.iconPathForWidget()), + provider.classForWidget() + ); + parameterWidgetOptionsMap.put(provider.classForWidget(), provider.appearanceForWidget()); + parameterWidgetOptions.add(option); + } + + /** + * 添加 webWidgetOptions + * + * @return 返回 webWidgetOptions + */ + public void addWebWidgetOption(Level level, PluginSimplify simplify) throws Exception { + if (webWidgetOptions == null) { + webWidgetOptions = new ArrayList(); + } + validAPILevel(level, ToolbarItemProvider.CURRENT_LEVEL, simplify.getPluginName()); + + ToolbarItemProvider provider = (ToolbarItemProvider) level; + WidgetOption option = WidgetOptionFactory.createByWidgetClass( + provider.nameForWidget(), + BaseUtils.readIcon(provider.iconPathForWidget()), + provider.classForWidget() + ); + if (!webWidgetOptions.contains(option)) { + webWidgetOptions.add(option); + } + } + + public Map, Class> getFormWidgetOptionsMap() { + if (formWidgetOptionsMap == null) { + return new HashMap, Class>(); + } else { + return formWidgetOptionsMap; + } + } + + public WidgetOption[] getFormWidgetOptions() { + if (formWidgetOptions == null) { + return new WidgetOption[0]; + } else { + return formWidgetOptions.toArray(new WidgetOption[formWidgetOptions.size()]); + } + } + + public WidgetOption[] getWebWidgetOptions() { + if (webWidgetOptions == null) { + return new WidgetOption[0]; + } else { + return webWidgetOptions.toArray(new WidgetOption[webWidgetOptions.size()]); + } + } + + public WidgetOption[] getFormWidgetContainerOptions() { + if (formWidgetContainerOptions == null) { + return new WidgetOption[0]; + } else { + return formWidgetContainerOptions.toArray(new WidgetOption[formWidgetContainerOptions.size()]); + } + } + + /** + * 添加 formWidgetContainerOptions + */ + public void addFormWidgetOption(Level level, PluginSimplify simplify) throws Exception { + if (formWidgetOptions == null) { + formWidgetOptions = new ArrayList(); + } + if (formWidgetContainerOptions == null) { + formWidgetContainerOptions = new ArrayList(); + } + if (formWidgetOptionsMap == null) { + formWidgetOptionsMap = new HashMap, Class>(); + } + validAPILevel(level, FormWidgetOptionProvider.CURRENT_LEVEL, simplify.getPluginName()); + + FormWidgetOptionProvider provider = (FormWidgetOptionProvider) level; + WidgetOption option = WidgetOptionFactory.createByWidgetClass( + provider.nameForWidget(), + BaseUtils.readIcon(provider.iconPathForWidget()), + provider.classForWidget() + ); + formWidgetOptionsMap.put(provider.classForWidget(), provider.appearanceForWidget()); + if (provider.isContainer()) { + formWidgetContainerOptions.add(option); + } else { + formWidgetOptions.add(option); + } + } + + public Map, Appearance> getCellWidgetOptionsMap() { + if (cellWidgetOptionMap == null) { + return new HashMap, Appearance>(); + } else { + return cellWidgetOptionMap; + } + } + + public WidgetOption[] getCellWidgetOptions() { + if (cellWidgetOptions == null) { + return new WidgetOption[0]; + } else { + return cellWidgetOptions.toArray(new WidgetOption[cellWidgetOptions.size()]); + } + } + + /** + * 添加cellWidgetOptionMap + */ + public void addCellWidgetOption(Level level, PluginSimplify simplify) throws Exception { + if (cellWidgetOptions == null) { + cellWidgetOptions = new ArrayList(); + } + if (cellWidgetOptionMap == null) { + cellWidgetOptionMap = new HashMap, Appearance>(); + } + validAPILevel(level, CellWidgetOptionProvider.CURRENT_LEVEL, simplify.getPluginName()); + + CellWidgetOptionProvider provider = (CellWidgetOptionProvider) level; + WidgetOption option = WidgetOptionFactory.createByWidgetClass( + provider.nameForWidget(), + BaseUtils.readIcon(provider.iconPathForWidget()), + provider.classForWidget() + ); + if (cellWidgetOptions.contains(option)) { + return; + } + cellWidgetOptionMap.put(provider.classForWidget(), new Appearance(provider.appearanceForWidget(), Appearance.P_MARK + cellWidgetOptionMap.size())); + cellWidgetOptions.add(option); + } + + + /** + * 添加 connectionCreators + * + * @param className 类名 + */ + public void addConnection(String className, PluginSimplify simplify) { + if (StringUtils.isNotBlank(className)) { + try { + Class clazz = Class.forName(className); + if (connectionCreators == null) { + connectionCreators = new ArrayList(); + } + ConnectionProvider provider = (ConnectionProvider) clazz.newInstance(); + validAPILevel(provider, ConnectionProvider.CURRENT_LEVEL, simplify.getPluginName()); + NameObjectCreator creator = new NameObjectCreator( + provider.nameForConnection(), + provider.iconPathForConnection(), + provider.classForConnection(), + provider.appearanceForConnection() + ); + if (!connectionCreators.contains(creator)) { + connectionCreators.add(creator); + } + } catch (Exception e) { + PluginMessage.remindUpdate(className + e.getMessage()); + } + } + } + + public NameObjectCreator[] getConnections() { + if (connectionCreators == null) { + return new NameObjectCreator[0]; + } else { + return connectionCreators.toArray(new NameObjectCreator[connectionCreators.size()]); + } + } + + public PreviewProvider[] getPreviewProviders() { + if (previewProviders == null) { + return new PreviewProvider[0]; + } + return previewProviders.toArray(new PreviewProvider[previewProviders.size()]); + } + + /** + * 添加previewProviders + */ + public void addPreviewProvider(Level level, PluginSimplify simplify) throws Exception { + if (previewProviders == null) { + previewProviders = new HashSet(); + } + validAPILevel(level, PreviewProvider.CURRENT_LEVEL, simplify.getPluginName()); + + PreviewProvider provider = (PreviewProvider) level; + if (!previewProviders.contains(provider)) { + previewProviders.add(provider); + } + } + + public HighlightProvider[] getHighlightProviders() { + if (highlightProviders == null) { + return new HighlightProvider[0]; + } + return highlightProviders.toArray(new HighlightProvider[highlightProviders.size()]); + } + + /** + * 添加 highlightProviders + */ + public void addTemplateTreeShortCutProvider(Level level, PluginSimplify simplify) throws Exception { + if (templateTreeShortCutProviders == null) { + templateTreeShortCutProviders = new HashSet(); + } + validAPILevel(level, ShortCut.CURRENT_LEVEL, simplify.getPluginName()); + ShortCut provider = (ShortCut) level; + templateTreeShortCutProviders.add(provider); + } + + public ShortCut[] getTemplateTreeShortCutProviders() { + if (templateTreeShortCutProviders == null) { + return new ShortCut[0]; + } + return templateTreeShortCutProviders.toArray(new ShortCut[templateTreeShortCutProviders.size()]); + } + + /** + * 添加 highlightProviders + */ + public void addConditionProvider(Level level, PluginSimplify simplify) throws Exception { + if (highlightProviders == null) { + highlightProviders = new HashSet(); + } + validAPILevel(level, HighlightProvider.CURRENT_LEVEL, simplify.getPluginName()); + HighlightProvider provider = (HighlightProvider) level; + highlightProviders.add(provider); + } + + public Feedback getFeedback() { + try { + Class clazz = GeneralUtils.classForName("com.fr.design.feedback.CurrentFeedback"); + if (clazz != null) { + return (Feedback) clazz.newInstance(); + } + } catch (Exception e) { + FRLogger.getLogger().info("no feed back support"); + } + return Feedback.EMPTY; + } + + public MenuHandler[] getMenuHandlers(String category) { + if (menuHandlers == null) { + return new MenuHandler[0]; + } + List handlers = new ArrayList(); + for (MenuHandler handler : menuHandlers) { + if (ComparatorUtils.equals(category, handler.category())) { + handlers.add(handler); + } + } + return handlers.toArray(new MenuHandler[handlers.size()]); + } + + /** + * 添加menuHandlers + */ + public void addMenuHandler(Level level, PluginSimplify simplify) throws Exception { + if (menuHandlers == null) { + menuHandlers = new ArrayList(); + } + validAPILevel(level, MenuHandler.CURRENT_LEVEL, simplify.getPluginName()); + MenuHandler handler = (MenuHandler) level; + if (!menuHandlers.contains(handler)) { + menuHandlers.add(handler); + } + } + + public UIFormulaProcessor getUIFormulaProcessor() { + return uiFormulaProcessor; + } + + public void setUIFormulaProcessor(Level level, PluginSimplify simplify) throws Exception { + validAPILevel(level, UIFormulaProcessor.CURRENT_LEVEL, simplify.getPluginName()); + uiFormulaProcessor = (UIFormulaProcessor) level; + } + + public PresentKindProvider[] getPresentKindProviders() { + if (presentKindProviders == null) { + return new PresentKindProvider[0]; + } + return presentKindProviders.toArray(new PresentKindProvider[presentKindProviders.size()]); + } + + /** + * 添加presentKindProviders + */ + public void addPresentKindProvider(Level level, PluginSimplify simplify) throws Exception { + if (presentKindProviders == null) { + presentKindProviders = new ArrayList(); + } + validAPILevel(level, PresentKindProvider.CURRENT_LEVEL, simplify.getPluginName()); + PresentKindProvider provider = (PresentKindProvider) level; + presentKindProviders.add(provider); + } + + public ExportToolBarProvider[] getExportToolBarProviders() { + if (exportToolBarProviders == null) { + return new ExportToolBarProvider[0]; + } + return exportToolBarProviders.toArray(new ExportToolBarProvider[exportToolBarProviders.size()]); + } + + /** + * 添加exportToolBarProviders + */ + public void addExportToolBarProvider(Level level, PluginSimplify simplify) throws Exception { + if (exportToolBarProviders == null) { + exportToolBarProviders = new ArrayList(); + } + validAPILevel(level, ExportToolBarProvider.CURRENT_LEVEL, simplify.getPluginName()); + ExportToolBarProvider provider = (ExportToolBarProvider) level; + if (!exportToolBarProviders.contains(provider)) { + exportToolBarProviders.add(provider); + } + } + + public TitlePlaceProcessor getTitlePlaceProcessor() { + return titlePlaceProcessor; + } + + public void setTitlePlaceProcessor(Level level, PluginSimplify simplify) throws Exception { + validAPILevel(level, TitlePlaceProcessor.CURRENT_LEVEL, simplify.getPluginName()); + titlePlaceProcessor = (TitlePlaceProcessor) level; + } + + public FormElementCaseEditorProcessor getPropertyTableEditor() { + return formElementCaseEditorProcessor; + } + + public void setPropertyTableEditor(Level level, PluginSimplify simplify) throws Exception { + validAPILevel(level, FormElementCaseEditorProcessor.CURRENT_LEVEL, simplify.getPluginName()); + formElementCaseEditorProcessor = (FormElementCaseEditorProcessor) level; + } + + public IndentationUnitProcessor getIndentationUnitEditor() { + return indentationUnitProcessor; + } + + public void setIndentationUnitEditor(Level level, PluginSimplify simplify) throws Exception { + validAPILevel(level, IndentationUnitProcessor.CURRENT_LEVEL, simplify.getPluginName()); + indentationUnitProcessor = (IndentationUnitProcessor) level; + } + + public CellAttributeProvider getCelllAttributeProvider() { + return cellAttributeProvider; + } + + public void setCellAttributeProvider(Level level, PluginSimplify simplify) throws Exception { + validAPILevel(level, CellAttributeProvider.CURRENT_LEVEL, simplify.getPluginName()); + cellAttributeProvider = (CellAttributeProvider) level; + } + + /** + * 文件名 + * + * @return 文件名 + */ + @Override + public String fileName() { + return "designer.xml"; + } + + /** + * 读xml + * + * @param reader xml对象 + */ + public void readXML(XMLableReader reader) { + readXML(reader, null, PluginSimplify.NULL); + } + + /** + * 读xml + * + * @param reader xml对象 + * @param extraDesignInterfaceList 接口列表 + */ + @Override + public void readXML(XMLableReader reader, List extraDesignInterfaceList, PluginSimplify simplify) { + if (reader.isChildNode()) { + String tagName = reader.getTagName(); + if (extraDesignInterfaceList != null) { + extraDesignInterfaceList.add(tagName); + } + String className = reader.getAttrAsString("class", ""); + if (StringUtils.isEmpty(className)) { + return; + } + readLevelTag(tagName, className, simplify); + } + } + + private void readLevelTag(String tagName, String className, PluginSimplify simplify) { + try { + //实现了Level接口的, 可以直接newInstance子类的 + Class clazz = loader.loadClass(className); + Authorize authorize = clazz.getAnnotation(Authorize.class); + if (authorize != null) { + PluginLicenseManager.getInstance().registerPaid(authorize, simplify); + } + + Level impl = (Level) clazz.newInstance(); + //控件 + readWidgetRelated(tagName, impl, simplify); + //数据集, 数据连接 + readTableDataRelated(tagName, className, simplify); + if (tagName.equals(ParameterWidgetOptionProvider.XML_TAG)) { + addParameterWidgetOption(impl, simplify); + } else if (tagName.equals(PreviewProvider.MARK_STRING)) { + addPreviewProvider(impl, simplify); + } else if (tagName.equals(HighlightProvider.MARK_STRING)) { + addConditionProvider(impl, simplify); + } else if (tagName.equals(MenuHandler.MARK_STRING)) { + addMenuHandler(impl, simplify); + } else if (tagName.equals(UIFormulaProcessor.MARK_STRING)) { + setUIFormulaProcessor(impl, simplify); + } else if (tagName.equals(PresentKindProvider.MARK_STRING)) { + addPresentKindProvider(impl, simplify); + } else if (tagName.equals(TEMPLATE_TREE_TAG)) { + addTemplateTreeShortCutProvider(impl, simplify); + } else if (tagName.equals(SubmitProvider.MARK_STRING)) { + addSubmitProvider(impl, simplify); + } else if (tagName.equals(GlobalListenerProvider.XML_TAG)) { + addGlobalListenerProvider(impl, simplify); + } else if (tagName.equals(JavaScriptActionProvider.XML_TAG)) { + addJavaScriptActionProvider(impl, simplify); + } else if (tagName.equals(TitlePlaceProcessor.MARK_STRING)) { + setTitlePlaceProcessor(impl, simplify); + } else if (tagName.equals(FormElementCaseEditorProcessor.MARK_STRING)) { + setPropertyTableEditor(impl, simplify); + } else if (tagName.equals(IndentationUnitProcessor.MARK_STRING)) { + setIndentationUnitEditor(impl, simplify); + } else if (tagName.equals(CellAttributeProvider.MARK_STRING)) { + setCellAttributeProvider(impl, simplify); + } else if (tagName.equals(HyperlinkProvider.XML_TAG)) { + addHyperlinkProvider(impl, simplify); + } else if (tagName.equals(App.MARK_STRING)) { + addSupportDesignApps(impl, simplify); + } + } catch (PluginInvalidLevelException e) { + PluginMessage.remindUpdate(e.getMessage()); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + } + + private void readTableDataRelated(String tagName, String className, PluginSimplify simplify) { + if (tagName.equals(TableDataCreatorProvider.XML_TAG)) { + setTableDataCreatorProvider(className); + } else if (tagName.equals(TableDataDefineProvider.XML_TAG)) { + addTableDataNameObjectCreator(className, simplify); + } else if (tagName.equals(ServerTableDataDefineProvider.XML_TAG)) { + addServerTableDataNameObjectCreator(className, simplify); + } else if (tagName.equals(ConnectionProvider.XML_TAG)) { + addConnection(className, simplify); + } + } + + private void readWidgetRelated(String tagName, Level impl, PluginSimplify simplify) throws Exception { + if (tagName.equals(FormWidgetOptionProvider.XML_TAG)) { + addFormWidgetOption(impl, simplify); + } else if (tagName.equals(ToolbarItemProvider.XML_TAG)) { + addWebWidgetOption(impl, simplify); + } else if (tagName.equals(ExportToolBarProvider.XML_TAG)) { + addExportToolBarProvider(impl, simplify); + } else if (tagName.equals(CellWidgetOptionProvider.XML_TAG)) { + addCellWidgetOption(impl, simplify); + } + } + + /** + * 写xml + * + * @param writer xml对象 + */ + public void writeXML(XMLPrintWriter writer) { + writer.startTAG(XML_TAG); + writer.end(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/RestartHelper.java b/designer_base/src/com/fr/design/RestartHelper.java new file mode 100644 index 0000000000..4dff98615c --- /dev/null +++ b/designer_base/src/com/fr/design/RestartHelper.java @@ -0,0 +1,191 @@ +package com.fr.design; + +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.GeneralUtils; +import com.fr.stable.ArrayUtils; +import com.fr.stable.OperatingSystem; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * @author richie + * @date 2015-03-26 + * @since 8.0 + */ +public class RestartHelper { + + public static final String RECORD_FILE = StableUtils.pathJoin(StableUtils.getInstallHome(), "delete.properties"); + public static final String MOVE_FILE = StableUtils.pathJoin(StableUtils.getInstallHome(), "move.properties"); + + + /** + * 把要删除的文件都记录到delete.properties中 + * + * @param files 要删除的文件 + */ + public static void saveFilesWhichToDelete(String[] files) { + Properties properties = new Properties(); + File file = new File(RECORD_FILE); + if (file.exists()) { + try { + FileInputStream file2DeleteInputStream = new FileInputStream(file); + properties.load(file2DeleteInputStream); + file2DeleteInputStream.close(); + } catch (IOException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + } + if (ArrayUtils.getLength(files) != 0) { + int size = properties.values().size(); + for (int i = 0, len = files.length; i < len; i++) { + properties.setProperty((i + size) + "", files[i]); + } + } + try { + FileOutputStream file2DeleteOutputStream = new FileOutputStream(file); + properties.store(file2DeleteOutputStream, "save"); + file2DeleteOutputStream.close(); + } catch (IOException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + } + + /** + * 把要移动的文件都记录到move.properties中 + * + * @param map 移动的文件 + */ + public static void saveFilesWhichToMove(Map map) { + Properties properties = new Properties(); + File file = new File(MOVE_FILE); + if (file.exists()) { + try { + FileInputStream file2MoveInputStream = new FileInputStream(file); + properties.load(file2MoveInputStream); + file2MoveInputStream.close(); + } catch (IOException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + } + if (!map.isEmpty()) { + for (String key : map.keySet()) { + properties.setProperty(key, map.get(key)); + } + } + try { + FileOutputStream file2MoveOutputStream = new FileOutputStream(file); + properties.store(file2MoveOutputStream, "save"); + file2MoveOutputStream.close(); + } catch (IOException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + } + + /** + * 需要重启启动器用于删除文件 + */ + public static void deleteRecordFilesWhenStart() { + File ff = new File(RECORD_FILE); + // 如果文件不存在就直接返回了 + if (!ff.exists()) { + return; + } + restart(); + } + + private static boolean deleteWhenDebug() { + File ff = new File(RECORD_FILE); + Properties properties = new Properties(); + try { + properties.load(new FileInputStream(ff)); + } catch (IOException ignore) { + return true; + } + + for (Map.Entry entry : properties.entrySet()) { + String filePath = GeneralUtils.objectToString(entry.getValue()); + File file = new File(filePath); + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files != null) { + for (File f : files) { + deleteFile(f); + } + } + } + deleteFile(file); + } + return ff.delete(); + } + + private static boolean deleteFile(File f) { + return StableUtils.deleteFile(f); + } + + /** + * 重启设计器 + */ + public static void restart() { + restart(ArrayUtils.EMPTY_STRING_ARRAY); + } + + /** + * 重启设计器并删除某些特定的文件 + * + * @param filesToBeDelete 要删除的文件集合 + */ + public static void restart(String[] filesToBeDelete) { + String installHome = StableUtils.getInstallHome(); + if (StringUtils.isEmpty(installHome) || ComparatorUtils.equals(".", installHome)) { + deleteWhenDebug(); + return; + } + + try { + if (OperatingSystem.isMacOS()) { + restartInMacOS(installHome, filesToBeDelete); + } else { + restartInWindows(installHome, filesToBeDelete); + } + } catch (Exception e) { + FRLogger.getLogger().error(e.getMessage()); + } finally { + DesignerContext.getDesignerFrame().exit(); + } + } + + private static void restartInMacOS(String installHome, String[] filesToBeDelete) throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + List commands = new ArrayList(); + commands.add("open"); + commands.add(installHome + File.separator + "bin" + File.separator + "restart.app"); + if (ArrayUtils.isNotEmpty(filesToBeDelete)) { + commands.add("--args"); + commands.add(StableUtils.join(filesToBeDelete, "+")); + } + builder.command(commands); + builder.start(); + } + + private static void restartInWindows(String installHome, String[] filesToBeDelete) throws Exception { + ProcessBuilder builder = new ProcessBuilder(); + List commands = new ArrayList(); + commands.add(installHome + File.separator + "bin" + File.separator + "restart.exe"); + if (ArrayUtils.isNotEmpty(filesToBeDelete)) { + commands.add(StableUtils.join(filesToBeDelete, "+")); + } + builder.command(commands); + builder.start(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/AllowAuthorityEditAction.java b/designer_base/src/com/fr/design/actions/AllowAuthorityEditAction.java new file mode 100644 index 0000000000..5d0ccf2d09 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/AllowAuthorityEditAction.java @@ -0,0 +1 @@ +package com.fr.design.actions; import com.fr.base.BaseUtils; import com.fr.design.constants.UIConstants; import com.fr.design.menu.KeySetUtils; import com.fr.design.roleAuthority.ReportAndFSManagePane; import com.fr.design.roleAuthority.RolesAlreadyEditedPane; import com.fr.design.designer.TargetComponent; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.mainframe.*; /** * Author : daisy * Date: 13-8-30 * Time: 上午10:12 */ public class AllowAuthorityEditAction extends TemplateComponentAction { public AllowAuthorityEditAction(TargetComponent t) { super(t); this.setMenuKeySet(KeySetUtils.ALLOW_AUTHORITY_EDIT); this.setName(getMenuKeySet().getMenuName()); this.setMnemonic(getMenuKeySet().getMnemonic()); this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/allow_authority_edit.png")); } /** * 撤销 */ public void prepare4Undo() { HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().iniAuthorityUndoState(); } /** * 执行动作 * * @return 是否执行成功 */ public boolean executeActionReturnUndoRecordNeeded() { TargetComponent tc = getEditingComponent(); if (tc == null) { return false; } cleanAuthorityCondition(); //进入时是格式刷则取消格式刷 if (DesignerContext.getFormatState() != DesignerContext.FORMAT_STATE_NULL) { tc.cancelFormat(); } BaseUtils.setAuthorityEditing(true); ReportAndFSManagePane.getInstance().refreshDockingView(); RolesAlreadyEditedPane.getInstance().refreshDockingView(); WestRegionContainerPane.getInstance().replaceDownPane(ReportAndFSManagePane.getInstance()); DesignerContext.getDesignerFrame().setCloseMode(UIConstants.CLOSE_OF_AUTHORITY); DesignerContext.getDesignerFrame().resetToolkitByPlus(tc.getToolBarMenuDockPlus()); DesignerContext.getDesignerFrame().needToAddAuhtorityPaint(); EastRegionContainerPane.getInstance().replaceUpPane(tc.getEastUpPane()); DesignerContext.getDesignerFrame().refreshDottedLine(); EastRegionContainerPane.getInstance().replaceDownPane(RolesAlreadyEditedPane.getInstance()); //画虚线 return true; } /** * 进入权限编辑之前将权限编辑界面重置一下工具栏 */ private void cleanAuthorityCondition() { java.util.List> opendedTemplate = HistoryTemplateListPane.getInstance().getHistoryList(); for (int i = 0; i < opendedTemplate.size(); i++) { opendedTemplate.get(i).cleanAuthorityUndo(); } } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/CheckBoxAction.java b/designer_base/src/com/fr/design/actions/CheckBoxAction.java new file mode 100644 index 0000000000..4734d9ac66 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/CheckBoxAction.java @@ -0,0 +1,41 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions; + +import javax.swing.JCheckBoxMenuItem; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.imenu.UICheckBoxMenuItem; + +/** + * check box + */ +public abstract class CheckBoxAction extends UpdateAction { + public UICheckBoxMenuItem createMenuItem() { + Object object = this.getValue(UICheckBoxMenuItem.class.getName()); + if (object == null) { + object = createCheckBoxMenuItem(this); + this.putValue(UICheckBoxMenuItem.class.getName(), object); + } + + // isSelected. + ((JCheckBoxMenuItem) object).setSelected(this.isSelected()); + + return (UICheckBoxMenuItem) object; + } + + + + public abstract boolean isSelected(); + + + public boolean isRadioSelect() { + return false; + } + + public void setSelected(boolean isSelected) { + UIButton button = (UIButton) this.createToolBarComponent(); + button.setSelected(isSelected); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/ExitAuthorityEditAction.java b/designer_base/src/com/fr/design/actions/ExitAuthorityEditAction.java new file mode 100644 index 0000000000..238e703f19 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/ExitAuthorityEditAction.java @@ -0,0 +1 @@ +package com.fr.design.actions; import com.fr.base.BaseUtils; import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.DesignModelAdapter; import com.fr.design.designer.TargetComponent; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.mainframe.*; import com.fr.general.Inter; /** * Author : daisy * Date: 13-9-2 * Time: 下午3:36 */ public class ExitAuthorityEditAction extends TemplateComponentAction { public ExitAuthorityEditAction(TargetComponent t) { super(t); this.setName(Inter.getLocText(new String[]{"Exit", "DashBoard-Potence", "Edit"})); this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/exit_authority_edit.png")); } public void prepare4Undo() { } public boolean executeActionReturnUndoRecordNeeded() { TargetComponent tc = getEditingComponent(); if (tc == null) { return false; } if (BaseUtils.isAuthorityEditing()) { BaseUtils.setAuthorityEditing(false); WestRegionContainerPane.getInstance().replaceDownPane(TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter())); EastRegionContainerPane.getInstance().replaceDownPane(tc.getEastDownPane()); EastRegionContainerPane.getInstance().replaceUpPane(tc.getEastUpPane()); DesignerContext.getDesignerFrame().resetToolkitByPlus(tc.getToolBarMenuDockPlus()); DesignerContext.getDesignerFrame().needToAddAuhtorityPaint(); DesignerContext.getDesignerFrame().refreshDottedLine(); fireAuthorityStateToNomal(); } return true; } /** * 退出权限编辑时,将所有的做过权限编辑的状态,作为一个状态赋给报、报表主体 */ private void fireAuthorityStateToNomal() { java.util.List> opendedTemplate = HistoryTemplateListPane.getInstance().getHistoryList(); for (int i = 0; i < opendedTemplate.size(); i++) { //如果在权限编辑时做过操作,则将做过的操作作为一个整体状态赋给正在报表 if (opendedTemplate.get(i).isDoSomethingInAuthority()) { opendedTemplate.get(i).fireAuthorityStateToNomal(); } } } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/HyperlinkPluginAction.java b/designer_base/src/com/fr/design/actions/HyperlinkPluginAction.java new file mode 100644 index 0000000000..19e9acca23 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/HyperlinkPluginAction.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.actions; + +import com.fr.design.gui.controlpane.NameObjectCreator; + +import java.awt.event.ActionEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-26 + * Time: 上午10:47 + */ +public abstract class HyperlinkPluginAction extends UpdateAction { + public static final String XML_TAG = "hyperlinkType"; + + public HyperlinkPluginAction() { + this.setName(this.getDisplayName()); + } + + + /** + * 名字 + * + * @return + */ + public abstract String getDisplayName(); + + /** + * 得到超级链接的声明类 + * + * @return + */ + public abstract Class getHyperlinkClass(); + + /** + * 得到相应面板的类 + * + * @return + */ + public abstract Class getUpdateHyperlinkPaneClass(); + + public NameObjectCreator getHyperlinkCreator() { + return new NameObjectCreator(getDisplayName(), getHyperlinkClass(), getUpdateHyperlinkPaneClass()); + } + + /** + * 动作 + * @param e 动作 + */ + public void actionPerformed(ActionEvent e) { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/JTemplateAction.java b/designer_base/src/com/fr/design/actions/JTemplateAction.java new file mode 100644 index 0000000000..eb218195b6 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/JTemplateAction.java @@ -0,0 +1,16 @@ +package com.fr.design.actions; + +import com.fr.design.mainframe.JTemplate; + +public abstract class JTemplateAction> extends UpdateAction implements TemplateComponentActionInterface { + private T t; + public JTemplateAction(T t) { + this.t = t; + } + + @Override + public T getEditingComponent() { + return t; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/MenuAction.java b/designer_base/src/com/fr/design/actions/MenuAction.java new file mode 100644 index 0000000000..63d57146c5 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/MenuAction.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.actions; + +import com.fr.base.BaseUtils; +import com.fr.stable.StringUtils; + + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-28 + * Time: 上午9:44 + */ +public abstract class MenuAction extends UpdateAction { + + public MenuAction() { + this.setName(getDisplayName()); + this.setMnemonic(getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_insert/bindColumn.png")); + } + + /** + * 名字 + * + * @return + */ + public abstract String getDisplayName(); + + public char getMnemonic() { + return '\0'; + } + + /** + * 图标 + * + * @return + */ + public String getIconPath() { + return StringUtils.EMPTY; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/TableDataSourceAction.java b/designer_base/src/com/fr/design/actions/TableDataSourceAction.java new file mode 100644 index 0000000000..7d14d3eaa0 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/TableDataSourceAction.java @@ -0,0 +1,84 @@ +package com.fr.design.actions; + +import javax.swing.SwingUtilities; + +import com.fr.base.BaseUtils; +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.TableDataSource; +import com.fr.design.data.datapane.ReportTableDataPane; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.tabledata.ResponseDataSourceChange; +import com.fr.design.DesignModelAdapter; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.KeySetUtils; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; + +import java.util.HashMap; +import java.util.Map; + +/* + * richer:包括报表和表单的数据集 && 图表的数据集 + */ +public class TableDataSourceAction extends TemplateComponentAction> implements ResponseDataSourceChange { + public TableDataSourceAction(JTemplate t) { + super(t); + this.setMenuKeySet(KeySetUtils.TEMPLATE_TABLE_DATA_SOURCE); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_web/datasource.png")); + } + + /** + * 执行动作 + * + * @return 是否执行成功 + */ + public boolean executeActionReturnUndoRecordNeeded() { + final TableDataSource tds = this.getEditingComponent().getTarget(); + + final ReportTableDataPane tableDataPane = new ReportTableDataPane() { + public void complete() { + populate(tds); + } + }; + BasicDialog reportTableDataDialog = tableDataPane.showLargeWindow(SwingUtilities.getWindowAncestor(this.getEditingComponent()), null); + reportTableDataDialog.addDialogActionListener(new DialogActionAdapter() { + + @Override + public void doOk() { + DesignModelAdapter.getCurrentModelAdapter().renameTableData(tableDataPane.getDsNameChangedMap()); + tableDataPane.update(tds); + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + TableDataSourceAction.this.getEditingComponent().fireTargetModified(); + fireDSChanged(tableDataPane.getDsNameChangedMap()); + } + }); + reportTableDataDialog.setVisible(true); + return false; + } + + // TODO ALEX_SEP 同JWorkBookAction,也不知道这个undo该如何处理 + + /** + * 撤销 + */ + public void prepare4Undo() { + } + + /** + * 响应数据集改变 + */ + public void fireDSChanged() { + fireDSChanged(new HashMap()); + } + + /** + * 响应数据集改变 + * + * @param map 地图 + */ + public void fireDSChanged(Map map) { + DesignTableDataManager.fireDSChanged(map); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/TemplateComponentAction.java b/designer_base/src/com/fr/design/actions/TemplateComponentAction.java new file mode 100644 index 0000000000..a8bfe8fb61 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/TemplateComponentAction.java @@ -0,0 +1,40 @@ +package com.fr.design.actions; + + +import com.fr.design.designer.TargetComponent; + +public abstract class TemplateComponentAction extends UndoableAction implements TemplateComponentActionInterface { + private T t; + protected TemplateComponentAction(T t) { + this.t = t; + } + + protected void setEditingComponent(T t) { + this.t = t; + } + + @Override + public T getEditingComponent() { + return t; + } + + @Override + public void prepare4Undo() { + this.getEditingComponent().fireTargetModified(); + T component = getEditingComponent(); + if (component == null) { + return; + } + + component.requestFocus(); + } + + /** + * update enable + * TODO ALEX_SEP 这个方法的名字只是简单的叫update,太不明了了 + */ + @Override + public void update() { + this.setEnabled(this.getEditingComponent() != null); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/TemplateComponentActionInterface.java b/designer_base/src/com/fr/design/actions/TemplateComponentActionInterface.java new file mode 100644 index 0000000000..6a3ca1551c --- /dev/null +++ b/designer_base/src/com/fr/design/actions/TemplateComponentActionInterface.java @@ -0,0 +1,7 @@ +package com.fr.design.actions; + +import com.fr.design.designer.TargetComponent; + +public interface TemplateComponentActionInterface { + public T getEditingComponent(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/ToggleButtonUpdateAction.java b/designer_base/src/com/fr/design/actions/ToggleButtonUpdateAction.java new file mode 100644 index 0000000000..4d61663ae8 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/ToggleButtonUpdateAction.java @@ -0,0 +1,15 @@ +package com.fr.design.actions; + +import com.fr.design.gui.ibutton.UIToggleButton; + +/** + * 具有ToggleButton属性的action,继承这个类的action就会有 + * + * @author zhou + * + */ + +public interface ToggleButtonUpdateAction { + + public abstract UIToggleButton createToolBarComponent(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/ToolbarActionManager.java b/designer_base/src/com/fr/design/actions/ToolbarActionManager.java new file mode 100644 index 0000000000..74d5364d77 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/ToolbarActionManager.java @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions; + +import java.util.ArrayList; +import java.util.List; + +import com.fr.design.menu.MenuDef; + +public class ToolbarActionManager { + + private static ToolbarActionManager toolbarActionManager = null; //key map + //所有的Action Map. + private List actionList = new ArrayList(); + private List menuList=new ArrayList(); + + private ToolbarActionManager() { + } + + public static ToolbarActionManager createToolbarActionManager() { + if (toolbarActionManager == null) { + toolbarActionManager = new ToolbarActionManager(); + } + return toolbarActionManager; + } + + public void registerAction(UpdateAction updateAction) { + actionList.add(updateAction); + } + + public void registerAction(MenuDef menuDef) { + menuList.add(menuDef); + } + + public void update() { + int actionCount = actionList.size(); + for (int i = 0; i < actionCount; i++) { + UpdateAction action = actionList.get(i); + if (action != null) { + action.update(); + } + } + actionCount=menuList.size(); + for(int i=0;i + * For example, a 'cut' action my be enabled or disabled based on the state of the selection + * in a text component. Just before the edit menu is displayed, the cut action is given the + * opportunity to update itself, and will appear in the menu with the correct state. + * august:不需要考虑UpdateAction的持久化,难道需要持久化吗? 又不像以前那样保存docking的大小布局 + * 如果是ToggleButton,就额外继承ToggleButtonUpdateAction接口 + */ +public abstract class UpdateAction extends ShortCut implements Action { + + /** + * Specifies whether action is enabled; the default is true. + */ + private boolean enabled = true; + + /** + * Contains the array of key bindings. + * august:关键词key,是Action里面的final常量,如:Action.NAME、Action.SMALL_ICON等等 + */ + private Map componentMap; + + /** + * Constructor + */ + public UpdateAction() { + //设置默认的small icon,必须有一个默认的图片,这样菜单整体美观. + this.putValue(Action.SMALL_ICON, UIConstants.BLACK_ICON); + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + * @see Action#isEnabled + */ + @Override + public boolean isEnabled() { + return enabled; + } + + /** + * Enables or disables the action. + * + * @param newValue true to enable the action, false to + * disable it + * @see Action#setEnabled + */ + @Override + public void setEnabled(boolean newValue) { + boolean oldValue = this.enabled; + + if (oldValue != newValue) { + this.enabled = newValue; + + //循环遍历所有的Enable属性. + Iterator valueIt = this.componentMap.values().iterator(); + while (valueIt.hasNext()) { + Object valueObject = valueIt.next(); + if (valueObject instanceof JComponent) { + ((JComponent) valueObject).setEnabled(this.enabled); + } + } + } + } + + + /** + * Returns the name for the action, used for a menu or button. + * + * @return the name for the action. + */ + public String getName() { + return (String) this.getValue(Action.NAME); + } + + /** + * Sets the name for the action, used for a menu or button. + * + * @param name the name for the action. + */ + public void setName(String name) { + this.putValue(Action.NAME, name); + } + + /** + * Returns the smallIcon property setting. + * + * @return The small icon for the action. + */ + public Icon getSmallIcon() { + return (Icon) this.getValue(Action.SMALL_ICON); + } + + /** + * Sets the smallIcon property. The smallIcon may be displayed as a menu item's icon or + * possibly as the icon for a button. This icon should be 16x16 pixels in size. + * + * @param smallIcon The small icon for the action. + */ + public void setSmallIcon(Icon smallIcon) { + this.putValue(Action.SMALL_ICON, smallIcon); + } + + /** + * Returns the mnemonic property setting. + * + * @return The mnemonic character for the action. + */ + public char getMnemonic() { + Integer n = (Integer) this.getValue(Action.MNEMONIC_KEY); + return n == null ? '\0' : (char) n.intValue(); + } + + /** + * Sets the mnemonic property. The mnemonic character is the 'hotkey' for the menu item + * or button displaying the action. This *must* be a character in the 'name' property, + * or it will have no effect. + * + * @param mnemonic The mnemonic character for the action + */ + public void setMnemonic(char mnemonic) { + this.putValue(Action.MNEMONIC_KEY, new Integer(mnemonic)); + } + + /** + * Returns the key used for storing a KeyStroke to be used as the + * accelerator for the action. + * + * @return the key as the accelerator for the action. + */ + public KeyStroke getAccelerator() { + return (KeyStroke) this.getValue(Action.ACCELERATOR_KEY); + } + + /** + * Sets the key used for storing a KeyStroke to be used as the + * accelerator for the action. + * + * @param accelerator the key as the accelerator for the action. + */ + public void setAccelerator(KeyStroke accelerator) { + this.putValue(Action.ACCELERATOR_KEY, accelerator); + } + + /** + * update enable + */ + public void update() { + } + + /** + * Gets the Object associated with the specified key. + * + * @param key a string containing the specified key + * @return the binding Object stored with this key; if there + * are no keys, it will return null + * @see Action#getValue + */ + @Override + public Object getValue(String key) { + if (componentMap == null) { + return null; + } + return componentMap.get(key); + } + + /** + * Sets the Value associated with the specified key. + * + * @param key the String that identifies the stored object + * @param newValue the Object to store using this key + * @see Action#putValue + */ + @Override + public void putValue(String key, Object newValue) { + if (componentMap == null) { + componentMap = new HashMap(); + } + + + if (newValue == null) { + componentMap.remove(key); + } else { + componentMap.put(key, newValue); + } + + } + + @Override + public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { + + } + + @Override + public synchronized void removePropertyChangeListener(PropertyChangeListener listener) { + } + + /** + * Gets menu item. + * + * @return the created menu item. + */ + public UIMenuItem createMenuItem() { + Object object = this.getValue(UIMenuItem.class.getName()); + if (object == null && !(object instanceof UIMenuItem)) { + UIMenuItem menuItem = new UIMenuItem(this); + // 设置名字用作单元测 + menuItem.setName(getName()); + object = menuItem; + + this.putValue(UIMenuItem.class.getName(), object); + } + + return (UIMenuItem) object; + } + + /** + * Gets component on toolbar. + * + * @return the created components on toolbar. + */ + public JComponent createToolBarComponent() { + Object object = this.getValue(UIButton.class.getName()); + if (!(object instanceof AbstractButton)) { + UIButton button = null; + button = new UIButton(); + // 添加一个名字作为自动化测试用 + button.setName(getName()); + button.set4ToolbarButton(); + + //设置属性. + Integer mnemonicInteger = (Integer) this.getValue(Action.MNEMONIC_KEY); + if (mnemonicInteger != null) { + button.setMnemonic((char) mnemonicInteger.intValue()); + } + + button.setIcon((Icon) this.getValue(Action.SMALL_ICON)); + button.addActionListener(this); + + button.registerKeyboardAction(this, this.getAccelerator(), JComponent.WHEN_IN_FOCUSED_WINDOW); + + this.putValue(UIButton.class.getName(), button); + button.setText(StringUtils.EMPTY); + button.setEnabled(this.isEnabled()); + + //peter:产生tooltip + button.setToolTipText(ActionUtils.createButtonToolTipText(this)); + object = button; + } + + return (JComponent) object; + } + + /** + * Equals + */ + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (!(object instanceof UpdateAction)) { + return false; + } + + return ((UpdateAction) object).getName().equals(this.getName()); + } + + @Override + public int hashCode() { + int hash = 5; + hash = 59 * hash + (this.enabled ? 1 : 0); + return hash; + } + + /* + * Add this ShortCut into JPopupMenu + */ + @Override + public void intoJPopupMenu(JPopupMenu menu) { + update(); + + menu.add(this.createMenuItem()); + } + + /* + * Add this ShortCut into JToolBar + */ + @Override + public void intoJToolBar(JToolBar toolBar) { + update(); + + toolBar.add(this.createToolBarComponent()); + } + + /** + * 全局style的菜单 + */ + public static class UseMenuItem extends UIMenuItem { + + private NameStyle nameStyle; + + public UseMenuItem(Action action) { + super(action); + setPreferredSize(new Dimension(80, 20)); + } + + public UseMenuItem(String text, Icon icon) { + super(text, icon); + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + + if (nameStyle == null) { + return; + } + + Style.paintBackground((Graphics2D) g, nameStyle, getWidth() - 1, getHeight() - 1); + + Style.paintContent((Graphics2D) g, nameStyle.getName(), nameStyle, getWidth() - 1, getHeight() - 1, ScreenResolution.getScreenResolution()); + + Style.paintBorder((Graphics2D) g, nameStyle, getWidth() - 1, getHeight() - 1); + } + + public NameStyle getNameStyle() { + return this.nameStyle; + } + + public void setNameStyle(NameStyle nameStyle) { + this.nameStyle = nameStyle; + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + } + + /** + * Gets menu item. + * + * @return the created menu item. + */ + public UseMenuItem createUseMenuItem() { + Object object = this.getValue(UseMenuItem.class.getName()); + if (object == null && !(object instanceof UseMenuItem)) { + object = new UseMenuItem(this); + this.putValue(UseMenuItem.class.getName(), object); + } + return (UseMenuItem) object; + } + + public static UICheckBoxMenuItem createCheckBoxMenuItem(UpdateAction action) { + UICheckBoxMenuItem menuItem = new UICheckBoxMenuItem(action.getName()); + + // 设置属性. + Integer mnemonicInteger = (Integer) action + .getValue(Action.MNEMONIC_KEY); + if (mnemonicInteger != null) { + menuItem.setMnemonic((char) mnemonicInteger.intValue()); + } + menuItem.setIcon((Icon) action.getValue(Action.SMALL_ICON)); +// if(menuItem.isSelected()){ +// menuItem.setIcon(FRSwingConstants.YES_ICON); +// } + menuItem.addActionListener(action); + menuItem.setToolTipText((String) action.getValue(Action.LONG_DESCRIPTION)); + menuItem.setAccelerator((KeyStroke) action.getValue(Action.ACCELERATOR_KEY)); + + return menuItem; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/core/ActionUtils.java b/designer_base/src/com/fr/design/actions/core/ActionUtils.java new file mode 100644 index 0000000000..ea9550544f --- /dev/null +++ b/designer_base/src/com/fr/design/actions/core/ActionUtils.java @@ -0,0 +1,202 @@ +package com.fr.design.actions.core; + +import java.awt.event.KeyEvent; +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.Action; +import javax.swing.KeyStroke; + +import com.fr.base.FRContext; +import com.fr.base.Utils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.selection.QuickEditor; + +/** + * 一些ActionUtils + */ +public class ActionUtils { + private static Class[] actionClasses; + private static Class[] floatActionClasses; + + private ActionUtils() { + } + + private static Map floatEditor = new HashMap(); + + private static Class chartCollectionClass = null; + + private static Map cellEditor = new HashMap(); + + private static UpdateAction chartPreStyleAction = null; + + /** + * 待说明 + * @param clzz 待说明 + * @param editor 待说明 + */ + public static void registerCellEditor(Class clzz, QuickEditor editor) { + cellEditor.put(clzz, editor); + } + + /** + * 待说明 + * @param clzz 待说明 + * @param editor 待说明 + */ + public static void registerFloatEditor(Class clzz, QuickEditor editor) { + floatEditor.put(clzz, editor); + } + + /** + * 注册图表的 预定义样式. + * @param action 注册的图表预定义样式action + */ + public static void registerChartPreStyleAction(UpdateAction action) { + chartPreStyleAction = action; + } + + /** + * 返回 图表预定义样式Action + */ + public static UpdateAction getChartPreStyleAction() { + return chartPreStyleAction; + } + + /** + * kunsnat: 图表注册 悬浮元素编辑器 , 因为ChartCollecion和ChartQuickEditor一个在Chart,一个在Designer, 所以分开注册. + * @param clzz 待说明 + */ + public static void registerChartCollection(Class clzz) { + chartCollectionClass = clzz; + } + + public static Class getChartCollectionClass() { + return chartCollectionClass; + } + + /** + * kunsnat: 图表注册 悬浮元素编辑器 , 因为ChartCollecion和ChartQuickEditor一个在Chart,一个在Designer, 所以分开注册. + * @param editor 待说明 + */ + public static void registerChartFloatEditorInEditor(QuickEditor editor) { + if(chartCollectionClass != null) { + floatEditor.put(chartCollectionClass, editor); + } + } + + /** + * kunsnat: 图表注册 悬浮元素编辑器 , 因为ChartCollecion和ChartQuickEditor一个在Chart,一个在Designer, 所以分开注册. + * @param editor 待说明 + */ + public static void registerChartCellEditorInEditor(QuickEditor editor) { + if(chartCollectionClass != null) { + cellEditor.put(chartCollectionClass, editor); + } + } + + /** + * 返回 悬浮元素选中的Editor + */ + public static QuickEditor getFloatEditor(Class clazz) { + return floatEditor.get(clazz); + } + + public static QuickEditor getCellEditor(Class clazz) { + return cellEditor.get(clazz); + } + + /** + * peter:从Action来产生ToolTipText. + * @param action 动作 + * @return 字符 + */ + public static String createButtonToolTipText(Action action) { + StringBuffer buttonToolTipTextBuf = new StringBuffer(); + + //peter:把中文后面的(U),alt 快捷键的括号去掉,这个方法是临时的做法. + String actionName = (String) action.getValue(Action.NAME); + if (actionName.lastIndexOf("(") != -1) { + buttonToolTipTextBuf.append(actionName.substring(0, actionName.lastIndexOf("("))); + } else { + buttonToolTipTextBuf.append(actionName); + } + + //peter:产生快捷键的ToolTip. + KeyStroke keyStroke = (KeyStroke) action.getValue(Action.ACCELERATOR_KEY); + if (keyStroke != null) { + buttonToolTipTextBuf.append(" ("); + buttonToolTipTextBuf.append(KeyEvent.getKeyModifiersText(keyStroke.getModifiers())); + buttonToolTipTextBuf.append('+'); + buttonToolTipTextBuf.append(KeyEvent.getKeyText(keyStroke.getKeyCode())); + buttonToolTipTextBuf.append(')'); + } + + return Utils.objectToString(buttonToolTipTextBuf); + } + + /** + * 纪录插入元素的种类 + * + * @param cls 类型数组 + */ + public static void registerCellInsertActionClass(Class[] cls) { + actionClasses = cls; + } + + /** + * 生成单元格插入相关的Action + * + * @param cls 构造函数参数类型 + * @param obj 构造函数参数值 + * @return 相关Action组成的一个数组 + */ + public static UpdateAction[] createCellInsertAction(Class cls, Object obj) { + int length = 0; + JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + //表单中报表块编辑屏蔽掉 插入子报表 + length = jTemplate.isJWorkBook()? actionClasses.length : actionClasses.length - 1; + UpdateAction[] actions = new UpdateAction[length]; + for (int i = 0; i < length; i++) { + try { + Constructor c = actionClasses[i].getConstructor(cls); + actions[i] = c.newInstance(obj); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + return actions; + } + + /** + * 登记悬浮元素插入类型 + * + * @param cls 插入类型数组 + */ + public static void registerFloatInsertActionClass(Class[] cls) { + floatActionClasses = cls; + } + + /** + * 生成悬浮元素插入相关的Action + * + * @param cls 构造函数参数类型 + * @param obj 构造函数参数值 + * @return 相关Action组成的一个数组 + */ + public static UpdateAction[] createFloatInsertAction(Class cls, Object obj) { + UpdateAction[] actions = new UpdateAction[floatActionClasses.length]; + for (int i = 0; i < floatActionClasses.length; i++) { + try { + Constructor c = floatActionClasses[i].getConstructor(cls); + actions[i] = c.newInstance(obj); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + return actions; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/edit/CopyAction.java b/designer_base/src/com/fr/design/actions/edit/CopyAction.java new file mode 100644 index 0000000000..6f7ec1c4d2 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/edit/CopyAction.java @@ -0,0 +1,37 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import java.awt.event.KeyEvent; + +import javax.swing.KeyStroke; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.TemplateComponentAction; +import com.fr.design.designer.TargetComponent; +import com.fr.general.Inter; + +/** + * Copy. + */ +public class CopyAction extends TemplateComponentAction { + public CopyAction(TargetComponent t) { + super(t); + + this.setName(Inter.getLocText("M_Edit-Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + TargetComponent tc = getEditingComponent(); + if (tc != null) { + tc.copy(); + } + + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/edit/CutAction.java b/designer_base/src/com/fr/design/actions/edit/CutAction.java new file mode 100644 index 0000000000..735ec5bf3d --- /dev/null +++ b/designer_base/src/com/fr/design/actions/edit/CutAction.java @@ -0,0 +1,39 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import java.awt.event.KeyEvent; + +import javax.swing.KeyStroke; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.TemplateComponentAction; +import com.fr.design.designer.TargetComponent; +import com.fr.general.Inter; + +/** + * Cut. + */ +public class CutAction extends TemplateComponentAction { + /** + * Constructor + */ + public CutAction(TargetComponent t) { + super(t); + + this.setName(Inter.getLocText("M_Edit-Cut")); + this.setMnemonic('T'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/cut.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + TargetComponent editPane = getEditingComponent(); + if (editPane == null) { + return false; + } + return editPane.cut(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/edit/PasteAction.java b/designer_base/src/com/fr/design/actions/edit/PasteAction.java new file mode 100644 index 0000000000..f6b71e421f --- /dev/null +++ b/designer_base/src/com/fr/design/actions/edit/PasteAction.java @@ -0,0 +1,39 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import java.awt.event.KeyEvent; + +import javax.swing.KeyStroke; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.TemplateComponentAction; +import com.fr.design.designer.TargetComponent; +import com.fr.general.Inter; + +/** + * Paste. + */ +public class PasteAction extends TemplateComponentAction { + /** + * Constructor + */ + public PasteAction(TargetComponent t) { + super(t); + + this.setName(Inter.getLocText("M_Edit-Paste")); + this.setMnemonic('P'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/paste.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK)); + } + + @Override + public boolean executeActionReturnUndoRecordNeeded() { + TargetComponent tc = getEditingComponent(); + if (tc == null) { + return false; + } + return tc.paste(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/edit/RedoAction.java b/designer_base/src/com/fr/design/actions/edit/RedoAction.java new file mode 100644 index 0000000000..6ac6544f84 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/edit/RedoAction.java @@ -0,0 +1,59 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import java.awt.event.ActionEvent; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.TemplateComponentActionInterface; +import com.fr.design.actions.UpdateAction; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.KeySetUtils; + +/** + * Redo. + */ +public class RedoAction extends UpdateAction implements TemplateComponentActionInterface> { + private JTemplate t; + + public RedoAction(JTemplate t) { + this.t = t; + this.setMenuKeySet(KeySetUtils.REDO); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/redo.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public JTemplate getEditingComponent() { + return t; + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + JTemplate uncComponent = getEditingComponent(); + if (uncComponent != null) { + uncComponent.redo(); + } + } + + /** + * update enable + */ + @Override + public void update() { + JTemplate undoComponent = getEditingComponent(); + if (DesignerEnvManager.getEnvManager().isSupportUndo()) { + this.setEnabled(undoComponent != null && undoComponent.canRedo()); + } else { + this.setEnabled(false); + } + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/edit/UndoAction.java b/designer_base/src/com/fr/design/actions/edit/UndoAction.java new file mode 100644 index 0000000000..37523dce2d --- /dev/null +++ b/designer_base/src/com/fr/design/actions/edit/UndoAction.java @@ -0,0 +1,60 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.edit; + +import java.awt.event.ActionEvent; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.TemplateComponentActionInterface; +import com.fr.design.actions.UpdateAction; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.KeySetUtils; + +/** + * Undo. + */ +public class UndoAction extends UpdateAction implements TemplateComponentActionInterface> { + private JTemplate t; + + public UndoAction(JTemplate t) { + this.t = t; + this.setMenuKeySet(KeySetUtils.UNDO); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/undo.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public JTemplate getEditingComponent() { + return t; + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + JTemplate undoComponent = getEditingComponent(); + if (undoComponent != null) { + undoComponent.undo(); + } + } + + /** + * update enable + */ + @Override + public void update() { + JTemplate undoComponent = getEditingComponent(); + if (DesignerEnvManager.getEnvManager().isSupportUndo()) { + this.setEnabled(undoComponent != null && undoComponent.canUndo()); + } else { + this.setEnabled(false); + } + + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/CloseCurrentTemplateAction.java b/designer_base/src/com/fr/design/actions/file/CloseCurrentTemplateAction.java new file mode 100644 index 0000000000..9e8be9f51b --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/CloseCurrentTemplateAction.java @@ -0,0 +1 @@ +package com.fr.design.actions.file; import com.fr.design.actions.UpdateAction; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; import com.fr.design.menu.KeySetUtils; import java.awt.event.ActionEvent; /** * Author : daisy * Date: 13-8-16 * Time: 下午3:23 */ public class CloseCurrentTemplateAction extends UpdateAction { public CloseCurrentTemplateAction() { this.setMenuKeySet(KeySetUtils.CLOSE_CURRENT_TEMPLATE); this.setName(getMenuKeySet().getMenuKeySetName()); this.setMnemonic(getMenuKeySet().getMnemonic()); this.setAccelerator(getMenuKeySet().getKeyStroke()); } /** * 动作 * @param e 事件 */ public void actionPerformed(ActionEvent e) { MutilTempalteTabPane.getInstance().setIsCloseCurrent(true); MutilTempalteTabPane.getInstance().closeFormat(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); MutilTempalteTabPane.getInstance().closeSpecifiedTemplate(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()); } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/CloseTemplateAction.java b/designer_base/src/com/fr/design/actions/file/CloseTemplateAction.java new file mode 100644 index 0000000000..18c88d28d7 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/CloseTemplateAction.java @@ -0,0 +1,29 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.design.actions.JTemplateAction; +import com.fr.design.mainframe.JTemplate; +import com.fr.general.Inter; + +/** + * Close Report. + */ +public class CloseTemplateAction extends JTemplateAction> { + /** + * Constructor + */ + public CloseTemplateAction(JTemplate jt) { + super(jt); + + this.setName(Inter.getLocText("M-Close_Template")); + this.setMnemonic('C'); + } + + public void actionPerformed(ActionEvent evt) { +// this.getEditingComponent().unlockTemplate(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/EditEnvAction.java b/designer_base/src/com/fr/design/actions/file/EditEnvAction.java new file mode 100644 index 0000000000..901f02333d --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/EditEnvAction.java @@ -0,0 +1,22 @@ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.design.actions.UpdateAction; +import com.fr.design.mainframe.TemplatePane; +import com.fr.general.Inter; + + +public class EditEnvAction extends UpdateAction { + + + public EditEnvAction() { + this.setName(Inter.getLocText("M-Others") + "..."); + } + + @Override + public void actionPerformed(ActionEvent e) { + TemplatePane.getInstance().editItems(); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/ExitDesignerAction.java b/designer_base/src/com/fr/design/actions/file/ExitDesignerAction.java new file mode 100644 index 0000000000..a846d0115d --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/ExitDesignerAction.java @@ -0,0 +1,32 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.design.actions.UpdateAction; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.KeySetUtils; + +/** + * Exit. + */ +public class ExitDesignerAction extends UpdateAction { + /** + * Constructor + */ + public ExitDesignerAction() { + this.setMenuKeySet(KeySetUtils.EXIT_DESIGNER); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + DesignerContext.getDesignerFrame().exit(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/LocalePane.java b/designer_base/src/com/fr/design/actions/file/LocalePane.java new file mode 100644 index 0000000000..a604bc22aa --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/LocalePane.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.actions.file; + +import java.awt.BorderLayout; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.Vector; + +import javax.swing.JTable; +import javax.swing.RowFilter; +import javax.swing.SwingWorker; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableRowSorter; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.dialog.BasicPane; +import com.fr.file.filetree.FileNode; +import com.fr.general.FRLogger; +import com.fr.general.GeneralUtils; +import com.fr.general.IOUtils; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.project.ProjectConstants; + +/** + * @author : richie + * @since : 8.0 + */ +public class LocalePane extends BasicPane { + private static final String FR = "fr.properties"; + private static final String US = "fr_en_US.properties"; + private static final String CN = "fr_zh_CN.properties"; + private static final String JP = "fr_ja_JP.properties"; + private static final String TW = "fr_zh_TW.properties"; + private static final String PREFIX = "fr_"; + private static final int LOCALE_NAME_LEN = 5; + + private UITabbedPane tabbedPane; + private JTable predefinedTable; + private JTable customTable; + private DefaultTableModel predefineTableModel; + private DefaultTableModel customTableModel; + + public LocalePane() { + tabbedPane = new UITabbedPane(); + setLayout(new BorderLayout()); + final UITextField searchTextField = new UITextField(); + add(searchTextField, BorderLayout.NORTH); + add(tabbedPane, BorderLayout.CENTER); + + predefineTableModel = new DefaultTableModel() { + public boolean isCellEditable(int col, int row) { + return false; + } + }; + + predefinedTable = new JTable(predefineTableModel); + final TableRowSorter sorter = new TableRowSorter(predefineTableModel); + predefinedTable.setRowSorter(sorter); + + customTableModel = new DefaultTableModel(); + customTable = new JTable(customTableModel); + final TableRowSorter customSorter = new TableRowSorter(customTableModel); + customTable.setRowSorter(customSorter); + + + searchTextField.getDocument().addDocumentListener(new DocumentListener() { + public void insertUpdate(DocumentEvent e) { + customSorter.setRowFilter(RowFilter.regexFilter(searchTextField.getText())); + sorter.setRowFilter(RowFilter.regexFilter(searchTextField.getText())); + } + + public void removeUpdate(DocumentEvent e) { + customSorter.setRowFilter(RowFilter.regexFilter(searchTextField.getText())); + sorter.setRowFilter(RowFilter.regexFilter(searchTextField.getText())); + } + + public void changedUpdate(DocumentEvent e) { + customSorter.setRowFilter(RowFilter.regexFilter(searchTextField.getText())); + sorter.setRowFilter(RowFilter.regexFilter(searchTextField.getText())); + } + }); + + + tabbedPane.addTab(Inter.getLocText("Preference-Predefined"), new UIScrollPane(predefinedTable)); + tabbedPane.addTab(Inter.getLocText("Preference-Custom"), new UIScrollPane(customTable)); + + loadData(); + } + + private void loadData() { + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + initPredefinedProperties(); + initCustomProperties(); + + return null; + } + + public void done() { + predefineTableModel.fireTableDataChanged(); + customTableModel.fireTableDataChanged(); + } + }.execute(); + } + + private void initPredefinedProperties() { + Properties fr = loadLocaleProperties(FR); + Properties us = loadLocaleProperties(US); + Properties cn = loadLocaleProperties(CN); + Properties jp = loadLocaleProperties(JP); + Properties tw = loadLocaleProperties(TW); + + Set keys = fr.stringPropertyNames(); + List sortKeys = new ArrayList(keys); + Collections.sort(sortKeys); + Vector keyVector = new Vector(); + Vector valueVector = new Vector(); + Vector usVector = new Vector(); + Vector cnVector = new Vector(); + Vector jpVector = new Vector(); + Vector twVector = new Vector(); + for (String key : sortKeys) { + keyVector.add(key); + valueVector.add(fr.getProperty(key)); + usVector.add(us.getProperty(key)); + cnVector.add(cn.getProperty(key)); + jpVector.add(jp.getProperty(key)); + twVector.add(tw.getProperty(key)); + } + predefineTableModel.addColumn(Inter.getLocText("Key"), keyVector); + predefineTableModel.addColumn(Inter.getLocText("Value"), valueVector); + predefineTableModel.addColumn("en_US", usVector); + predefineTableModel.addColumn("zh_CN", cnVector); + predefineTableModel.addColumn("ja_JP", jpVector); + predefineTableModel.addColumn("zh_TW", twVector); + } + + private void initCustomProperties() throws Exception { + Env env = FRContext.getCurrentEnv(); + if (env == null) { + return; + } + FileNode[] fileNodes = env.listFile(ProjectConstants.LOCALE_NAME); + if (ArrayUtils.getLength(fileNodes) == 0) { + return; + } + + List list = new ArrayList(); + Set keys = new HashSet(); + customTableModel.addColumn(Inter.getLocText("Key")); + for (FileNode fileNode : fileNodes) { + String fileName = fileNode.getName(); + if (fileName.endsWith(".properties")) { + InputStream in = env.readBean(fileName, ProjectConstants.LOCALE_NAME); + Properties properties = new Properties(); + properties.load(in); + keys.addAll(properties.stringPropertyNames()); + list.add(properties); + customTableModel.addColumn(fileName.substring(PREFIX.length(), LOCALE_NAME_LEN + PREFIX.length())); + } + } + List sortKeys = new ArrayList(keys); + Collections.sort(sortKeys); + for (String key : sortKeys) { + Vector vector = new Vector(); + vector.add(key); + for (int i = 0; i < list.size(); i ++) { + vector.add(list.get(i).getProperty(key)); + } + customTableModel.addRow(vector); + } + } + + private Properties loadLocaleProperties(String name) { + Properties properties = new Properties(); + InputStream inputStream = IOUtils.readResource("/com/fr/general/locale/" + name); + try { + properties.load(inputStream); + } catch (IOException e) { + FRLogger.getLogger().error(e.getMessage()); + } + return properties; + } + + /** + * 保存当前编辑的国际化 + * + * + * @date 2014-9-30-下午3:10:30 + */ + public void save() { + Env env = FRContext.getCurrentEnv(); + if (env == null) { + return; + } + if (customTable.getCellEditor() == null) { + return; + } + customTable.getCellEditor().stopCellEditing(); + for (int i = 1, columnCount = customTableModel.getColumnCount(); i < columnCount; i ++) { + String fileName = customTableModel.getColumnName(i); + Properties properties = new Properties(); + for (int j = 0, rowCount = customTableModel.getRowCount(); j < rowCount; j ++) { + properties.setProperty(GeneralUtils.objectToString(customTableModel.getValueAt(j, 0)), GeneralUtils.objectToString(customTableModel.getValueAt(j, i))); + } + + OutputStream out = null; + try { + out = env.writeBean(PREFIX + fileName + ".properties", ProjectConstants.LOCALE_NAME); + properties.store(out, null); + + out.flush(); + out.close(); + } catch (Exception e) { + FRLogger.getLogger().info(e.getMessage()); + } + } + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Preference-Locale"); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/OpenRecentReportMenuDef.java b/designer_base/src/com/fr/design/actions/file/OpenRecentReportMenuDef.java new file mode 100644 index 0000000000..5015af0715 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/OpenRecentReportMenuDef.java @@ -0,0 +1,78 @@ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; +import java.util.List; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.UpdateAction; +import com.fr.design.gui.imenu.UIMenu; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.KeySetUtils; +import com.fr.design.menu.MenuDef; +import com.fr.file.FILEFactory; + +/** + * Open Resent MenuDef. + */ +public class OpenRecentReportMenuDef extends MenuDef { + public OpenRecentReportMenuDef() { + this.setMenuKeySet(KeySetUtils.RECENT_OPEN); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setIconPath("/com/fr/base/images/cell/blank.gif"); + initMenuDef(); + } + + private void initMenuDef() { + DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager(); + List list = designerEnvManager.getRecentOpenedFilePathList(); + for (int i = 0; i < list.size(); i++) { + this.addShortCut(new OpenRecentReportAction(list.get(i))); + } + } + + /** + * 更新菜单 + */ + public void updateMenu() { + UIMenu createdMenu = this.createJMenu(); + createdMenu.removeAll(); + this.clearShortCuts(); + initMenuDef(); + int menuCount = this.getShortCutCount(); + for (int i = 0; i < menuCount; i++) { + Object object = this.getShortCut(i); + if (!(object instanceof OpenRecentReportAction)) { + return; + } + OpenRecentReportAction openResentReportAction = (OpenRecentReportAction) object; + openResentReportAction.update(); + if (openResentReportAction.isEnabled()) { + createdMenu.add(openResentReportAction.createMenuItem()); + } + } + } + + public static class OpenRecentReportAction extends UpdateAction { + public OpenRecentReportAction() { + } + + public OpenRecentReportAction(String cptName) { + this.setName(cptName); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/oem/logo.png")); + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + DesignerContext.getDesignerFrame().openTemplate(FILEFactory.createFILE(this.getPath())); + } + + public String getPath() { + return this.getName(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/OpenTemplateAction.java b/designer_base/src/com/fr/design/actions/file/OpenTemplateAction.java new file mode 100644 index 0000000000..d02c60acd3 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/OpenTemplateAction.java @@ -0,0 +1,45 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.KeySetUtils; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; + + +/** + * Open Template. + */ +public class OpenTemplateAction extends UpdateAction { + + public OpenTemplateAction() { + this.setMenuKeySet(KeySetUtils.OPEN_TEMPLATE); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/open.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + FILEChooserPane fileChooser = FILEChooserPane.getInstance(true, true); + + if (fileChooser.showOpenDialog(DesignerContext.getDesignerFrame()) + == FILEChooserPane.OK_OPTION) { + final FILE file = fileChooser.getSelectedFILE(); + if (file == null) {//选择的文件不能是 null + return; + } + DesignerContext.getDesignerFrame().openTemplate(file); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/PreferenceAction.java b/designer_base/src/com/fr/design/actions/file/PreferenceAction.java new file mode 100644 index 0000000000..f3f5ef3250 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/PreferenceAction.java @@ -0,0 +1,46 @@ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.KeySetUtils; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; + + +public class PreferenceAction extends UpdateAction { + public PreferenceAction() { + this.setMenuKeySet(KeySetUtils.PREFERENCE); + this.setName(getMenuKeySet().getMenuKeySetName()+"..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + final DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + + final PreferencePane preferencePane = new PreferencePane(); + preferencePane.populate(DesignerEnvManager.getEnvManager()); + + BasicDialog basicDialog = preferencePane.showWindow(designerFrame); + basicDialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + preferencePane.update(DesignerEnvManager.getEnvManager()); + DesignerEnvManager.loadLogSetting(); + DesignerEnvManager.getEnvManager().saveXMLFile(); + JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + jt.refreshToolArea(); + } + }); + + basicDialog.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/PreferencePane.java b/designer_base/src/com/fr/design/actions/file/PreferencePane.java new file mode 100644 index 0000000000..a40f0e82f2 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/PreferencePane.java @@ -0,0 +1,633 @@ +package com.fr.design.actions.file; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.util.Locale; + +import javax.swing.JFileChooser; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignerEnvManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.editor.editor.IntegerEditor; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIColorButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLevel; +import com.fr.general.Inter; + +/** + * 选项对话框 + * + * @editor zhou + * @since 2012-3-28下午3:39:48 + */ +public class PreferencePane extends BasicPane { + private static final int MAX_UNDO_LIMIT_5 = 5; + private static final int MAX_UNDO_LIMIT_10 = 10; + private static final int MAX_UNDO_LIMIT_15 = 15; + private static final int MAX_UNDO_LIMIT_20 = 20; + private static final int MAX_UNDO_LIMIT_50 = 50; + private static final int SELECTED_INDEX_4 = 4; + private static final int SELECTED_INDEX_5 = 5; + + private static final String TYPE = "pressed"; + private static final String DISPLAY_TYPE = "+"; + private static final String BACK_SLASH = "BACK_SLASH"; + private static final String DISPLAY_BACK_SLASH = "\\"; + private static final String SLASH = "SLASH"; + private static final String DISPLAY_SLASH = "/"; + private static final String CONTROL = "CONTROL"; + private static final String DISPLAY_CONTROL = "ctrl"; + private static final String OPEN_BRACKET = "OPEN_BRACKET"; + private static final String DISPLAY_OPEN_BRACKET = "{"; + private static final String CLOSE_BRACKET = "CLOSE_BRACKET"; + private static final String DISPLAY_CLOSE_BRACKET = "}"; + private static final String COMMA = "COMMA"; + private static final String DISPLAY_COMMA = ","; + private static final String PERIOD = "PERIOD"; + private static final String DISPLAY_PERIOD = "."; + private static final String SEMICOLON = "SEMICOLON"; + private static final String DISPLAY_SEMICOLON = ";"; + private static final String QUOTE = "QUOTE"; + private static final String DISPLAY_QUOTE = "'"; + private static final String EQUALS = "EQUALS"; + private static final String DISPLAY_EQUALS = "+"; + private static final String MINUS = "MINUS"; + private static final String DISPLAY_MINUS = "-"; + + private static final FRLevel[] LOG = {FRLevel.SEVERE, FRLevel.WARNING, FRLevel.INFO, FRLevel.DEBUG}; + private static final String[] LANGUAGE = {Inter.getLocText("FR-Designer_Language_Default"), + getLocaledLanguage("Simplified_Chinese_Language", Locale.SIMPLIFIED_CHINESE), + getLocaledLanguage("English_Language", Locale.ENGLISH), + getLocaledLanguage("Japanese_Language", Locale.JAPAN), + getLocaledLanguage("Traditional_Chinese_Language", Locale.TRADITIONAL_CHINESE)}; + + //设置是否支持undo + private UICheckBox supportUndoCheckBox; + //设置最大撤销次数 + private UIComboBox maxUndoLimit; + //是非支持自动计算父格 + private UICheckBox supportDefaultParentCalculateCheckBox; + + //是否自动转化为公式 + private UICheckBox supportStringToFormulaBox; + private UICheckBox defaultStringToFormulaBox; + + private UILabel shortCutLabel; + private KeyStroke shortCutKeyStore = null; + private UIColorButton gridLineColorTBButton; + + + private UIColorButton paginationLineColorTBButton; + + private UICheckBox supportCellEditorDefCheckBox; + private UICheckBox isDragPermitedCheckBox; + + private UITextField logExportDirectoryField; + + private UIComboBox logLevelComboBox, languageComboBox, pageLengthComboBox, reportLengthComboBox; + private IntegerEditor portEditor; + private UITextField jdkHomeTextField; + private UICheckBox oracleSpace; + private UICheckBox joinProductImprove; + + public PreferencePane() { + this.initComponents(); + } + + protected void initComponents() { + JPanel contentPane = this; + contentPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + + UITabbedPane jtabPane = new UITabbedPane(); + JPanel generalPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + jtabPane.addTab(Inter.getLocText("FR-Designer_General"), generalPane); + JPanel advancePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + jtabPane.addTab(Inter.getLocText("FR-Designer_Advanced"), advancePane); + contentPane.add(jtabPane, BorderLayout.NORTH); + + + createFunctionPane(generalPane); + createEditPane(generalPane); + createGuiOfGridPane(generalPane); + createColorSettingPane(generalPane); + + // ConfPane + JPanel confLocationPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); + advancePane.add(confLocationPane); + + createLogPane(advancePane); + + createLanPane(generalPane); + + createLengthPane(advancePane); + + createServerPane(advancePane); + + createJdkHomePane(advancePane); + + String[] message = new String[]{"Display", "Oracle_All_Tables"}; + String[] sign = new String[]{"Oracle"}; + JPanel oraclePane = FRGUIPaneFactory.createTitledBorderPane("Oracle" + Inter.getLocText("FR-Designer_Oracle_All_Tables")); + oracleSpace = new UICheckBox(Inter.getLocText(message, sign)); + oraclePane.add(oracleSpace); + + JPanel improvePane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("FR-Designer_Product_improve")); + joinProductImprove = new UICheckBox(Inter.getLocText("FR-Designer_Join_Product_improve")); + improvePane.add(joinProductImprove); + + JPanel spaceUpPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + spaceUpPane.add(oraclePane, BorderLayout.NORTH); + spaceUpPane.add(improvePane, BorderLayout.SOUTH); + advancePane.add(spaceUpPane); + } + + private static String getLocaledLanguage(String key, Locale locale){ + StringBuilder sb = new StringBuilder(); + sb.append(Inter.getLocText(key)).append("("); + sb.append(Inter.getLocText(key, locale)).append(")"); + return sb.toString(); + } + + private void createFunctionPane(JPanel generalPane) { + JPanel functionPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("FR-Designer_Preference-Function")); + generalPane.add(functionPane); + + //添加supportUndo选择项 + supportUndoCheckBox = new UICheckBox(Inter.getLocText("Preference-Support_Undo")); + functionPane.add(supportUndoCheckBox); + //添加maxUndoLimit + //String[] undoTimes = {"最大撤销次数","5次","10次","15次","20次","50次"}; + String[] undoTimes = {Inter.getLocText("FR-Designer_max_undo_limit"), MAX_UNDO_LIMIT_5 + Inter.getLocText("FR-Designer_time(s)"), MAX_UNDO_LIMIT_10 + Inter.getLocText("FR-Designer_time(s)") + , MAX_UNDO_LIMIT_15 + Inter.getLocText("FR-Designer_time(s)"), MAX_UNDO_LIMIT_20 + Inter.getLocText("FR-Designer_time(s)"), MAX_UNDO_LIMIT_50 + Inter.getLocText("FR-Designer_time(s)")}; + maxUndoLimit = new UIComboBox(undoTimes); + functionPane.add(maxUndoLimit); + + //不支持撤销则不能选择撤销可缓存,也不能设置最大撤销次数 + supportUndoCheckBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + maxUndoLimit.setEnabled(supportUndoCheckBox.isSelected()); + } + }); + + + //添加supportDefaultParentCalculate选择项 + supportDefaultParentCalculateCheckBox = new UICheckBox( + Inter.getLocText("Preference-Support_Default_Parent_Calculate")); + functionPane.add(supportDefaultParentCalculateCheckBox); + } + + private void createEditPane(JPanel generalPane) { + //samuel:编辑器设置 + JPanel editPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText(new String[]{"Editor", "Set"})); + generalPane.add(editPane); + + //设置是否支持将字符串编辑为公式 + supportStringToFormulaBox = new UICheckBox(Inter.getLocText("FR-Designer_Surport_String_To_Formula")); + editPane.add(supportStringToFormulaBox); + + //是否默认转化 + defaultStringToFormulaBox = new UICheckBox(Inter.getLocText("FR-Designer_Always")); + + editPane.add(defaultStringToFormulaBox); + //不支持转化则不能默认执行 + supportStringToFormulaBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + defaultStringToFormulaBox.setEnabled(supportStringToFormulaBox.isSelected()); + } + }); + JPanel keyStrokePane = new JPanel(new BorderLayout()); + keyStrokePane.add(new UILabel(Inter.getLocText("Support-Auto_Complete_Shortcut") + ":"), BorderLayout.WEST); + shortCutLabel = new UILabel(); + keyStrokePane.add(shortCutLabel, BorderLayout.CENTER); + editPane.add(keyStrokePane); + shortCutLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() > 1) { + final KeyStrokePane basicPane = new KeyStrokePane(shortCutLabel.getText()); + BasicDialog dlg = basicPane.showSmallWindow(SwingUtilities.getWindowAncestor(PreferencePane.this), new DialogActionAdapter() { + @Override + public void doOk() { + shortCutLabel.setText(basicPane.getText()); + } + }); + dlg.setVisible(true); + } + } + }); + } + + private class KeyStrokePane extends BasicPane { + private UILabel label; + + public KeyStrokePane(String text) { + setLayout(new BorderLayout()); + setFocusable(true); + requestFocusInWindow(); + label = new UILabel(text); + add(GUICoreUtils.createBorderLayoutPane( + new UILabel(Inter.getLocText("Support-Current_Auto_Complete_Shortcut") + ":"), + BorderLayout.WEST, + label, + BorderLayout.CENTER), + BorderLayout.NORTH); + addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + int modifier = e.getModifiers(); + if (modifier == 0) { + return; + } + int keyCode = e.getKeyCode(); + shortCutKeyStore = KeyStroke.getKeyStroke(keyCode, modifier); + String str = shortCutKeyStore.toString(); + label.setText(getDisplayShortCut(str)); + } + }); + } + + public String getText() { + return label.getText(); + } + + + @Override + protected String title4PopupWindow() { + return "KeyStroke"; + } + + } + + private void createGuiOfGridPane(JPanel generalPane) { + // GridPane + JPanel guiOfGridPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("Preference-Setting_Grid")); + generalPane.add(guiOfGridPane); + + supportCellEditorDefCheckBox = new UICheckBox(Inter.getLocText("Preference-Support_Cell_Editor_Definition")); + guiOfGridPane.add(supportCellEditorDefCheckBox); + + isDragPermitedCheckBox = new UICheckBox(Inter.getLocText("Preference-Is_Drag_Permited")); + guiOfGridPane.add(isDragPermitedCheckBox); + } + + private void createColorSettingPane(JPanel generalPane) { + // Color Setting Pane + JPanel colorSettingPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("Preference-Setting_Colors")); + generalPane.add(colorSettingPane); + + new UILabel(Inter.getLocText("Preference-Grid_Line_Color")); + + new UILabel(Inter.getLocText("Preference-Pagination_Line_Color")); + + gridLineColorTBButton = new UIColorButton(BaseUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); + gridLineColorTBButton.setEnabled(this.isEnabled()); + + paginationLineColorTBButton = new UIColorButton(BaseUtils.readIcon("/com/fr/design/images/gui/color/foreground.png")); + paginationLineColorTBButton.setEnabled(this.isEnabled()); + + JPanel leftPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + leftPane.add(new UILabel(Inter.getLocText("Preference-Grid_Line_Color") + ":")); + leftPane.add(gridLineColorTBButton); + JPanel rightPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + rightPane.add(new UILabel(Inter.getLocText("Preference-Pagination_Line_Color") + ":")); + rightPane.add(paginationLineColorTBButton); + colorSettingPane.add(leftPane); + colorSettingPane.add(rightPane); + } + + private void createLogPane(JPanel advancePane) { + //richer:选择导出log文件的目录. + JPanel logPane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); + advancePane.add(logPane); + JPanel logExportPane = FRGUIPaneFactory.createTitledBorderPane("log" + Inter.getLocText("FR-Designer_Export_Setting")); + logPane.add(logExportPane); + UILabel logLabel = new UILabel(Inter.getLocText("FR-Designer_Select_Export_Log_Directory") + ":"); + logExportPane.add(logLabel, BorderLayout.WEST); + logExportDirectoryField = new UITextField(24); + logExportPane.add(logExportDirectoryField, BorderLayout.CENTER); + UIButton chooseDirBtn = new UIButton("..."); + logExportPane.add(chooseDirBtn, BorderLayout.EAST); + chooseDirBtn.setPreferredSize(new Dimension(25, 25)); + chooseDirBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int saveValue = fileChooser.showOpenDialog(DesignerContext.getDesignerFrame()); + if (saveValue == JFileChooser.APPROVE_OPTION) { + File selectedFile = fileChooser.getSelectedFile(); + logExportDirectoryField.setText(selectedFile.getAbsolutePath()); + } + } + }); + + JPanel logLevelPane = FRGUIPaneFactory.createTitledBorderPane("log" + Inter.getLocText("FR-Designer_Level_Setting")); + logPane.add(logLevelPane); + logLevelComboBox = new UIComboBox(LOG); + logLevelPane.add(logLevelComboBox); + logLevelComboBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + DesignerEnvManager.getEnvManager().setLogLevel(((FRLevel) logLevelComboBox.getSelectedItem()).getLevel()); + } + }); + } + + private void createLanPane(JPanel generalPane) { + // ben:选择版本语言; + JPanel languageAndDashBoard_pane = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); + JPanel LanguagePane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("FR-Designer_Choose_Language")); + generalPane.add(languageAndDashBoard_pane); + languageAndDashBoard_pane.add(LanguagePane); + languageComboBox = new UIComboBox(LANGUAGE); + ActionLabel languageLabel = new ActionLabel(Inter.getLocText("FR-Designer_Designer_Language")); + languageLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final LocalePane localePane = new LocalePane(); + BasicDialog dlg = localePane.showLargeWindow(SwingUtilities.getWindowAncestor(PreferencePane.this), new DialogActionAdapter() { + @Override + public void doOk() { + localePane.save(); + } + }); + dlg.setVisible(true); + } + }); + UILabel noticeLabel = new UILabel(Inter.getLocText("FR-Designer_Work_After_Restart_Designer"));//sail:提示重启后生效 + double p = TableLayout.PREFERRED; + double rowSize[] = {p}; + double columnSize[] = {p, p, p}; + Component[][] components = { + {languageLabel, languageComboBox, noticeLabel}, + }; + languageComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + //Inter.fr = ResourceBundle.getBundle("com/fr/general/locale/fr", Locale.US); + } + }); + JPanel choosePane = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); + LanguagePane.add(choosePane); + } + + private String getDisplayShortCut(String shotrCut) { + return shotrCut.replace(TYPE, DISPLAY_TYPE).replace(BACK_SLASH, DISPLAY_BACK_SLASH).replace(SLASH, DISPLAY_SLASH) + .replace(CONTROL, DISPLAY_CONTROL).replace(OPEN_BRACKET, DISPLAY_OPEN_BRACKET).replace(CLOSE_BRACKET, DISPLAY_CLOSE_BRACKET) + .replace(COMMA, DISPLAY_COMMA).replace(PERIOD, DISPLAY_PERIOD).replace(SEMICOLON, DISPLAY_SEMICOLON).replace(QUOTE, DISPLAY_QUOTE) + .replace(EQUALS, DISPLAY_EQUALS).replace(MINUS, DISPLAY_MINUS); + } + + + private KeyStroke convert2KeyStroke(String ks) { + return KeyStroke.getKeyStroke(ks.replace(DISPLAY_TYPE, TYPE)); + } + + + private void createLengthPane(JPanel advancePane) { + double p = TableLayout.PREFERRED; + double rowSize[] = {p}; + + // 长度单位选择 + JPanel lengthPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("FR-Designer_Setting-Ruler-Units")); + advancePane.add(lengthPane); + pageLengthComboBox = new UIComboBox(new String[]{Inter.getLocText("FR-Designer_PageSetup-mm"), Inter.getLocText("FR-Designer_Unit_CM"), Inter.getLocText("FR-Designer_Unit_INCH")}); + pageLengthComboBox.setPreferredSize(new Dimension(80, 20)); + pageLengthComboBox.setMinimumSize(new Dimension(80, 20)); + reportLengthComboBox = new UIComboBox(new String[]{Inter.getLocText("FR-Designer_PageSetup-mm"), Inter.getLocText("FR-Designer_Unit_CM"), Inter.getLocText("FR-Designer_Unit_INCH"), Inter.getLocText("FR-Designer_Unit_PT")}); + reportLengthComboBox.setPreferredSize(new Dimension(80, 20)); + reportLengthComboBox.setMinimumSize(new Dimension(80, 20)); + UILabel pagelengthLabel = new UILabel(Inter.getLocText("FR-Designer_Page-Setup-Scale-Units") + ":"); + UILabel reportLengthLabel = new UILabel(Inter.getLocText("FR-Designer_Report-Design-Ruler-Units") + ":"); + Component[][] lengthComponents = { + {pagelengthLabel, pageLengthComboBox, reportLengthLabel, reportLengthComboBox}, + }; + JPanel chooseLengthPane = TableLayoutHelper.createTableLayoutPane(lengthComponents, rowSize, new double[]{p, p, p, p}); + lengthPane.add(chooseLengthPane); + } + + private void createServerPane(JPanel advancePane) { + double p = TableLayout.PREFERRED; + double rowSize[] = {p}; + double columnSize[] = {p, p, p}; + + JPanel serverPortPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("FR-Designer_Web_Preview_Port_Setting")); + advancePane.add(serverPortPane); + portEditor = new IntegerEditor(); + portEditor.setPreferredSize(new Dimension(80, 20)); + portEditor.setMinimumSize(new Dimension(80, 20)); + UILabel notiJlabel = new UILabel(Inter.getLocText("FR-Designer_Work_After_Restart_Designer")); + UILabel serverPortLabel = new UILabel(Inter.getLocText("FR-Designer_Web_Preview_Port") + ":"); + Component[][] portComponents = { + {serverPortLabel, portEditor, notiJlabel}, + }; + JPanel choosePortPane = TableLayoutHelper.createTableLayoutPane(portComponents, rowSize, columnSize); + serverPortPane.add(choosePortPane, BorderLayout.CENTER); + } + + private void createJdkHomePane(JPanel advancePane) { + double p = TableLayout.PREFERRED; + double rowSize[] = {p}; + double columnSize[] = {p, p, p}; + + JPanel serverPortPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("Preference-JDK_Home")); + advancePane.add(serverPortPane); + jdkHomeTextField = new UITextField(); + UIButton chooseBtn = new UIButton("..."); + chooseBtn.setPreferredSize(new Dimension(20, 20)); + JPanel panel = GUICoreUtils.createBorderLayoutPane( + jdkHomeTextField, BorderLayout.CENTER, + chooseBtn, BorderLayout.EAST + ); + chooseBtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int returnValue = fileChooser.showOpenDialog(PreferencePane.this); + if (returnValue == JFileChooser.APPROVE_OPTION) { + File file = fileChooser.getSelectedFile(); + jdkHomeTextField.setText(file.getAbsolutePath()); + } + } + }); + panel.setPreferredSize(new Dimension(300, 20)); + UILabel notiJlabel = new UILabel(Inter.getLocText("FR-Designer_Work_After_Restart_Designer")); + UILabel serverPortLabel = new UILabel(Inter.getLocText("Preference-JDK_Home") + ":"); + Component[][] portComponents = { + {serverPortLabel, panel, notiJlabel}, + }; + JPanel choosePortPane = TableLayoutHelper.createTableLayoutPane(portComponents, rowSize, columnSize); + serverPortPane.add(choosePortPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("M_Window-Preference"); + } + + /** + * The method of populate. + * + * @param designerEnvManager + */ + public void populate(DesignerEnvManager designerEnvManager) { + if (designerEnvManager == null) { + return; + } + + supportUndoCheckBox.setSelected(designerEnvManager.isSupportUndo()); + if (designerEnvManager.isSupportUndo()) { + maxUndoLimit.setSelectedIndex(chooseCase(designerEnvManager.getUndoLimit())); + } else { + maxUndoLimit.setEnabled(false); + } + + supportDefaultParentCalculateCheckBox.setSelected(designerEnvManager.isSupportDefaultParentCalculate()); + + supportStringToFormulaBox.setSelected(designerEnvManager.isSupportStringToFormula()); + + shortCutLabel.setText(getDisplayShortCut(designerEnvManager.getAutoCompleteShortcuts())); + shortCutKeyStore = convert2KeyStroke(designerEnvManager.getAutoCompleteShortcuts()); + + if (supportStringToFormulaBox.isSelected()) { + defaultStringToFormulaBox.setEnabled(true); + defaultStringToFormulaBox.setSelected(designerEnvManager.isDefaultStringToFormula()); + } else { + defaultStringToFormulaBox.setEnabled(false); + defaultStringToFormulaBox.setSelected(false); + } + + supportCellEditorDefCheckBox.setSelected(designerEnvManager.isSupportCellEditorDef()); + + isDragPermitedCheckBox.setSelected(designerEnvManager.isDragPermited()); + + gridLineColorTBButton.setColor(designerEnvManager.getGridLineColor()); + paginationLineColorTBButton.setColor(designerEnvManager.getPaginationLineColor()); + + this.logExportDirectoryField.setText(designerEnvManager.getLogLocation()); + + this.logLevelComboBox.setSelectedItem(FRLevel.getByLevel(designerEnvManager.getLogLevel())); + + this.languageComboBox.setSelectedItem(LANGUAGE[designerEnvManager.getLanguage()]); + + this.pageLengthComboBox.setSelectedIndex(designerEnvManager.getPageLengthUnit()); + this.reportLengthComboBox.setSelectedIndex(designerEnvManager.getReportLengthUnit()); + + this.portEditor.setValue(new Integer(designerEnvManager.getJettyServerPort())); + + this.jdkHomeTextField.setText(designerEnvManager.getJdkHome()); + + this.oracleSpace.setSelected(designerEnvManager.isOracleSystemSpace()); + this.joinProductImprove.setSelected(designerEnvManager.isJoinProductImprove()); + } + + private int chooseCase(int sign) { + switch (sign) { + case 0: + return 0; + case MAX_UNDO_LIMIT_5: + return 1; + case MAX_UNDO_LIMIT_10: + return 2; + case MAX_UNDO_LIMIT_15: + return 3; + case MAX_UNDO_LIMIT_20: + return SELECTED_INDEX_4; + case MAX_UNDO_LIMIT_50: + return SELECTED_INDEX_5; + default: + return 1; + } + } + + /** + * The method of update. + */ + public void update(DesignerEnvManager designerEnvManager) { + if (designerEnvManager == null) { + return; + } + + designerEnvManager.setLogLocation(this.logExportDirectoryField.getText()); + + designerEnvManager.setLogLevel(((FRLevel) logLevelComboBox.getSelectedItem()).getLevel()); + + designerEnvManager.setSupportUndo(supportUndoCheckBox.isSelected()); + + designerEnvManager.setSupportDefaultParentCalculate(supportDefaultParentCalculateCheckBox.isSelected()); + + designerEnvManager.setSupportStringToFormula(supportStringToFormulaBox.isSelected()); + + designerEnvManager.setDefaultStringToFormula(defaultStringToFormulaBox.isSelected()); + + designerEnvManager.setSupportCellEditorDef(supportCellEditorDefCheckBox.isSelected()); + + designerEnvManager.setAutoCompleteShortcuts(shortCutKeyStore != null ? shortCutKeyStore.toString().replace(TYPE, DISPLAY_TYPE) : shortCutLabel.getText()); + + designerEnvManager.setDragPermited(isDragPermitedCheckBox.isSelected()); + + designerEnvManager.setGridLineColor(gridLineColorTBButton.getColor()); + + designerEnvManager.setPaginationLineColor(paginationLineColorTBButton.getColor()); + + designerEnvManager.setLanguage(getLanguageInt()); + + designerEnvManager.setPageLengthUnit((short) pageLengthComboBox.getSelectedIndex()); + designerEnvManager.setReportLengthUnit((short) reportLengthComboBox.getSelectedIndex()); + + designerEnvManager.setJettyServerPort(portEditor.getValue().intValue()); + + designerEnvManager.setJdkHome(jdkHomeTextField.getText()); + + designerEnvManager.setOracleSystemSpace(this.oracleSpace.isSelected()); + designerEnvManager.setJoinProductImprove(this.joinProductImprove.isSelected()); +// designerEnvManager.setAutoBackUp(this.autoBackUp.isSelected()); + + designerEnvManager.setUndoLimit(maxUndoLimit.getSelectedIndex() * SELECTED_INDEX_5); + if (maxUndoLimit.getSelectedIndex() == SELECTED_INDEX_5) { + designerEnvManager.setUndoLimit(MAX_UNDO_LIMIT_50); + } + } + + /* + * 得到所选语言的int值 + */ + private int getLanguageInt() { + int l = 0; + String lang = (String) this.languageComboBox.getSelectedItem(); + for (int i = 0; i < LANGUAGE.length; i++) { + if (ComparatorUtils.equals(lang, LANGUAGE[i])) { + l = i; + break; + } + } + return l; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/SaveAsTemplateAction.java b/designer_base/src/com/fr/design/actions/file/SaveAsTemplateAction.java new file mode 100644 index 0000000000..3dd4524597 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/SaveAsTemplateAction.java @@ -0,0 +1,48 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.JTemplateAction; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.KeySetUtils; + +/** + * Save as file + */ +public class SaveAsTemplateAction extends JTemplateAction> { + + public SaveAsTemplateAction(JTemplate dPane) { + super(dPane); + this.setMenuKeySet(KeySetUtils.SAVE_AS_TEMPLATE); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/saveAs.png")); + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + JTemplate jt = this.getEditingComponent(); + // kunsnat: 保存前停止编辑状态,保存属性. + jt.stopEditing(); + jt.saveAsTemplate(); + this.setEnabled(true); + + jt.requestFocus(); + } + + @Override + public void update() { + super.update(); + +// this.setEnabled(!this.getEditingComponent().isSaved()); +// 另存为按钮应该一直可用使用 + this.setEnabled(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/SaveTemplateAction.java b/designer_base/src/com/fr/design/actions/file/SaveTemplateAction.java new file mode 100644 index 0000000000..de2cf1e427 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/SaveTemplateAction.java @@ -0,0 +1,45 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.file; + +import java.awt.event.ActionEvent; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.JTemplateAction; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.KeySetUtils; + +/** + * @author richer + * @since 6.5.3 + */ +public class SaveTemplateAction extends JTemplateAction> { + + public SaveTemplateAction(JTemplate jt) { + super(jt); + this.setMenuKeySet(KeySetUtils.SAVE_TEMPLATE); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/save.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + JTemplate jt = this.getEditingComponent(); + jt.stopEditing(); + jt.saveTemplate(); + jt.requestFocus(); + } + + @Override + public void update() { + super.update(); + this.setEnabled(!this.getEditingComponent().isSaved()); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/SwitchExistEnv.java b/designer_base/src/com/fr/design/actions/file/SwitchExistEnv.java new file mode 100644 index 0000000000..8854e777b8 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/SwitchExistEnv.java @@ -0,0 +1,127 @@ +package com.fr.design.actions.file; + +import com.fr.base.BaseUtils; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.tabledata.ResponseDataSourceChange; +import com.fr.dav.LocalEnv; +import com.fr.design.DesignerEnvManager; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.TemplatePane; +import com.fr.design.menu.KeySetUtils; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.SeparatorDef; +import com.fr.design.dialog.InformationWarnPane; +import com.fr.env.RemoteEnv; +import com.fr.env.SignIn; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.GeneralContext; +import com.fr.general.Inter; +import com.fr.stable.LicUtils; +import com.fr.stable.ProductConstants; +import com.fr.stable.EnvChangedListener; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.logging.Level; + + +public class SwitchExistEnv extends MenuDef { + + public SwitchExistEnv() { + this.setMenuKeySet(KeySetUtils.SWITCH_ENV); + this.setName(getMenuKeySet().getMenuName()); + this.setHasScrollSubMenu(true); + initMenuDef(); + GeneralContext.addEnvWillChangedListener(new EnvChangedListener() { + public void envChanged() { + SwitchExistEnv.this.clearShortCuts(); + initMenuDef(); + } + }); + } + + private void initMenuDef() { + //ButtonGroup group = new ButtonGroup(); + Iterator nameIt = DesignerEnvManager.getEnvManager().getEnvNameIterator(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + this.setIconPath("com/fr/design/images/m_file/switch.png"); + this.addShortCut(new GetExistEnvAction(name)); + } + this.addShortCut(SeparatorDef.DEFAULT); + this.addShortCut(new EditEnvAction()); + } + + public static class GetExistEnvAction extends UpdateAction implements ResponseDataSourceChange { + public GetExistEnvAction() { + + } + + public GetExistEnvAction(String envName) { + this.setName(envName); + Env env = DesignerEnvManager.getEnvManager().getEnv(envName); + if (env instanceof LocalEnv) { + this.setSmallIcon(BaseUtils.readIcon("com/fr/design/images/data/bind/localconnect.png")); + } else if (env instanceof RemoteEnv) { + this.setSmallIcon(BaseUtils.readIcon("com/fr/design/images/data/bind/distanceconnect.png")); + } + } + + /** + * 响应数据集改变 + */ + public void fireDSChanged() { + fireDSChanged(new HashMap()); + } + + /** + * 响应数据集改变 + * + * @param map 数据集 + */ + public void fireDSChanged(Map map) { + DesignTableDataManager.fireDSChanged(map); + } + + /** + * 动作 + * + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + DesignerEnvManager envManager = DesignerEnvManager.getEnvManager(); + Env selectedEnv = envManager.getEnv(this.getName()); + try { + if (selectedEnv instanceof RemoteEnv && !((RemoteEnv) selectedEnv).testServerConnection()) { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText(new String[]{"M-SwitchWorkspace", "Failed"})); + return; + } + String remoteVersion = selectedEnv.getDesignerVersion(); + if (StringUtils.isBlank(remoteVersion) || ComparatorUtils.compare(remoteVersion, ProductConstants.DESIGNER_VERSION) < 0) { + String infor = Inter.getLocText("Server-version-tip"); + String moreInfo = Inter.getLocText("Server-version-tip-moreInfo"); + FRLogger.getLogger().log(Level.WARNING, infor); + new InformationWarnPane(infor, moreInfo, Inter.getLocText("Tooltips")).show(); + return; + } + SignIn.signIn(selectedEnv); + LicUtils.resetBytes(); + HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().refreshToolArea(); + fireDSChanged(); + } catch (Exception em) { + FRContext.getLogger().error(em.getMessage(), em); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText(new String[]{"M-SwitchWorkspace", "Failed"})); + TemplatePane.getInstance().editItems(); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/file/WebPreviewUtils.java b/designer_base/src/com/fr/design/actions/file/WebPreviewUtils.java new file mode 100644 index 0000000000..0947d4323a --- /dev/null +++ b/designer_base/src/com/fr/design/actions/file/WebPreviewUtils.java @@ -0,0 +1,95 @@ +package com.fr.design.actions.file; + +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.utils.DesignUtils; +import com.fr.file.FILE; +import com.fr.file.FileNodeFILE; +import com.fr.general.GeneralUtils; +import com.fr.general.Inter; +import com.fr.general.web.ParameterConsts; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import java.util.Map; + +public final class WebPreviewUtils { + + public static void onWorkbookPreview(JTemplate jt) { + actionPerformed(jt, jt.getPreviewType().parametersForPreview(), ParameterConsts.REPORTLET); + } + + public static void onFormPreview(JTemplate jt) { + actionPerformed(jt, null, ParameterConsts.FORMLET); + } + + public static void actionPerformed(JTemplate jt, Map map, String actionType) { + if (jt == null) { + return; + } + + DesignerContext.getDesignerFrame().refreshToolbar(); + + jt.stopEditing(); + /* + * alex:如果没有保存,先保存到Env + * + * 如果保存失败,不执行下面的WebPreview + */ + if (!jt.isSaved() && !jt.saveTemplate2Env()) { + return; + } + + FILE currentTemplate = jt.getEditingFILE(); + // carl:是否是保存在运行环境下的模板,不是就不能被预览 + if (currentTemplate instanceof FileNodeFILE) { + browseUrl(currentTemplate, map, actionType, jt); + } else { + // 说明模板没有保存在报表运行环境下面,提示用户 + int selVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Web_Preview_Message"), + Inter.getLocText("Preview_ToolTips"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); + + if (JOptionPane.OK_OPTION == selVal) { + if (!jt.saveAsTemplate2Env()) { + return; + } + currentTemplate = jt.getEditingFILE(); + browseUrl(currentTemplate, map, actionType, jt); + } + } + } + + private static void browseUrl(FILE currentTemplate, Map map, String actionType, JTemplate jt) { + if (!(currentTemplate instanceof FileNodeFILE)) { + return; + } + + if (currentTemplate.exists()) { + String path = currentTemplate.getPath(); + if (path.startsWith(ProjectConstants.REPORTLETS_NAME)) { + path = path.substring(ProjectConstants.REPORTLETS_NAME.length() + 1); + + java.util.List parameterNameList = new java.util.ArrayList(); + java.util.List parameterValueList = new java.util.ArrayList(); + + parameterNameList.add(actionType); + parameterValueList.add(path); + if (map != null) { + for (String key : map.keySet()) { + parameterNameList.add(key); + parameterValueList.add(GeneralUtils.objectToString(map.get(key))); + } + } + DesignUtils.visitEnvServerByParameters(parameterNameList.toArray(new String[parameterNameList.size()]), parameterValueList.toArray(new String[parameterValueList.size()])); + } + } else { + int selVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Web_Preview_Message"), + Inter.getLocText("Preview_ToolTips"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); + if (JOptionPane.OK_OPTION == selVal) { + if (!jt.saveAsTemplate()) { + return; + } + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/AboutAction.java b/designer_base/src/com/fr/design/actions/help/AboutAction.java new file mode 100644 index 0000000000..1c3c48d0ec --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/AboutAction.java @@ -0,0 +1,50 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.help; + +import com.fr.design.actions.UpdateAction; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * help about. + */ +public class AboutAction extends UpdateAction { + public AboutAction() { + this.setMenuKeySet(ABOUT); + this.setName(getMenuKeySet().getMenuKeySetName()+"..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + } + + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + AboutPane aboutPane = new AboutPane(); + AboutDialog aboutDailog = new AboutDialog(DesignerContext.getDesignerFrame(), aboutPane); + aboutDailog.setVisible(true); + } + + public static final MenuKeySet ABOUT = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'S'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("M_Help-About_Software"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/AboutDialog.java b/designer_base/src/com/fr/design/actions/help/AboutDialog.java new file mode 100644 index 0000000000..de75b13da3 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/AboutDialog.java @@ -0,0 +1,100 @@ +package com.fr.design.actions.help; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.KeyStroke; + +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.ProductConstants; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * Dialog displaying information about the application. + */ +public class AboutDialog extends JDialog implements ActionListener { + /** + * Construct a new AboutDialog. + */ + public AboutDialog() { + } + + public AboutDialog(Frame parent, JPanel aboutPanel) { + super(parent, true); + + this.setTitle(ProductConstants.PRODUCT_NAME); + this.setResizable(false); + JPanel defaultPane=FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.setContentPane(defaultPane); + + okButton = new UIButton(Inter.getLocText("OK")); + okButton.addActionListener(this); + + tabbedPane = new UITabbedPane(); + sysPane = new SystemInfoPane(); + + tabbedPane.addTab(Inter.getLocText("About"), aboutPanel); + tabbedPane.addTab(Inter.getLocText("System"), sysPane); + + buttonPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + buttonPanel.add(okButton); + + defaultPane.add(tabbedPane, BorderLayout.CENTER); + defaultPane.add(buttonPanel, BorderLayout.SOUTH); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + dialogExit(); + } + }); + + //esp. + InputMap inputMapAncestor = defaultPane.getInputMap( + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + ActionMap actionMap = defaultPane.getActionMap(); + + //transfer focus to CurrentEditor + inputMapAncestor.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dialogExit"); + actionMap.put("dialogExit", new AbstractAction() { + public void actionPerformed(ActionEvent evt) { + dialogExit(); + } + }); + + this.getRootPane().setDefaultButton(okButton); + + this.setSize(new Dimension(660, 600)); + GUICoreUtils.centerWindow(this); + } + + public void dialogExit() { + this.dispose(); + } + + /** + * Called when the ok button is clicked. + */ + public void actionPerformed(ActionEvent e) { + this.dialogExit(); + } + + private SystemInfoPane sysPane; + private JPanel buttonPanel; + private UITabbedPane tabbedPane; + private UIButton okButton; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/AboutPane.java b/designer_base/src/com/fr/design/actions/help/AboutPane.java new file mode 100644 index 0000000000..caa3190889 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/AboutPane.java @@ -0,0 +1,238 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.help; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.BoldFontTextLabel; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.ComparatorUtils; +import com.fr.general.GeneralUtils; +import com.fr.general.Inter; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; +import com.fr.stable.bridge.StableFactory; +import com.fr.start.BBSGuestPaneProvider; + +import javax.swing.*; +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.net.URI; + +public class AboutPane extends JPanel { + private static final String FINEREPORT = "FineReport"; + private static final int DEFAULT_GAP = 12; + private static final String COPYRIGHT_LABEL = "\u00A9 "; + private static final String BUILD_PREFIX = " Build #"; + + public AboutPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + //center panel + JPanel centerPane=FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.add(centerPane, BorderLayout.CENTER); + + JPanel contentPane=FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + centerPane.add(contentPane, BorderLayout.NORTH); + + BoxCenterAlignmentCopyablePane buildCopyPane = new BoxCenterAlignmentCopyablePane( + getBuildTitle(), + GeneralUtils.readBuildNO(), + new String[]{ + Inter.getLocText("FR-Designer-Basic_Copy_Build_NO"), + Inter.getLocText("FR-Designer-Basic_Copy_Build_NO_OK") + }); + contentPane.add(buildCopyPane); + + BoxCenterAligmentPane boxCenterAlignmentPane = new BoxCenterAligmentPane(getCopyRight()); + contentPane.add(boxCenterAlignmentPane); + + boxCenterAlignmentPane = new BoxCenterAligmentPane(Inter.getLocText("About-All_Rights_Reserved")); + contentPane.add(boxCenterAlignmentPane); + + contentPane.add(new BoxCenterAlignmentCopyablePane( + Inter.getLocText("FR-Designer-Basic_Activation_Key"), + DesignerEnvManager.getEnvManager().getActivationKey(), + new String[]{ + Inter.getLocText("FR-Designer-Basic_Copy_Activation_Key"), + Inter.getLocText("FR-Designer-Basic_Activation_Key_Copy_OK") + })); + + if(ComparatorUtils.equals(ProductConstants.APP_NAME,FINEREPORT)){ + boxCenterAlignmentPane = new BoxCenterAligmentPane(Inter.getLocText("Service_Phone") + ProductConstants.COMPARE_TELEPHONE); + contentPane.add(boxCenterAlignmentPane); + } + + BoxCenterAligmentPane actionLabel = getURLActionLabel(ProductConstants.WEBSITE_URL); + BoxCenterAligmentPane emailLabel = getEmailActionLabel(ProductConstants.SUPPORT_EMAIL); + + contentPane.add(actionLabel); + contentPane.add(emailLabel); + + addThankPane(contentPane); + } + + //添加鸣谢面板 + private void addThankPane(JPanel contentPane){ + BBSGuestPaneProvider pane = StableFactory.getMarkedInstanceObjectFromClass(BBSGuestPaneProvider.XML_TAG, BBSGuestPaneProvider.class); + if(pane == null){ + return; + } + + contentPane.add(Box.createVerticalStrut(DEFAULT_GAP)); + contentPane.add((Component) pane); + } + + private String append(String...strs){ + StringBuilder sb = new StringBuilder(); + for(String str : strs){ + sb.append(str); + } + + return sb.toString(); + } + + private String getCopyRight(){ + return append(Inter.getLocText("About-CopyRight"), COPYRIGHT_LABEL, + ProductConstants.HISTORY, StringUtils.BLANK, ProductConstants.COMPANY_NAME); + } + + private String getBuildTitle() { + return append(ProductConstants.APP_NAME, Inter.getLocText("About-Version"), + StringUtils.BLANK, ProductConstants.RELEASE_VERSION, BUILD_PREFIX); + } + + private BoxCenterAligmentPane getEmailActionLabel(final String mailTo){ + ActionLabel emailLabel = new ActionLabel(mailTo); + + emailLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + Desktop.getDesktop().mail(new URI(mailTo)); + } catch (Exception ignore) { + + } + } + }); + + return new BoxCenterAligmentPane(emailLabel); + } + + private BoxCenterAligmentPane getURLActionLabel(final String url){ + ActionLabel actionLabel = new ActionLabel(url); + actionLabel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (Exception exp) { + + } + } + }); + + return new BoxCenterAligmentPane(actionLabel); + } + + class UserLabel extends BoldFontTextLabel { + public UserLabel(String text) { + super(text); + + if (text != null && text.length() > 30) { + ToolTipManager manager = ToolTipManager.sharedInstance(); + manager.registerComponent(this); + } + } + + public String getToolTipText(MouseEvent e) { + return this.getText(); + } + + public Point getToolTipLocation(MouseEvent e) { + return new Point(0, 0); + } + } + + class BoxCenterAligmentPane extends JPanel { + + private UILabel textLabel; + + public BoxCenterAligmentPane(String text) { + this(new UILabel(text)); + } + + public BoxCenterAligmentPane(UILabel label) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel centerPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + this.add(centerPane, BorderLayout.CENTER); + + this.textLabel = label; + centerPane.add(textLabel); + } + + public void setFont(Font font) { + super.setFont(font); + + if (textLabel != null) { + textLabel.setFont(font); + } + } + } + + class BoxCenterAlignmentCopyablePane extends JPanel { + + private UILabel label; + private UILabel textField; + private UILabel lastLabel; + + public BoxCenterAlignmentCopyablePane(String title, String copyText, final String[] descriptions) { + setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel centerPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + this.label = new UILabel(title); + this.textField = new UILabel(copyText); + textField.setBackground(null); + textField.setBorder(null); + + centerPane.add(label); + centerPane.add(textField); + textField.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + StringSelection selection = new StringSelection(textField.getText()); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(selection, selection); + lastLabel.setText(descriptions[1]); + lastLabel.setForeground(Color.RED); + } + } + }); + + this.lastLabel = new UILabel(descriptions[0]); + lastLabel.setForeground(Color.lightGray); + centerPane.add(lastLabel); + + add(centerPane, BorderLayout.CENTER); + } + + public void setFont(Font font) { + super.setFont(font); + + if (textField != null) { + textField.setFont(font); + } + if (label != null) { + label.setFont(font); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/FeedBackAction.java b/designer_base/src/com/fr/design/actions/help/FeedBackAction.java new file mode 100644 index 0000000000..84c6143f00 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/FeedBackAction.java @@ -0,0 +1,57 @@ +package com.fr.design.actions.help; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-18 + * Time: 上午9:09 + */ +public class FeedBackAction extends UpdateAction { + + public FeedBackAction() { + this.setMenuKeySet(FEED_BACK); + this.setName(getMenuKeySet().getMenuName()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_help/feedback.png")); + } + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + final DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + FeedBackPane feedBackPane = new FeedBackPane(); + BasicDialog basicDialog =feedBackPane.showWindow(designerFrame,false); + feedBackPane.setFeedbackDialog(basicDialog); + basicDialog.setVisible(true); + } + + public static final MenuKeySet FEED_BACK = new MenuKeySet() { + @Override + public char getMnemonic() { + return 0; + } + + @Override + public String getMenuName() { + return Inter.getLocText("product_feedback"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/FeedBackPane.java b/designer_base/src/com/fr/design/actions/help/FeedBackPane.java new file mode 100644 index 0000000000..b328fddbc7 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/FeedBackPane.java @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.actions.help; + +import com.fr.base.FRContext; +import com.fr.base.FeedBackInfo; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; +import com.fr.design.utils.DesignUtils; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.border.MatteBorder; +import javax.swing.plaf.ColorUIResource; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; +import java.awt.*; +import java.awt.event.*; +import java.util.Date; +import java.util.concurrent.CancellationException; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-18 + * Time: 上午9:50 + */ +public class FeedBackPane extends BasicPane { + + private static final Dimension DIALOG_SIZE = new Dimension(660, 600); + private static final Dimension TEXT_AREA_SIZE = new Dimension(585, 180); + private static final int TEXT_FIELD_WIDTH = 160; + private static final int TEXT_FIELD_HEIGHT = 21; + private static final int GAP = 5; + private static final ColorUIResource BORDER_COLOR = new ColorUIResource(168, 172, 180); + private static final Border TIP_BORDER = BorderFactory.createEmptyBorder(10, 4, 4, 4); + private static final Border DIALOG_BORDER = BorderFactory.createEmptyBorder(0, 6, 4, 6); + private static final Border INNER_LEFT_BORDER = BorderFactory.createEmptyBorder(15, 18, 0, 0); + private static final Border TEXT_AREA_BORDER = BorderFactory.createEmptyBorder(0, 13, 0, 15); + private static final Border SEND_BORDER = BorderFactory.createEmptyBorder(10, 0, 10, 0); + private static final int DETAIL_TEXT_MAX_LENGTH = 400; + private static final int QQ_MAX_LENGTH = 15; + private static final int EMAIL_MAX_LENGTH = 40; + private static final int TEL_MAX_LENGTH = 11; + private static final String ALLOWED_INTEGER_TYPE = "0123456789"; + private SwingWorker worker; + private JDialog dlg = new JDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Send"), true); + private UIButton ok = new UIButton(Inter.getLocText("OK")); + private UIButton cancle = new UIButton(Inter.getLocText("Cancel")); + private int ifHasBeenWriten = 0; + private UITextArea detailField; + private boolean isSendSuccessful = false; + private UITextField qq = new UITextField() { + public Dimension getPreferredSize() { + return new Dimension(TEXT_FIELD_WIDTH, TEXT_FIELD_HEIGHT); + } + }; + protected UITextField email = new UITextField() { + public Dimension getPreferredSize() { + return new Dimension(TEXT_FIELD_WIDTH, TEXT_FIELD_HEIGHT); + } + }; + protected UITextField phone = new UITextField() { + public Dimension getPreferredSize() { + return new Dimension(TEXT_FIELD_WIDTH, TEXT_FIELD_HEIGHT); + } + }; + private UIButton sendButton = null; + + private BasicDialog feedbackDialog = null; + private JOptionPane send = null; + + public FeedBackPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + initDetailArea(); + UILabel tip = new UILabel(Inter.getLocText("feedback_info")); + tip.setBorder(TIP_BORDER); + this.add(tip, BorderLayout.NORTH); + UIScrollPane scrollPane = new UIScrollPane(initDetailPane()); + scrollPane.setBorder(new MatteBorder(1, 1, 1, 1, BORDER_COLOR)); + this.add(scrollPane, BorderLayout.CENTER); + this.add(getSendButton(), BorderLayout.SOUTH); + sendButton.setEnabled(false); + this.setBorder(DIALOG_BORDER); + initDocument(); + } + + public void setFeedbackDialog(BasicDialog dialog) { + feedbackDialog = dialog; + } + + public Dimension getPreferredSize() { + return DIALOG_SIZE; + } + + + private void initDocument() { + LimitedDocument qqLimited = new LimitedDocument(QQ_MAX_LENGTH); + qqLimited.setAllowChar(ALLOWED_INTEGER_TYPE); + qq.setDocument(qqLimited); + email.setDocument(new LimitedDocument(EMAIL_MAX_LENGTH)); + LimitedDocument phoneLimited = new LimitedDocument(TEL_MAX_LENGTH); + phoneLimited.setAllowChar(ALLOWED_INTEGER_TYPE); + phone.setDocument(phoneLimited); + } + + + private void initDetailArea() { + detailField = new UITextArea() { + public Dimension getPreferredSize() { + return TEXT_AREA_SIZE; + } + }; + this.detailField.setForeground(Color.gray); + this.detailField.setText(Inter.getLocText("feedback_tip")); + detailField.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + if (ifHasBeenWriten == 0) { + detailField.setText(StringUtils.EMPTY); + detailField.setDocument(new LimitedDocument(DETAIL_TEXT_MAX_LENGTH)); + ifHasBeenWriten = 1; + } + } + + public void keyReleased(KeyEvent e) { + if (ifHasBeenWriten == 0) { + detailField.setText(StringUtils.EMPTY); + detailField.setDocument(new LimitedDocument(DETAIL_TEXT_MAX_LENGTH)); + ifHasBeenWriten = 1; + } + detailField.setForeground(Color.black); + String text = detailField.getText(); + // 判断在中文输入状态是否还包含提示符 要删掉 + String tip = Inter.getLocText("feedback_tip"); + if (text.contains(tip)) { + text = text.substring(0, text.indexOf(tip)); + detailField.setText(text); + } + sendButton.setEnabled(!(ifHasBeenWriten == 0 || ComparatorUtils.equals(detailField.getText().trim(), StringUtils.EMPTY))); + } + }); + + detailField.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (ifHasBeenWriten == 0) { + detailField.setText(StringUtils.EMPTY); + detailField.setDocument(new LimitedDocument(DETAIL_TEXT_MAX_LENGTH)); + ifHasBeenWriten = 1; + } + } + }); + } + + private JPanel initDetailPane() { + double p = TableLayout.PREFERRED; + UILabel info = new UILabel(Inter.getLocText("detail_description") + ":"); + info.setBorder(INNER_LEFT_BORDER); + JPanel contactPane = getContactPane(); + contactPane.setBorder(INNER_LEFT_BORDER); + UILabel contact = new UILabel(Inter.getLocText("contact_info") + ":"); + contact.setBorder(INNER_LEFT_BORDER); + JPanel jPanel = new JPanel(); + jPanel.add(detailField); + jPanel.setBorder(TEXT_AREA_BORDER); + Component[][] components = new Component[][]{ + new Component[]{info}, + new Component[]{jPanel}, + new Component[]{contact}, + new Component[]{contactPane}, + }; + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p}; + int[][] rowCount = {{1}, {1}, {1}, {1}}; + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_MEDIUM, LayoutConstants.VGAP_MEDIUM); + } + + + protected JPanel getContactPane() { + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + Component[][] components = new Component[][]{ + new Component[]{new UILabel("QQ:", SwingConstants.RIGHT), qq}, + new Component[]{new UILabel(Inter.getLocText("email") + ":", SwingConstants.RIGHT), email}, + new Component[]{new UILabel(Inter.getLocText("mobile_number") + ":", SwingConstants.RIGHT), phone} + }; + double[] rowSize = {p, p, p}; + double[] columnSize = {p, p}; + int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}}; + return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_MEDIUM, LayoutConstants.VGAP_MEDIUM); + } + + private JPanel getSendButton() { + JPanel controlPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel buttonsPane = new JPanel(new FlowLayout(FlowLayout.LEFT, GAP, 0)); + controlPane.add(buttonsPane, BorderLayout.EAST); + sendButton = new UIButton(Inter.getLocText("Send")); + buttonsPane.add(sendButton); + buttonsPane.setBorder(SEND_BORDER); + sendButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + doWithSendPane(); + } + }); + controlPane.setBorder(new EmptyBorder(0, 0, GAP, 0)); + return controlPane; + } + + + private void doWithSendPane() { + Object[] options = new Object[]{ok, cancle}; + send = new JOptionPane(Inter.getLocText("sending"), + JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, options, options[0]); + ok.setEnabled(false); + ok.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (isSendSuccessful) { + dlg.dispose(); + feedbackDialog.dispose(); + } else { + ok.setEnabled(false); + send.setMessage(Inter.getLocText("sending")); + setWorker(send); + worker.execute(); + } + } + }); + cancle.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + worker.cancel(true); + dlg.dispose(); + } + }); + + dlg.setContentPane(send); + dlg.pack(); + dlg.setLocationRelativeTo(DesignerContext.getDesignerFrame()); + setWorker(send); + worker.execute(); + dlg.setVisible(true); + + + } + + + private void setWorker(final JOptionPane send) { + worker = new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + FeedBackInfo feedBackInfo = new FeedBackInfo(new Date(), qq.getText(), email.getText(), phone.getText(), detailField.getText()); + try { + return DesignUtils.sendFeedBack(feedBackInfo); + } catch (Exception e) { + FRLogger.getLogger().error(e.getMessage()); + return false; + } + } + + public void done() { + try { + boolean model = get(); + ok.setEnabled(true); + cancle.setEnabled(!model); + if (model) { + //发送成功 + isSendSuccessful = true; + send.setMessage(Inter.getLocText("HJS-Send_Successfully") + "!"); + } else { + isSendSuccessful = false; + String[] message = new String[]{"HJS-Send_Failed", "try_resending"}; + String[] operator = new String[]{",", ""}; + send.setMessage(Inter.getLocText(message, operator)); + } + } catch (Exception e) { + isSendSuccessful = false; + if (!(e instanceof CancellationException)) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + } + }; + } + + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("product_feedback"); + } + + + private class LimitedDocument extends PlainDocument { + private static final long serialVersionUID = 1L; + private int maxLength = -1;// 允许的最大长度 + private String allowCharAsString = null;// 允许的字符串格式(0123456789) + + public LimitedDocument(int maxLength) { + super(); + this.maxLength = maxLength; + } + + public void insertString(int offset, String str, AttributeSet attrSet) throws BadLocationException { + if (str == null) { + return; + } + if (allowCharAsString != null && str.length() == 1) { + if (allowCharAsString.indexOf(str) == -1) { + Toolkit.getDefaultToolkit().beep();// 发出一个警告声 + return;// 不是所要求的字符格式,就直接返回,不进行下面的添加 + } + } + char[] charVal = str.toCharArray(); + String strOldValue = getText(0, getLength()); + char[] tmp = strOldValue.toCharArray(); + if (maxLength != -1 && (tmp.length + charVal.length > maxLength)) { + Toolkit.getDefaultToolkit().beep();// 发出一个警告声 + return;// 长度大于指定的长度maxLength,也直接返回,不进行下面的添加 + } + super.insertString(offset, str, attrSet); + } + + public void setAllowChar(String str) { + allowCharAsString = str; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/ForumAction.java b/designer_base/src/com/fr/design/actions/help/ForumAction.java new file mode 100644 index 0000000000..8df49a5bba --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/ForumAction.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.actions.help; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-18 + * Time: 上午9:21 + */ +public class ForumAction extends UpdateAction { + public ForumAction() { + this.setMenuKeySet(FORUM); + this.setName(getMenuKeySet().getMenuName()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_help/product_forum.png")); + } + + + /** + * 动作 + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + String url = "http://bbs.finereport.com/"; + if (StringUtils.isEmpty(url)) { + FRContext.getLogger().info("The URL is empty!"); + return; + } + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException exp) { + JOptionPane.showMessageDialog(null, Inter.getLocText("Set_default_browser")); + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + } catch (URISyntaxException exp) { + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + } catch (Exception exp) { + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + FRContext.getLogger().error("Can not open the browser for URL: " + url); + } + } + + public static final MenuKeySet FORUM = new MenuKeySet() { + @Override + public char getMnemonic() { + return 0; + } + + @Override + public String getMenuName() { + return Inter.getLocText("Forum"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/SupportQQAction.java b/designer_base/src/com/fr/design/actions/help/SupportQQAction.java new file mode 100644 index 0000000000..9dcb07987e --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/SupportQQAction.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.actions.help; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.Inter; +import com.fr.stable.ProductConstants; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Created with IntelliJ IDEA. + * User: wikky + * Date: 14-6-20 + * Time: 上午10:01 + * To change this template use File | Settings | File Templates. + */ +public class SupportQQAction extends UpdateAction { + + public SupportQQAction(){ + this.setMenuKeySet(SUPPORT_QQ); + this.setName(getMenuKeySet().getMenuName()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_help/support_qq.png")); + } + @Override + public void actionPerformed(ActionEvent e) { + try { + Desktop.getDesktop().browse(new URI(ProductConstants.SUPPORT_QQ)); + } catch (IOException exp) { + JOptionPane.showMessageDialog(null, Inter.getLocText("Set_default_browser")); + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + } catch (URISyntaxException exp) { + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + } + } + + public static final MenuKeySet SUPPORT_QQ = new MenuKeySet() { + @Override + public char getMnemonic() { + return 0; + } + + @Override + public String getMenuName() { + return Inter.getLocText("Support_QQ"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/SystemInfoPane.java b/designer_base/src/com/fr/design/actions/help/SystemInfoPane.java new file mode 100644 index 0000000000..947afc6dbf --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/SystemInfoPane.java @@ -0,0 +1,69 @@ +package com.fr.design.actions.help; + +import java.awt.BorderLayout; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.Properties; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumnModel; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.ProductConstants; + +public class SystemInfoPane extends JPanel { + public SystemInfoPane() { + super(FRGUIPaneFactory.createBorderLayout()); + + DefaultTableModel tableModel = new DefaultTableModel(); + JTable table = new JTable(tableModel) { + public boolean isCellEditable(int row, int column) { + return false; + } + }; + tableModel.addColumn(Inter.getLocText("Property")); + tableModel.addColumn(Inter.getLocText("Value")); + + Properties properties = System.getProperties(); + Object[] keys = new Object[properties.size()]; + + int index = 0; + Enumeration enumeration = properties.propertyNames(); + while (enumeration.hasMoreElements()) { + keys[index++] = enumeration.nextElement(); + } + Arrays.sort(keys); + + for (int i = 0; i < keys.length; i++) { + Object[] tableRowData = new Object[2]; + String keyValue = keys[i].toString(); + // james:屏蔽掉exe4j的内容 + if (keyValue.indexOf("exe4j") != -1) { + continue; + } + // james:这个也是exe4j的东东 + if ("install4j.exeDir".equals(keyValue)) { + continue; + } + + if(keyValue.indexOf("FineReport") != -1){ + keys[i] = keyValue.replaceAll("FineReport", ProductConstants.APP_NAME); + } + + tableRowData[0] = keys[i]; + tableRowData[1] = properties.getProperty((String) keys[i]); + tableModel.addRow(tableRowData); + } + + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + TableColumnModel columnModel = table.getColumnModel(); + columnModel.getColumn(0).setPreferredWidth(160); + columnModel.getColumn(1).setPreferredWidth(240); + + add(new JScrollPane(table), BorderLayout.CENTER); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/TutorialAction.java b/designer_base/src/com/fr/design/actions/help/TutorialAction.java new file mode 100644 index 0000000000..b2f83e4948 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/TutorialAction.java @@ -0,0 +1,98 @@ +package com.fr.design.actions.help; + +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.Locale; + +import javax.swing.KeyStroke; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.Utils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.general.http.HttpClient; +import com.fr.stable.OperatingSystem; +import com.fr.stable.ProductConstants; +import com.fr.stable.StableUtils; + +public class TutorialAction extends UpdateAction { + + public TutorialAction() { + this.setMenuKeySet(HELP_TUTORIAL); + this.setName(getMenuKeySet().getMenuName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_help/help.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + private void nativeExcuteMacInstallHomePrograms(String appName) { + String installHome = StableUtils.getInstallHome(); + if(installHome == null) { + FRContext.getLogger().error("Can not find the install home, please check it."); + } else { + String appPath = StableUtils.pathJoin(new String[]{installHome, "bin", appName}); + if(!(new File(appPath)).exists()) { + FRContext.getLogger().error(appPath + " can not be found."); + } + + String cmd = "open " + appPath; + Runtime runtime = Runtime.getRuntime(); + + try { + runtime.exec(cmd); + } catch (IOException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + } + } + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + Locale locale = FRContext.getLocale(); + if (ComparatorUtils.equals(locale, Locale.CHINA) || ComparatorUtils.equals(locale, Locale.TAIWAN)){ + HttpClient client = new HttpClient(ProductConstants.HELP_URL); + if(client.getResponseCode() != -1) { + try { + Desktop.getDesktop().browse(new URI(ProductConstants.HELP_URL)); + return; + } catch (Exception e) { + //出了异常的话, 依然打开本地教程 + } + } + } + if (OperatingSystem.isMacOS()) { + nativeExcuteMacInstallHomePrograms("helptutorial.app"); + } + else { + Utils.nativeExcuteInstallHomePrograms("helptutorial.exe"); + } + } + + public static final MenuKeySet HELP_TUTORIAL = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'T'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("M_Help-Tutorial"); + } + + @Override + public KeyStroke getKeyStroke() { + return KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0); + } + }; + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/help/WebDemoAction.java b/designer_base/src/com/fr/design/actions/help/WebDemoAction.java new file mode 100644 index 0000000000..a1808e43e7 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/help/WebDemoAction.java @@ -0,0 +1,46 @@ +package com.fr.design.actions.help; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.Inter; +import com.fr.start.StartServer; + +import javax.swing.*; +import java.awt.event.ActionEvent; + + +public class WebDemoAction extends UpdateAction { + public WebDemoAction() { + this.setMenuKeySet(PRODUCT_DEMO); + this.setName(getMenuKeySet().getMenuName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_help/demo.png")); + } + + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + StartServer.browerDemoURL(); + } + + public static final MenuKeySet PRODUCT_DEMO = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'D'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("Product_Demo"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/ConnectionListAction.java b/designer_base/src/com/fr/design/actions/server/ConnectionListAction.java new file mode 100644 index 0000000000..e24826b50b --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/ConnectionListAction.java @@ -0,0 +1,171 @@ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.base.ModifiedTable; +import com.fr.data.impl.Connection; +import com.fr.dav.LocalEnv; +import com.fr.design.actions.UpdateAction; +import com.fr.design.data.datapane.connect.ConnectionManagerPane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.util.HashMap; + +/** + * DatasourceList Action + */ +public class ConnectionListAction extends UpdateAction { + private static final int BYTENUM = 1444; + + public ConnectionListAction() { + this.setMenuKeySet(DEFINE_DATA_CONNECTION); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_web/connection.png")); + } + + public static final MenuKeySet DEFINE_DATA_CONNECTION = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'D'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("Server-Define_Data_Connection"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + + /** + * 执行动作 + * + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + final DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + final DatasourceManager backupManager = datasourceManager.getBackUpManager(); + final ConnectionManagerPane databaseManagerPane = new ConnectionManagerPane() { + public void complete() { + populate(datasourceManager); + } + + protected void renameConnection(String oldName, String newName) { + datasourceManager.getConnectionLocalModifyTable().rename(oldName, newName); + } + }; + final BasicDialog databaseListDialog = databaseManagerPane.showLargeWindow(designerFrame, null); + databaseListDialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + if (!databaseManagerPane.isNamePermitted()) { + databaseListDialog.setDoOKSucceed(false); + return; + } + if (!doWithDatasourceManager(datasourceManager, backupManager, databaseManagerPane, databaseListDialog)) { + //如果更新失败,则不关闭对话框,也不写xml文件,并且将对话框定位在请重命名的那个对象页面 + return; + } + // marks:保存数据 + writeFile(datasourceManager); + } + + public void doCancel() { + datasourceManager.synchronizedWithServer(); + } + }); + databaseListDialog.setVisible(true); + } + + + private void writeFile(DatasourceManagerProvider datasourceManager) { + Env currentEnv = FRContext.getCurrentEnv(); + try { + boolean isSuccess = currentEnv.writeResource(datasourceManager); + if (!isSuccess) { + throw new RuntimeException(Inter.getLocText("FR-Designer_Already_exist")); + } + } catch (Exception e) { + throw new RuntimeException(Inter.getLocText("FR-Designer_Already_exist")); + } + DesignerContext.getDesignerBean("databasename").refreshBeanElement(); + } + + /** + * 是否正常更新完datasourceManager + * + * @param datasourceManager + * @param databaseManagerPane + * @return + */ + private boolean doWithDatasourceManager(DatasourceManagerProvider datasourceManager, DatasourceManager backupManager, + ConnectionManagerPane databaseManagerPane, BasicDialog databaseListDialog) { + databaseManagerPane.update(datasourceManager); + HashMap modifyDetails = datasourceManager.getConnectionModifyDetails(); + modifyDetails.clear(); + Env currentEnv = FRContext.getCurrentEnv(); + ModifiedTable localModifiedTable = datasourceManager.checkConnectionModifyTable(backupManager, currentEnv.getUserID()); + boolean isFailed = false; + if (currentEnv.isSupportLocalFileOperate() && !((LocalEnv) currentEnv).isNoRemoteUser()) { + //如果是本地,并且有远程用户时则更新自己的修改表 + datasourceManager.updateSelfConnectionTotalModifiedTable(localModifiedTable, ModifiedTable.LOCAL_MODIFIER); + } else { + if (!currentEnv.isSupportLocalFileOperate()) { + //如果是远程,则去取服务器的最新的修改表,检查有没有冲突 + ModifiedTable currentServerModifyTable = currentEnv.getDataSourceModifiedTables(DatasourceManager.CONNECTION); + if (localModifiedTable.checkModifiedTableConflictWithServer(currentServerModifyTable, currentEnv.getUserID())) { + //有冲突,进行提示 + String title = Inter.getLocText(new String[]{"Select", "Single", "Setting"}); + int returnVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), localModifiedTable.getWaringMessage(), title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (returnVal == JOptionPane.YES_OPTION) { + //点击是,进行相应刷新去冲突 + datasourceManager.synchronizedWithServer(backupManager, DatasourceManager.CONNECTION); + //要是有重命名冲突的,则对详细的修改表先进行修改 + datasourceManager.doWithConnectionConflict(localModifiedTable); + localModifiedTable.removeConfilct(); + modifyDetails.clear(); + //更新面板 + databaseManagerPane.populate(datasourceManager); + } else { + //更新失败,继续停留页面 + isFailed = true; + } + + } + } + } + //存在请重命名则不能更新 + int index = datasourceManager.isConnectionMapContainsRename(); + if (index != -1) { + isFailed = true; + databaseManagerPane.setSelectedIndex(index); + } + databaseListDialog.setDoOKSucceed(!isFailed); + //如果修改成功,则去远程端增量修改修改表 + if (!isFailed && !currentEnv.isSupportLocalFileOperate()) { + currentEnv.writeDataSourceModifiedTables(localModifiedTable, DatasourceManager.CONNECTION); + localModifiedTable.clear(); + modifyDetails.clear(); + } + return !isFailed; + } + + + public void update() { + this.setEnabled(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/FunctionManagerAction.java b/designer_base/src/com/fr/design/actions/server/FunctionManagerAction.java new file mode 100644 index 0000000000..664d448622 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/FunctionManagerAction.java @@ -0,0 +1,79 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.FunctionManagerPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.FunctionManager; +import com.fr.file.FunctionManagerProvider; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.ActionEvent; + + +/** + * FunctionManager. + */ +public class FunctionManagerAction extends UpdateAction { + public FunctionManagerAction() { + this.setMenuKeySet(FUNCTION_MANAGER); + this.setName(getMenuKeySet().getMenuKeySetName()+"..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_web/function.png")); + } + + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + final FunctionManagerPane functionManagerPane = new FunctionManagerPane(); + BasicDialog functionManagerDialog = + functionManagerPane.showWindow( + DesignerContext.getDesignerFrame(),null); + final FunctionManagerProvider functionManager = FunctionManager.getProviderInstance(); + functionManagerDialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + functionManagerPane.update(functionManager); + Env currentEnv = FRContext.getCurrentEnv(); + try { + currentEnv.writeResource(functionManager); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + }); + functionManagerPane.populate(functionManager); + functionManagerDialog.setVisible(true); + } + + public void update() { + this.setEnabled(true); + } + + public static final MenuKeySet FUNCTION_MANAGER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'F'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("M_Server-Function_Manager"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/GlobalParameterAction.java b/designer_base/src/com/fr/design/actions/server/GlobalParameterAction.java new file mode 100644 index 0000000000..e2597c0fe7 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/GlobalParameterAction.java @@ -0,0 +1,93 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.base.ConfigManager; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.DesignModelAdapter; +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.parameter.ParameterManagerPane; +import com.fr.general.Inter; +import com.fr.base.ConfigManagerProvider; + +import javax.swing.*; +import java.awt.event.ActionEvent; + + +/** + * Parameter dialog + */ +public class GlobalParameterAction extends UpdateAction { + public GlobalParameterAction() { + this.setMenuKeySet(GLOBAL_PARAMETER); + this.setName(getMenuKeySet().getMenuKeySetName() + "..."); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/p.png")); + } + + /** + * 动作 + * + * @param e 事件 + */ + public void actionPerformed(ActionEvent e) { + final DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + final ParameterManagerPane parameterManagerPane = new ParameterManagerPane(); + + final BasicDialog parameterManagerDialog = parameterManagerPane.showWindow(designerFrame); + + //marks:读取服务器配置信息 + final ConfigManagerProvider configManager = ConfigManager.getProviderInstance(); + + parameterManagerPane.populate(configManager); + parameterManagerDialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + //apply new parameter list. + parameterManagerPane.update(configManager); + //marks:保存数据 + Env currentEnv = FRContext.getCurrentEnv(); + try { + currentEnv.writeResource(configManager); + } catch (Exception ex) { + FRContext.getLogger().error(ex.getMessage(), ex); + } + DesignModelAdapter model = DesignModelAdapter.getCurrentModelAdapter(); + if (model != null) { + model.parameterChanged(); + } + parameterManagerDialog.setDoOKSucceed(!parameterManagerPane.isContainsRename()); + } + }); + parameterManagerDialog.setModal(true); + parameterManagerDialog.setVisible(true); + } + + public void update() { + this.setEnabled(true); + } + + public static final MenuKeySet GLOBAL_PARAMETER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'G'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("M_Server-Global_Parameters"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/GlobalTableDataAction.java b/designer_base/src/com/fr/design/actions/server/GlobalTableDataAction.java new file mode 100644 index 0000000000..87d095dcb6 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/GlobalTableDataAction.java @@ -0,0 +1,197 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.actions.server; + +import com.fr.base.*; +import com.fr.dav.LocalEnv; +import com.fr.design.DesignModelAdapter; +import com.fr.design.actions.UpdateAction; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.tabledata.ResponseDataSourceChange; +import com.fr.design.data.tabledata.tabledatapane.TableDataManagerPane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.menu.MenuKeySet; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.util.HashMap; +import java.util.Map; + +/** + * Global TableData. + */ +public class GlobalTableDataAction extends UpdateAction implements ResponseDataSourceChange { + //private static TableDataManagerPane globalTableDataPane = new TableDataManagerPane(); + + public GlobalTableDataAction() { + this.setMenuKeySet(SERVER_TABLEDATA); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png")); + } + + public static final MenuKeySet SERVER_TABLEDATA = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'S'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("DS-Server_TableData"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; + + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + final DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + final DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + final DatasourceManager backupManager = datasourceManager.getBackUpManager(); + final TableDataManagerPane globalTableDataPane = new TableDataManagerPane() { + public void complete() { + populate(datasourceManager); + } + + protected void renameConnection(String oldName, String newName) { + datasourceManager.getConnectionLocalModifyTable().rename(oldName, newName); + } + }; + final BasicDialog globalTableDataDialog = globalTableDataPane.showLargeWindow(designerFrame, null); + + globalTableDataDialog.addDialogActionListener(new DialogActionAdapter() { + + @Override + public void doOk() { + if (!globalTableDataPane.isNamePermitted()) { + globalTableDataDialog.setDoOKSucceed(false); + return; + } + + DesignTableDataManager.clearGlobalDs(); + globalTableDataPane.update(datasourceManager); + if (!doWithDatasourceManager(datasourceManager, backupManager, globalTableDataPane, globalTableDataDialog)) { + //如果更新失败,则不关闭对话框,也不写xml文件,并且将对话框定位在请重命名的那个对象页面 + return; + } + + writeFile(datasourceManager); + // 刷新共有数据集 + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + fireDSChanged(globalTableDataPane.getDsChangedNameMap()); + } + + public void doCancel() { + datasourceManager.synchronizedWithServer(); + } + }); + globalTableDataDialog.setVisible(true); + } + + private void writeFile(DatasourceManagerProvider datasourceManager) { + + Env currentEnv = FRContext.getCurrentEnv(); + try { + boolean isSuccess = currentEnv.writeResource(datasourceManager); + if (!isSuccess) { + throw new RuntimeException(Inter.getLocText("FR-Designer_Already_exist")); + } + } catch (Exception e) { + throw new RuntimeException(Inter.getLocText("FR-Designer_Already_exist")); + } + } + + + /** + * 是否正常更新完datasourceManager + * + * @param datasourceManager + * @param databaseManagerPane + * @return + */ + private boolean doWithDatasourceManager(DatasourceManagerProvider datasourceManager, DatasourceManager backupManager, + TableDataManagerPane tableDataManagerPane, BasicDialog databaseListDialog) { + HashMap modifyDetails = datasourceManager.getTableDataModifyDetails(); + modifyDetails.clear(); + Env currentEnv = FRContext.getCurrentEnv(); + ModifiedTable localModifiedTable = datasourceManager.checkTableDataModifyTable(backupManager, currentEnv.getUserID()); + boolean isFailed = false; + if (currentEnv.isSupportLocalFileOperate() && !((LocalEnv) currentEnv).isNoRemoteUser()) { + //如果是本地,并且有远程用户时则更新自己的修改表 + datasourceManager.updateSelfTableDataTotalModifiedTable(localModifiedTable, ModifiedTable.LOCAL_MODIFIER); + } else { + if (!currentEnv.isSupportLocalFileOperate()) { + //如果是远程,则去取服务器的最新的修改表,检查有没有冲突 + ModifiedTable currentServerModifyTable = currentEnv.getDataSourceModifiedTables(DatasourceManager.TABLEDATA); + if (localModifiedTable.checkModifiedTableConflictWithServer(currentServerModifyTable, currentEnv.getUserID())) { + //有冲突,进行提示 + String title = Inter.getLocText(new String[]{"Select", "Single", "Setting"}); + int returnVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), localModifiedTable.getWaringMessage(), title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (returnVal == JOptionPane.YES_OPTION) { + //点击是,进行相应刷新去冲突 + datasourceManager.synchronizedWithServer(backupManager, DatasourceManager.TABLEDATA); + //要是有重命名冲突的,则对详细的修改表先进行修改 + datasourceManager.doWithTableDataConfilct(localModifiedTable); + localModifiedTable.removeConfilct(); + modifyDetails.clear(); + //更新面板 + tableDataManagerPane.populate(datasourceManager); + } else { + //更新失败,继续停留页面 + isFailed = true; + } + } + } + } + //存在请重命名则不能更新 + int index = datasourceManager.isTableDataMapContainsRename(); + if (index != -1) { + isFailed = true; + tableDataManagerPane.setSelectedIndex(index); + } + databaseListDialog.setDoOKSucceed(!isFailed); + //如果修改成功,则去远程端增量修改修改表 + if (!isFailed && !currentEnv.isSupportLocalFileOperate()) { + currentEnv.writeDataSourceModifiedTables(localModifiedTable, DatasourceManager.TABLEDATA); + localModifiedTable.clear(); + modifyDetails.clear(); + } + return !isFailed; + } + + + public void update() { + this.setEnabled(true); + } + + /** + * 响应数据集改变 + */ + public void fireDSChanged() { + fireDSChanged(new HashMap()); + } + + /** + * 响应数据集改变 + * + * @param map 对应集 + */ + public void fireDSChanged(Map map) { + DesignTableDataManager.fireDSChanged(map); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/PlatformManagerAction.java b/designer_base/src/com/fr/design/actions/server/PlatformManagerAction.java new file mode 100644 index 0000000000..4448c10249 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/PlatformManagerAction.java @@ -0,0 +1,48 @@ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.MenuKeySet; +import com.fr.design.utils.DesignUtils; +import com.fr.general.Inter; +import com.fr.general.web.ParameterConsts; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +public class PlatformManagerAction extends UpdateAction { + public PlatformManagerAction() { + this.setMenuKeySet(PLATEFORM_MANAGER); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/web/images/platform/platform_16_16.png")); + } + + /** + * 动作 + * @param evt 事件 + */ + public void actionPerformed(ActionEvent evt) { + DesignUtils.visitEnvServerByParameters( + new String[] {ParameterConsts.OP}, + new String[] {"fr_platform"} + ); + } + + public static final MenuKeySet PLATEFORM_MANAGER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'P'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("M_Server-Platform_Manager"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/PluginManagerAction.java b/designer_base/src/com/fr/design/actions/server/PluginManagerAction.java new file mode 100644 index 0000000000..91b4eb810d --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/PluginManagerAction.java @@ -0,0 +1,52 @@ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.extra.PluginManagerPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.MenuKeySet; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.event.ActionEvent; + +/** + * @author richie + * @date 2015-03-09 + * @since 8.0 + */ +public class PluginManagerAction extends UpdateAction { + + public PluginManagerAction() { + this.setMenuKeySet(PLUGIN_MANAGER); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/server/plugin.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + final PluginManagerPane managerPane = new PluginManagerPane(); + BasicDialog dlg = managerPane.showLargeWindow(DesignerContext.getDesignerFrame(),null); + + dlg.setVisible(true); + } + + public static final MenuKeySet PLUGIN_MANAGER = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'I'; + } + + @Override + public String getMenuName() { + return Inter.getLocText("FR-Designer-Plugin_Manager"); + } + + @Override + public KeyStroke getKeyStroke() { + return null; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/server/ProcedureListAction.java b/designer_base/src/com/fr/design/actions/server/ProcedureListAction.java new file mode 100644 index 0000000000..8751c03b31 --- /dev/null +++ b/designer_base/src/com/fr/design/actions/server/ProcedureListAction.java @@ -0,0 +1,63 @@ +package com.fr.design.actions.server; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.design.DesignModelAdapter; +import com.fr.design.actions.UpdateAction; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.tabledata.tabledatapane.ProcedureManagerPane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; + +import java.awt.event.ActionEvent; + +public class ProcedureListAction extends UpdateAction { + public ProcedureListAction() { + this.setName(Inter.getLocText("Datasource-Stored_Procedure") + "(P)" + "..."); + this.setMnemonic('P'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png")); + } + + /** + * 事件触发操作 + * + * @param evt 事件 + * + */ + public void actionPerformed(ActionEvent evt) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + + final DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + final ProcedureManagerPane databaseManagerPane = new ProcedureManagerPane() { + public void complete() { + populate(datasourceManager); + } + }; + BasicDialog databaseListDialog = databaseManagerPane.showLargeWindow(designerFrame,null); + databaseListDialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + DesignTableDataManager.clearGlobalDs(); + databaseManagerPane.update(datasourceManager); + + // marks:保存数据 + try { + FRContext.getCurrentEnv().writeResource(datasourceManager); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + } + }); + databaseListDialog.setVisible(true); + } + + public void update() { + this.setEnabled(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/actions/tabledata/TableDataAction.java b/designer_base/src/com/fr/design/actions/tabledata/TableDataAction.java new file mode 100644 index 0000000000..1f95f5beaf --- /dev/null +++ b/designer_base/src/com/fr/design/actions/tabledata/TableDataAction.java @@ -0,0 +1,97 @@ +package com.fr.design.actions.tabledata; + +import com.fr.base.BaseUtils; +import com.fr.design.data.datapane.TableDataNameObjectCreator; +import com.fr.design.actions.UpdateAction; + +import java.awt.event.ActionEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-19 + * Time: 下午5:21 + */ +public abstract class TableDataAction extends UpdateAction { + public static final String XML_TAG_TEMPLATE = "template_tabledata_Type"; + public static final String XML_TAG_SERVER = "server_tabledata_Type"; + + public TableDataAction() { + this.setName(this.getDisplayName()); + this.setSmallIcon(BaseUtils.readIcon(this.getIconPath())); + } + + + /** + * 名字 + * + * @return + */ + public abstract String getDisplayName(); + + /** + * 图标 + * + * @return + */ + public abstract String getIconPath(); + + /** + * 后缀 + * + * @return + */ + public abstract String getPrefix(); + + + /** + * 得到TableData的声明类 + * + * @return + */ + public abstract Class getTableDataClass(); + + /** + * 得到相应面板的类 + * + * @return + */ + public abstract Class getUpdateTableDataPaneClass(); + + /** + * 用于初始化的类。诺是不需要初始化,则不需要实现 + * + * @return + */ + public Class getClass4Init() { + return null; + } + + /** + * 该菜单后面是否需要插入分割符 + * + * @return 是则返回true + */ + public boolean isNeedInsertSeparator() { + return false; + } + + public TableDataNameObjectCreator getTableDataCreator() { + if (this.getClass4Init() == null) { + return new TableDataNameObjectCreator(this); + } else { + return new TableDataNameObjectCreator(this, getClass4Init()); + } + } + + + /** + * 动作 + * @param e 动作 + */ + public void actionPerformed(ActionEvent e) { + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/BasicBeanPane.java b/designer_base/src/com/fr/design/beans/BasicBeanPane.java new file mode 100644 index 0000000000..ac0ab63d89 --- /dev/null +++ b/designer_base/src/com/fr/design/beans/BasicBeanPane.java @@ -0,0 +1,39 @@ +package com.fr.design.beans; + +import com.fr.design.dialog.BasicPane; + +/** + * Update Pane + */ +public abstract class BasicBeanPane extends BasicPane { + + /** + * Populate. + */ + public abstract void populateBean(T ob); + + /** + * Update. + */ + public abstract T updateBean(); + + public void updateBean(T ob) { + + } + + /** + * 更新权限工具栏面板 + */ + public void populateAuthority() { + + } + + /** + * 仅用来处理图表设计器的地图面板 + * @param mapType 地图类型 + */ + public void dealWidthMap(String mapType){ + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/FurtherBasicBeanPane.java b/designer_base/src/com/fr/design/beans/FurtherBasicBeanPane.java new file mode 100644 index 0000000000..9129c2b870 --- /dev/null +++ b/designer_base/src/com/fr/design/beans/FurtherBasicBeanPane.java @@ -0,0 +1,28 @@ +package com.fr.design.beans; + +/** + * + * @author zhou + * @since 2012-5-30下午12:12:42 + */ +public abstract class FurtherBasicBeanPane extends BasicBeanPane { + /** + * 是否是指定类型 + * @param ob 对象 + * @return 是否是指定类型 + */ + public abstract boolean accept(Object ob); + + /** + * title应该是一个属性,不只是对话框的标题时用到,与其他组件结合时,也会用得到 + * @return 绥化狂标题 + */ + @Override + public abstract String title4PopupWindow(); + + /** + * 重置 + */ + public abstract void reset(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/GroupModel.java b/designer_base/src/com/fr/design/beans/GroupModel.java new file mode 100644 index 0000000000..9f7d3ae715 --- /dev/null +++ b/designer_base/src/com/fr/design/beans/GroupModel.java @@ -0,0 +1,56 @@ +package com.fr.design.beans; + +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; + +/** + * richer:属性和事件分组 + * @since 6.5.3 + */ +public interface GroupModel { + /** + * 该属性所属的分类,普通属性分为基本属性和其它,事件属性根据事件名称不同进行分类 + */ + String getGroupName(); + + /** + * 总共的属性行数 + */ + int getRowCount(); + + /** + * 获取属性表中第row行的渲染器 + * @param row + */ + TableCellRenderer getRenderer(int row); + + /** + * 获取属性表中第row行的编辑器 + * @param row + */ + TableCellEditor getEditor(int row); + + /** + * 获取属性表中第row行第column列的值 + * @param row + * @param column + * @return 表格中的值 + */ + Object getValue(int row, int column); + + /** + * 设置属性表中第row行第column列的值为value + * @param value + * @param row + * @param column + * @return 设置成功则返回true,否则返回false + */ + boolean setValue(Object value, int row, int column); + + /** + * 改行是否可编辑 + * @param row + * @return 第row行可编辑返回true,否则返回false + */ + boolean isEditable(int row); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/location/Absorptionline.java b/designer_base/src/com/fr/design/beans/location/Absorptionline.java new file mode 100644 index 0000000000..f72892eef7 --- /dev/null +++ b/designer_base/src/com/fr/design/beans/location/Absorptionline.java @@ -0,0 +1,190 @@ +package com.fr.design.beans.location; + +import java.awt.Color; +import java.awt.Graphics; + +import com.fr.base.GraphHelper; +import com.fr.design.scrollruler.ScrollRulerComponent; +import com.fr.stable.ArrayUtils; + +public class Absorptionline { + private static Absorptionline lineInX = new Absorptionline(null, null, null, true); + private static Absorptionline lineInY = new Absorptionline(null, null, null, false); + + private Color lineColor = new Color(228, 225, 199); + private Color midLineColor = new Color(196, 227, 237); + private Integer x1; + private Integer x2; + private Integer middle; + private int[] verticalLines; + private int[] horizontalLines; + + private boolean trans; + + /** + * 创建X轴连接线 + * + * @param x x坐标 + * + * @return X轴的连接线 + * + * @date 2015-2-12-下午2:45:49 + * + */ + public static Absorptionline createXAbsorptionline(int x) { + lineInX.x1 = x; + lineInX.x2 = lineInX.middle = null; + lineInX.horizontalLines = lineInX.verticalLines = null; + return lineInX; + } + + /** + * 创建X中轴连接线 + * + * @param x x坐标 + * + * @return X中轴的连接线 + * + * @date 2015-2-12-下午2:45:49 + * + */ + public static Absorptionline createXMidAbsorptionline(int x) { + lineInX.middle = x; + lineInX.x1 = lineInX.x2 = null; + lineInX.horizontalLines = lineInX.verticalLines = null; + return lineInX; + } + + /** + * 创建Y轴连接线 + * + * @param y y坐标 + * + * @return Y轴的连接线 + * + * @date 2015-2-12-下午2:45:49 + * + */ + public static Absorptionline createYAbsorptionline(int y) { + lineInY.x1 = y; + lineInY.x2 = lineInY.middle = null; + lineInY.horizontalLines = lineInY.verticalLines = null; + return lineInY; + } + + /** + * 创建Y中轴连接线 + * + * @param y y坐标 + * + * @return Y中轴的连接线 + * + * @date 2015-2-12-下午2:45:49 + * + */ + public static Absorptionline createYMidAbsorptionline(int y) { + lineInY.middle = y; + lineInY.x1 = lineInY.x2 = null; + lineInY.horizontalLines = lineInY.verticalLines = null; + return lineInY; + } + + private Absorptionline(Integer x1, Integer x2, Integer middleInX, boolean trans) { + this.x1 = x1; + this.x2 = x2; + this.middle = middleInX; + this.trans = trans; + } + + public void setFirstLine(Integer x) { + this.x1 = x; + } + + public void setMidLine(Integer x) { + this.middle = x; + } + + public void setSecondLine(Integer x) { + this.x2 = x; + } + + /** + * 是否相关参数都已设置完毕 + * + * @return 相关参数都已设置完毕 + * + * @date 2015-2-12-下午2:44:46 + * + */ + public boolean isFull() { + return x1 != null && x2 != null && middle != null; + } + + public int[] getVerticalLines() { + return verticalLines; + } + + public void setVerticalLines(int[] verticalLines) { + this.verticalLines = verticalLines; + } + + public int[] getHorizontalLines() { + return horizontalLines; + } + + public void setHorizontalLines(int[] horizontalLines) { + this.horizontalLines = horizontalLines; + } + + public void paint(Graphics g, ScrollRulerComponent designer) { + g = g.create(); + if (trans) { + + for (int i = 0; i < ArrayUtils.getLength(verticalLines); i++) { + g.setColor(lineColor); + GraphHelper.drawLine(g, verticalLines[i] - designer.getHorizontalValue(), 0, verticalLines[i] - designer.getHorizontalValue(), + designer.getDesignerHeight()); + } + + if (x1 != null) { + g.setColor(lineColor); + GraphHelper.drawLine(g, x1 - designer.getHorizontalValue(), 0, x1 - designer.getHorizontalValue(), + designer.getDesignerHeight()); + } + if (x2 != null) { + g.setColor(lineColor); + GraphHelper.drawLine(g, x2 - designer.getHorizontalValue(), 0, x2 - designer.getHorizontalValue(), + designer.getDesignerWidth()); + } + if (middle != null) { + g.setColor(midLineColor); + GraphHelper.drawLine(g, middle - designer.getHorizontalValue(), 0, middle + - designer.getHorizontalValue(), designer.getDesignerHeight()); + } + } else { + for (int i = 0; i < ArrayUtils.getLength(horizontalLines); i++) { + g.setColor(lineColor); + GraphHelper.drawLine(g, 0, horizontalLines[i] - designer.getVerticalValue(), + designer.getDesignerWidth(), horizontalLines[i] - designer.getVerticalValue()); + } + + if (x1 != null) { + + g.setColor(lineColor); + GraphHelper.drawLine(g, 0, x1 - designer.getVerticalValue(), designer.getDesignerWidth(), x1 + - designer.getVerticalValue()); + } + if (x2 != null) { + g.setColor(lineColor); + GraphHelper.drawLine(g, 0, x2 - designer.getVerticalValue(), designer.getDesignerWidth(), x2 + - designer.getVerticalValue()); + } + if (middle != null) { + g.setColor(midLineColor); + GraphHelper.drawLine(g, 0, middle - designer.getVerticalValue(), designer.getDesignerWidth(), middle + - designer.getVerticalValue()); + } + + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/beans/location/MoveUtils.java b/designer_base/src/com/fr/design/beans/location/MoveUtils.java new file mode 100644 index 0000000000..fddb87648f --- /dev/null +++ b/designer_base/src/com/fr/design/beans/location/MoveUtils.java @@ -0,0 +1,332 @@ +/* + * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.beans.location; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; + +/** + * Created by IntelliJ IDEA. + * + * @author: Richer + * @since : 6.5.5 Date: 11-7-1 Time: 下午2:22 + */ +public class MoveUtils { + + public static final int SORPTION_UNIT = 5; + + private MoveUtils() { + + } + + public interface RectangleDesigner { + + /** + * 获取块边界的迭代器 + * + * @return 块边界的迭代器 + * + * @date 2015-2-12-下午2:43:47 + * + */ + RectangleIterator createRectangleIterator(); + + /** + * 设置X轴的线 + * + * @param line 连接线 + * + * @date 2015-2-12-下午2:44:04 + * + */ + void setXAbsorptionline(Absorptionline line); + + /** + * 设置Y轴的线 + * + * @param line 连接线 + * + * @date 2015-2-12-下午2:44:04 + * + */ + void setYAbsorptionline(Absorptionline line); + + /** + * 获取当前选中块的垂直线数组 + * + * @return 块的垂直线数组 + * + */ + int[] getVerticalLine(); + + /** + * 获取当前选中块的水平线数组 + * + * @return 块的水平线数组 + * + */ + int[] getHorizontalLine(); + } + + public interface RectangleIterator { + + /** + * 是否存在下一个块 + * + * @return 是否存在下一个块 + * + * @date 2015-2-12-下午2:41:32 + * + */ + boolean hasNext(); + + /** + * 获取下一个块的bounds + * + * @return 下一个块的bounds + * + * @date 2015-2-12-下午2:41:55 + * + */ + Rectangle nextRectangle(); + + /** + * 获取块的垂直线数组 + * + * @return 块的垂直线数组 + * + * @date 2015-2-12-下午2:42:27 + * + */ + int[] getVerticalLine(); + + /** + * 获取块的水平线数组 + * + * @return 块的水平线数组 + * + * @date 2015-2-12-下午2:42:27 + * + */ + int[] getHorizontalLine(); + } + + private static class PlacePointing { + public PlacePointing(int x) { + this.palce = x; + } + + private boolean isFind() { + return direction != -1; + } + + private int palce; + private int direction = -1; + } + + private static void findX(PlacePointing px, Rectangle bounds, int left, int right, int width) { + if (px.isFind()) { + return; + } + if (Math.abs(bounds.x + bounds.width / 2 - (left + right) / 2) <= SORPTION_UNIT) { + px.palce = bounds.x + bounds.width / 2 - width / 2; + px.direction = SwingConstants.CENTER; + } + int x1 = bounds.x; + if (Math.abs(x1 - left) <= SORPTION_UNIT) { + px.palce = x1; + px.direction = SwingConstants.LEFT; + } + if (Math.abs(x1 - right) <= SORPTION_UNIT) { + px.palce = x1 - width; + px.direction = SwingConstants.RIGHT; + } + int x2 = bounds.x + bounds.width; + if (Math.abs(x2 - left) <= SORPTION_UNIT) { + px.palce = x2; + px.direction = SwingConstants.LEFT; + } + if (Math.abs(x2 - right) <= SORPTION_UNIT) { + px.palce = x2 - width; + px.direction = SwingConstants.RIGHT; + } + } + + private static void findY(PlacePointing py, Rectangle bounds, int top, int bottom, int height) { + if (py.isFind()) { + return; + } + + if (Math.abs(bounds.y + bounds.height / 2 - (top + bottom) / 2) <= SORPTION_UNIT) { + py.palce = bounds.y + bounds.height / 2 - height / 2; + py.direction = SwingConstants.CENTER; + } + int y1 = bounds.y; + if (Math.abs(y1 - top) <= SORPTION_UNIT) { + py.palce = y1; + py.direction = SwingConstants.TOP; + } + if (Math.abs(y1 - bottom) <= SORPTION_UNIT) { + py.palce = y1 - height; + py.direction = SwingConstants.BOTTOM; + } + int y2 = bounds.y + bounds.height; + if (Math.abs(y2 - top) <= SORPTION_UNIT) { + py.palce = y2; + py.direction = SwingConstants.TOP; + } + if (Math.abs(y2 - bottom) <= SORPTION_UNIT) { + py.palce = y2 - height; + py.direction = SwingConstants.BOTTOM; + } + } + + /** + * 吸附 + * + * @param x x坐标 + * @param y y坐标 + * @param width 宽度 + * @param height 高度 + * @param designer 块设计器 + * + * @return 吸附后坐标 + * + * @date 2015-2-12-下午2:39:16 + * + */ + public static Point sorption(int x, int y, int width, int height, RectangleDesigner designer) { + + int left = x, top = y, bottom = top + height, right = left + width; + + PlacePointing px = new PlacePointing(x); + PlacePointing py = new PlacePointing(y); + RectangleIterator iterator = designer.createRectangleIterator(); + + java.util.List cacheRecs = new ArrayList(); + while (iterator.hasNext()) { + Rectangle bounds = iterator.nextRectangle(); + cacheRecs.add(bounds); + findX(px, bounds, left, right, width); + findY(py, bounds, top, bottom, height); + if (px.isFind() && py.isFind()) { + break; + } + } + + createXAbsorptionline(px, designer, width, cacheRecs); + createYAbsorptionline(py, designer, height, cacheRecs); + return new Point(px.palce, py.palce); + } + + private static void createXAbsorptionline(PlacePointing px, RectangleDesigner designer, int width, java.util.List cacheRecs) { + Absorptionline line = null; + RectangleIterator iterator = designer.createRectangleIterator(); + int[] selfVertical = designer.getVerticalLine(); + if (px.direction == SwingConstants.CENTER) { + line = Absorptionline.createXMidAbsorptionline(px.palce + width / 2); + int left = px.palce; + int right = px.palce + width; + for (Rectangle bounds : cacheRecs) { + if (bounds.x == left || bounds.x + bounds.width == left) { + line.setFirstLine(left); + } + if (bounds.x == right || bounds.x + bounds.width == right) { + line.setSecondLine(right); + } + updateVerticalLine(selfVertical, iterator, line); + if (line.isFull()) { + break; + } + } + } else if (px.direction == SwingConstants.LEFT || px.direction == SwingConstants.RIGHT) { + int left = px.direction == SwingConstants.LEFT ? px.palce + width : px.palce; + line = Absorptionline.createXAbsorptionline(px.direction == SwingConstants.LEFT ? px.palce : px.palce + width); + int middle = px.palce + width / 2; + for (Rectangle bounds : cacheRecs) { + if (bounds.x == left || bounds.x + bounds.width == left) { + line.setSecondLine(left); + } + if (bounds.x + bounds.width / 2 == middle) { + line.setMidLine(middle); + } + updateVerticalLine(selfVertical, iterator, line); + if (line.isFull()) { + break; + } + } + } + designer.setXAbsorptionline(line); + } + + private static void createYAbsorptionline(PlacePointing py, RectangleDesigner designer, int height, java.util.List cacheRecs) { + Absorptionline line = null; + RectangleIterator iterator = designer.createRectangleIterator(); + int[] selfHorizontal = designer.getHorizontalLine(); + if (py.direction == SwingConstants.CENTER) { + line = Absorptionline.createYMidAbsorptionline(py.palce + height / 2); + int top = py.palce; + int bottom = py.palce + height; + for (Rectangle bounds : cacheRecs) { + if (bounds.y == top || bounds.y + bounds.height == top) { + line.setFirstLine(top); + } + if (bounds.y == bottom || bounds.y + bounds.height == bottom) { + line.setSecondLine(bottom); + } + updateHorizontalLine(selfHorizontal, iterator, line); + if (line.isFull()) { + break; + } + } + } else if (py.direction == SwingConstants.TOP || py.direction == SwingConstants.BOTTOM) { + int top = py.direction == SwingConstants.TOP ? py.palce + height : py.palce; + line = Absorptionline.createYAbsorptionline(py.direction == SwingConstants.TOP ? py.palce : py.palce + height); + int middle = py.palce + height / 2; + for (Rectangle bounds : cacheRecs) { + if (bounds.y == top || bounds.y + bounds.height == top) { + line.setSecondLine(top); + } + if (bounds.y + bounds.height / 2 == middle) { + line.setMidLine(middle); + } + updateHorizontalLine(selfHorizontal, iterator, line); + if (line.isFull()) { + break; + } + } + } + designer.setYAbsorptionline(line); + } + + //更新纵向行列线 + private static void updateVerticalLine(int[] selfVertical, RectangleIterator iterator, Absorptionline line){ + int[] targetArray = iterator.getVerticalLine(); + if (intersectArrays(targetArray, selfVertical)){ + line.setVerticalLines(targetArray); + } + } + + //更新横向行列线 + private static void updateHorizontalLine(int[] selfHorizontal, RectangleIterator iterator, Absorptionline line){ + int[] targetArray = iterator.getHorizontalLine(); + if (intersectArrays(targetArray, selfHorizontal)){ + line.setHorizontalLines(targetArray); + } + } + + //检测两个数组是否有相交的部分 + private static boolean intersectArrays(int[] targetArray, int[] selfArray){ + for (int i : targetArray) { + for (int j : selfArray) { + if(i == j){ + return true; + } + } + } + + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/border/UIRoundedBorder.java b/designer_base/src/com/fr/design/border/UIRoundedBorder.java new file mode 100644 index 0000000000..842d5584f3 --- /dev/null +++ b/designer_base/src/com/fr/design/border/UIRoundedBorder.java @@ -0,0 +1,50 @@ +package com.fr.design.border; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.border.LineBorder; + +import com.fr.base.GraphHelper; + +public class UIRoundedBorder extends LineBorder { + + private static final long serialVersionUID = 1L; + + private int roundedCorner; + private int lineStyle; + + public UIRoundedBorder(Color color) { + super(color); + } + + public UIRoundedBorder(Color color, int thickness){ + super(color, thickness); + } + + public UIRoundedBorder(Color color, int thickness, int roundedCorners){ + super(color, thickness, true); + this.roundedCorner = roundedCorners; + } + + public UIRoundedBorder(int lineStyle, Color color, int roundedCorners){ + super(color, GraphHelper.getLineStyleSize(lineStyle), true); + this.lineStyle = lineStyle; + this.roundedCorner = roundedCorners; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height){ + Color oldColor = g.getColor(); + + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setColor(lineColor); + GraphHelper.draw(g2d, new RoundRectangle2D.Double(x, y, width - 1, height-1, roundedCorner, roundedCorner),lineStyle); + g2d.setColor(oldColor); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/border/UITitledBorder.java b/designer_base/src/com/fr/design/border/UITitledBorder.java new file mode 100644 index 0000000000..6f8fcfea9d --- /dev/null +++ b/designer_base/src/com/fr/design/border/UITitledBorder.java @@ -0,0 +1,28 @@ +package com.fr.design.border; + +import java.awt.Color; + +import javax.swing.BorderFactory; +import javax.swing.border.TitledBorder; + +public class UITitledBorder extends TitledBorder { + + private static final long serialVersionUID = 1L; + + public static UITitledBorder createBorderWithTitle(String title) { + return new UITitledBorder(title); + } + + private UITitledBorder(String title) { + super(null, title, 4, 2, null, new Color(1, 159, 222)); + init(title); + } + + private void init(String title){ + UIRoundedBorder roundedborder = new UIRoundedBorder(new Color(204, 204, 204), 1, 10); + this.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0), roundedborder)); + + this.setTitle(title); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/bridge/DesignToolbarProvider.java b/designer_base/src/com/fr/design/bridge/DesignToolbarProvider.java new file mode 100644 index 0000000000..089e65e6e4 --- /dev/null +++ b/designer_base/src/com/fr/design/bridge/DesignToolbarProvider.java @@ -0,0 +1,17 @@ +package com.fr.design.bridge; + +/** + * @author richie + * @date 14/11/10 + * @since 8.0 + * 工具栏界面接口 + */ +public interface DesignToolbarProvider { + + public static final String STRING_MARKED = "DesignToolbarProvider"; + + /** + * 刷新工具栏 + */ + public void refreshToolbar(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/cell/FloatElementsProvider.java b/designer_base/src/com/fr/design/cell/FloatElementsProvider.java new file mode 100644 index 0000000000..6bbff0db60 --- /dev/null +++ b/designer_base/src/com/fr/design/cell/FloatElementsProvider.java @@ -0,0 +1,15 @@ +/** + * + */ +package com.fr.design.cell; + +/** + * 悬浮元素 + * + * @author focus + * @time 2014年11月17日下午10:44:10 + * @version + */ +public interface FloatElementsProvider { + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/CellHighlightAddMenuDef.java b/designer_base/src/com/fr/design/condition/CellHighlightAddMenuDef.java new file mode 100644 index 0000000000..b288b642fa --- /dev/null +++ b/designer_base/src/com/fr/design/condition/CellHighlightAddMenuDef.java @@ -0,0 +1,66 @@ +package com.fr.design.condition; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.imenu.UIPopupMenu; +import com.fr.design.menu.MenuDef; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * Define Menu. + */ +public class CellHighlightAddMenuDef extends MenuDef { + public CellHighlightAddMenuDef() { + } + + public CellHighlightAddMenuDef(String name) { + this.setName(name); + } + + public CellHighlightAddMenuDef(String name, char mnemonic) { + this.setName(name); + this.setMnemonic(mnemonic); + } + + // 生成UIButton,iconpath不可为null + public UIButton createUIButton() { + if (createdButton == null) { + if (this.iconPath != null && this.name != null) { + createdButton = new UIButton(BaseUtils.readIcon(this.iconPath)); + } else if (this.iconPath != null) { + createdButton = new UIButton(BaseUtils.readIcon(this.iconPath)); + } else { + createdButton = new UIButton(this.name); + } + createdButton.addMouseListener(mouseListener); + } + + return createdButton; + } + + private MouseListener mouseListener = new MouseAdapter() { + public void mouseReleased(MouseEvent evt) { + Object source = evt.getSource(); + UIButton button = (UIButton) source; + if (!button.isEnabled()) { + return; + } + + UIPopupMenu popupMenu = new UIPopupMenu(); + popupMenu.setInvoker(button); + CellHighlightAddMenuDef.this.updatePopupMenu(popupMenu); + + GUICoreUtils.showPopupMenu(popupMenu, button, 0, button.getSize().height); + } + + public void mouseExited(MouseEvent evt) { + if (createdButton != null) { + createdButton.setEnabled(true); + } + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/ConditionAttrSingleConditionPane.java b/designer_base/src/com/fr/design/condition/ConditionAttrSingleConditionPane.java new file mode 100644 index 0000000000..a3ce3108a8 --- /dev/null +++ b/designer_base/src/com/fr/design/condition/ConditionAttrSingleConditionPane.java @@ -0,0 +1,52 @@ +package com.fr.design.condition; + +/** +* @author richie +* @date 2015-03-26 +* @since 8.0 +*/ +public abstract class ConditionAttrSingleConditionPane extends SingleConditionPane { + protected HighLightConditionAction hightLighAttrUpdateAction = null; + private ConditionAttributesPane conditionAttributesPane; + + public ConditionAttrSingleConditionPane(ConditionAttributesPane conditionAttributesPane) { + this(conditionAttributesPane, true); + } + + public ConditionAttrSingleConditionPane(ConditionAttributesPane conditionAttributesPane, boolean isRemove) { + super(isRemove); + this.conditionAttributesPane = conditionAttributesPane; + } + + /** + * 条目名称 + * @return 名称 + */ + public abstract String nameForPopupMenuItem(); + + @Override + protected String title4PopupWindow() { + return nameForPopupMenuItem(); + } + + /** + * 取消 + */ + public void doCancel() { + conditionAttributesPane.removeConditionAttrSingleConditionPane(this); + conditionAttributesPane.resetUseAbleActionList(); + conditionAttributesPane.updateMenuDef(); + conditionAttributesPane.checkConditionPane(); + conditionAttributesPane.redraw(); + } + + public void setDefault() { + } + + public HighLightConditionAction getHighLightConditionAction() { + if (hightLighAttrUpdateAction == null) { + hightLighAttrUpdateAction = new HighLightConditionAction(nameForPopupMenuItem(), conditionAttributesPane, this); + } + return hightLighAttrUpdateAction; + } +} diff --git a/designer_base/src/com/fr/design/condition/ConditionAttributesPane.java b/designer_base/src/com/fr/design/condition/ConditionAttributesPane.java new file mode 100644 index 0000000000..9737856ddf --- /dev/null +++ b/designer_base/src/com/fr/design/condition/ConditionAttributesPane.java @@ -0,0 +1,133 @@ +package com.fr.design.condition; + + +import com.fr.base.FRContext; +import com.fr.design.actions.UpdateAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.menu.ToolBarDef; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import java.util.HashMap; +import java.util.Iterator; + +public abstract class ConditionAttributesPane extends BasicBeanPane { + protected CellHighlightAddMenuDef menuDef; + + protected JPanel selectedItemPane; + + protected LiteConditionPane liteConditionPane; + + protected java.util.Map classPaneMap = new HashMap(); + + //可用的Actions. + protected java.util.List useAbleActionList = new java.util.ArrayList(); + + protected void initComponents() { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + // 属性 界面 + JPanel propertyChangePane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + this.add(propertyChangePane); + + propertyChangePane.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("Property") + ":", null)); + + // 选择要改变的属性. + JPanel addItemPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + ToolBarDef toolbarDef = new ToolBarDef(); + + menuDef = new CellHighlightAddMenuDef(); + menuDef.setName(Inter.getLocText("Highlight-Click_to_Choose_Property_To_Modify")); + menuDef.setIconPath("com/fr/design/images/control/addPopup.png"); + + toolbarDef.addShortCut(menuDef); + + updateMenuDef(); + + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolbarDef.updateToolBar(toolBar); + + addItemPane.add(toolBar); + + propertyChangePane.add(addItemPane); + + selectedItemPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); +// selectedItemPane.setLayout(new BoxLayout(selectedItemPane,BoxLayout.Y_AXIS)); + + // 选中的添加Itempane + JScrollPane selectedItemScrollPane = new JScrollPane(); + selectedItemScrollPane.setViewportView(selectedItemPane); + selectedItemScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + propertyChangePane.add(selectedItemScrollPane); + } + + public void updateBean(T ob) { + updateMenuDef(); + } + + protected void updateMenuDef() { + menuDef.clearShortCuts(); + for (UpdateAction ac : useAbleActionList) { + menuDef.addShortCut(ac); + } + menuDef.updateMenu(); + menuDef.setEnabled(true); + } + + public void checkConditionPane() { + GUICoreUtils.setEnabled(this.liteConditionPane, this.selectedItemPane.getComponentCount() >= 1); + } + + public ConditionAttrSingleConditionPane createConditionAttrSingleConditionPane(Class clazz) { + try { + return clazz.newInstance(); + } catch (InstantiationException e) { + FRContext.getLogger().error(e.getMessage(), e); + } catch (IllegalAccessException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return null; + } + + protected void addAction2UseAbleActionList() { + useAbleActionList.clear(); + Iterator iterator = classPaneMap.values().iterator(); + + while (iterator.hasNext()) { + useAbleActionList.add(iterator.next().getHighLightConditionAction()); + } + } + + public void resetUseAbleActionList() { + Iterator iterator = classPaneMap.values().iterator(); + + while (iterator.hasNext()) { + ConditionAttrSingleConditionPane pane = iterator.next(); + if (pane.getParent() != this.selectedItemPane && !this.useAbleActionList.contains(pane.getHighLightConditionAction())) { + this.useAbleActionList.add(pane.getHighLightConditionAction()); + } + } + } + + public void removeConditionAttrSingleConditionPane(JComponent component) { + selectedItemPane.remove(component); + } + + public void addConditionAttrSingleConditionPane(JComponent component) { + selectedItemPane.add(component); + } + + + public void removeUpdateActionFromUsableList(UpdateAction action) { + useAbleActionList.remove(action); + } + + public void redraw() { + validate(); + repaint(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/ContinuousTreeSelectionModel.java b/designer_base/src/com/fr/design/condition/ContinuousTreeSelectionModel.java new file mode 100644 index 0000000000..774e8d585e --- /dev/null +++ b/designer_base/src/com/fr/design/condition/ContinuousTreeSelectionModel.java @@ -0,0 +1,128 @@ +package com.fr.design.condition; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeSelectionModel; +import javax.swing.tree.TreePath; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * 一个层次连续节点. + */ +public class ContinuousTreeSelectionModel extends DefaultTreeSelectionModel { + public ContinuousTreeSelectionModel() { + } + + public void addSelectionPaths(TreePath[] paths) { + if (paths == null || paths.length == 0) { + return; + } + + int firstIndex = 0; + Map indexTreePathMap = new HashMap(); + + TreePath[] oldSelectedPaths = this.getSelectionPaths(); + //peter:需要检查是否是同一个父亲的孩子 + if (oldSelectedPaths != null && oldSelectedPaths.length > 0) { + TreePath parentTreePath = oldSelectedPaths[0].getParentPath(); + DefaultMutableTreeNode parentTreeNode = (DefaultMutableTreeNode) parentTreePath.getLastPathComponent(); + + for (int i = 0; i < oldSelectedPaths.length; i++) { + if (ComparatorUtils.equals(parentTreePath, oldSelectedPaths[i].getParentPath())) { + DefaultMutableTreeNode tmpTreeNode = (DefaultMutableTreeNode) oldSelectedPaths[i].getLastPathComponent(); + int treeNodeIndex = parentTreeNode.getIndex(tmpTreeNode); + if (i == 0) { + firstIndex = treeNodeIndex; + } + indexTreePathMap.put(new Integer(treeNodeIndex), GUICoreUtils.getTreePath(tmpTreeNode)); + } + } + + for (int i = 0; i < paths.length; i++) { + if (ComparatorUtils.equals(parentTreePath, paths[i].getParentPath())) { + DefaultMutableTreeNode tmpTreeNode = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + int treeNodeIndex = parentTreeNode.getIndex(tmpTreeNode); + indexTreePathMap.put(new Integer(treeNodeIndex), GUICoreUtils.getTreePath(tmpTreeNode)); + } + } + } else { + firstIndex = findFirstIndexIfNotEmpty(indexTreePathMap, paths); + } + + List newTreePathList = resolveNewTreePathList(firstIndex, indexTreePathMap); + + if (newTreePathList.size() > 0) { + super.addSelectionPaths((TreePath[])newTreePathList.toArray(new TreePath[newTreePathList.size()])); + } + } + + public int findFirstIndexIfNotEmpty(Map indexTreePathMap, TreePath[] paths) { + int firstIndex = 0; + TreePath parentTreePath = paths[0].getParentPath(); + DefaultMutableTreeNode parentTreeNode = (DefaultMutableTreeNode) parentTreePath.getLastPathComponent(); + + for (int i = 0; i < paths.length; i++) { + if (ComparatorUtils.equals(parentTreePath, paths[i].getParentPath())) { + DefaultMutableTreeNode tmpTreeNode = (DefaultMutableTreeNode) paths[i].getLastPathComponent(); + int treeNodeIndex = parentTreeNode.getIndex(tmpTreeNode); + if (i == 0) { + firstIndex = treeNodeIndex; + } + indexTreePathMap.put(new Integer(treeNodeIndex), GUICoreUtils.getTreePath(tmpTreeNode)); + } + } + + return firstIndex; + } + + public List resolveNewTreePathList(int firstIndex, Map indexTreePathMap) { + List newTreePathList = new ArrayList(); + //peter: 先向下找. + for (int i = firstIndex - 1; i >= 0 && indexTreePathMap.size() > 0; i--) { + Object obj = indexTreePathMap.get(new Integer(i)); + if (obj == null) { + break; + } + + newTreePathList.add(obj); + indexTreePathMap.remove(new Integer(i)); + } + + //peter: 先向下找. + for (int i = firstIndex; i < Integer.MAX_VALUE && indexTreePathMap.size() > 0; i++) { + Object obj = indexTreePathMap.get(new Integer(i)); + if (obj == null) { + break; + } + + newTreePathList.add(obj); + indexTreePathMap.remove(new Integer(i)); + } + + return newTreePathList; + } + + // + public void setSelectionPaths(TreePath[] paths) { + if (paths == null || paths.length == 0) { + return; + } + + int firstIndex = 0; + Map indexTreePathMap = new HashMap(); + + firstIndex = findFirstIndexIfNotEmpty(indexTreePathMap, paths); + + List newTreePathList = resolveNewTreePathList(firstIndex, indexTreePathMap); + + if (newTreePathList.size() > 0) { + super.setSelectionPaths((TreePath[])newTreePathList.toArray(new TreePath[newTreePathList.size()])); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/DSColumnLiteConditionPane.java b/designer_base/src/com/fr/design/condition/DSColumnLiteConditionPane.java new file mode 100644 index 0000000000..9de32327d3 --- /dev/null +++ b/designer_base/src/com/fr/design/condition/DSColumnLiteConditionPane.java @@ -0,0 +1,200 @@ +package com.fr.design.condition; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; + +import javax.swing.DefaultComboBoxModel; + +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.tree.TreePath; + +import com.fr.data.condition.CommonCondition; +import com.fr.design.mainframe.JTemplate; +import com.fr.general.ComparatorUtils; +import com.fr.general.data.Condition; +import com.fr.data.condition.JoinCondition; +import com.fr.data.core.Compare; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.formula.CustomVariableResolver; +import com.fr.design.formula.VariableResolver; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.editor.editor.ColumnIndexEditor; +import com.fr.design.editor.editor.ColumnNameEditor; +import com.fr.design.editor.editor.Editor; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; + +public class DSColumnLiteConditionPane extends LiteConditionPane { + /** + * + */ + private static final long serialVersionUID = 1L; + private String[] displayNames = ArrayUtils.EMPTY_STRING_ARRAY; + + @Override + protected BasicBeanPane createUnFormulaConditionPane() { + return new CommonConditionPane(); + } + + @Override + protected VariableResolver variableResolver4FormulaPane() { + return new CustomVariableResolver(displayNames, false); + } + + /** + * 刷新数据列 + * @param displayNames 数据列名称 + */ + public void populateColumns(String[] displayNames) { + CommonConditionPane ccp = (CommonConditionPane) this.defaultConditionPane; + this.displayNames = displayNames; + if(ArrayUtils.isNotEmpty(displayNames)){ + ccp.setEditor(new Editor[] { new ColumnNameEditor(displayNames), new ColumnIndexEditor(displayNames.length)}, displayNames[0]); + } + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + if (selectedTreePath != null) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + JoinCondition joinCondition = (JoinCondition) selectedTreeNode.getUserObject(); + Condition liteCondition = joinCondition.getCondition(); + + if(liteCondition instanceof CommonCondition){ + CommonCondition commonCondition = (CommonCondition) liteCondition; + int columnNumber = commonCondition.getColumnNumber(); + if (columnNumber > 0){ + ccp.keyColumnPane.populate(columnNumber); + } else { + String columnName = commonCondition.getColumnName(); + ccp.keyColumnPane.populate(columnName); + } + } + } + } + + protected class CommonConditionPane extends BasicBeanPane { + private static final long serialVersionUID = 1L; + private ValueEditorPane keyColumnPane; + private UIComboBox conditionOPComboBox; + private ValueEditorPane conditionValuePane; + + CommonConditionPane() { + initComponents(); + } + + public void setEditor(Editor[] editors, Object obj) { + keyColumnPane.setEditors(editors, obj); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + keyColumnPane = ValueEditorPaneFactory.createValueEditorPane(new Editor[] { new ColumnNameEditor(), new ColumnIndexEditor() }); + conditionOPComboBox = new UIComboBox(new DefaultComboBoxModel()); + DefaultComboBoxModel opComboBoxModel = (DefaultComboBoxModel) conditionOPComboBox.getModel(); + int[] allOperators = Compare.getAllOperators(); + for (int i = 0; i < allOperators.length; i++) { + opComboBoxModel.addElement(new Integer(allOperators[i])); + } + this.conditionOPComboBox.setRenderer(new UIComboBoxRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof Integer) { + this.setText(Compare.operator2String(((Integer) value).intValue())); + } + + return this; + } + }); + conditionValuePane = createValueEditorPane(); + keyColumnPane.setPreferredSize(new Dimension(175, keyColumnPane.getPreferredSize().height)); + conditionOPComboBox.setPreferredSize(new Dimension(80, 20)); + Component[][] components = { + { new UILabel(Inter.getLocText("Utils-Available_Columns") + ":"), new UILabel(Inter.getLocText("FR-ConditionB_Operator") + ":"), + new UILabel() }, { keyColumnPane, conditionOPComboBox, conditionValuePane } }; + + double p = TableLayout.PREFERRED; + double rowSize[] = { p, p }; + double columnSize[] = { p, p, TableLayout.FILL }; + + JPanel leftPanel = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); + this.add(leftPanel, BorderLayout.CENTER); + } + + protected ValueEditorPane createValueEditorPane() { + JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if(jTemplate.isChartBook()){ + return ValueEditorPaneFactory.createBasicEditorWithoutFormulaPane(); + } + return ValueEditorPaneFactory.createAllValueEditorPane(); + } + + @Override + public CommonCondition updateBean() { + Object value = conditionValuePane.update(); + int columnNumber = (Integer) keyColumnPane.update(); + String columnName = StringUtils.EMPTY; + + if(keyColumnPane.getCurrentEditor() instanceof ColumnNameEditor && ArrayUtils.isNotEmpty(displayNames)){ + columnName = DSColumnLiteConditionPane.this.displayNames[columnNumber - 1]; + columnNumber = -1; + } + + return new CommonCondition(columnName, columnNumber, new Compare( + ((Integer) conditionOPComboBox.getSelectedItem()).intValue(), value)); + } + + @Override + public void populateBean(CommonCondition condition) { + + String selectionColumn = condition.getColumnName(); + int selectionColumnNumber = condition.getColumnNumber(); + if(StringUtils.isNotEmpty(selectionColumn)){ + for (int i = 0; i < DSColumnLiteConditionPane.this.displayNames.length; i++) { + if(ComparatorUtils.equals(DSColumnLiteConditionPane.this.displayNames[i],selectionColumn)) { + //keyColumnPane.populate(i + 1); + keyColumnPane.populate(selectionColumn); + break; + } + } + }else{ + keyColumnPane.populate(selectionColumnNumber); + } + + Compare compare = condition.getCompare(); + + if (compare == null) { + return; + } + conditionOPComboBox.setSelectedItem(new Integer(compare.getOp())); + + Object value = compare.getValue(); + + conditionValuePane.populate(value); + } + + @Override + protected String title4PopupWindow() { + return " "; + } + + @Override + public void checkValid() throws Exception { + conditionOPComboBox.setSelectedIndex(0); + conditionValuePane.populate(StringUtils.EMPTY); + } + + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/DSColumnSimpleLiteConditionPane.java b/designer_base/src/com/fr/design/condition/DSColumnSimpleLiteConditionPane.java new file mode 100644 index 0000000000..10a3ec4a36 --- /dev/null +++ b/designer_base/src/com/fr/design/condition/DSColumnSimpleLiteConditionPane.java @@ -0,0 +1,21 @@ +package com.fr.design.condition; + +import com.fr.data.condition.CommonCondition; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; + +public class DSColumnSimpleLiteConditionPane extends DSColumnLiteConditionPane { + + @Override + protected BasicBeanPane createUnFormulaConditionPane() { + return new SimpleCommonConditionPane(); + } + + protected class SimpleCommonConditionPane extends CommonConditionPane { + + protected ValueEditorPane createValueEditorPane() { + return ValueEditorPaneFactory.createNoCRNoColumnValueEditorPane(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/HighLightConditionAction.java b/designer_base/src/com/fr/design/condition/HighLightConditionAction.java new file mode 100644 index 0000000000..70ae023bf7 --- /dev/null +++ b/designer_base/src/com/fr/design/condition/HighLightConditionAction.java @@ -0,0 +1,36 @@ +package com.fr.design.condition; + +import com.fr.design.actions.UpdateAction; + +import java.awt.event.ActionEvent; + +/** +* @author richie +* @date 2015-03-26 +* @since 8.0 +*/ +public class HighLightConditionAction extends UpdateAction { + private ConditionAttributesPane conditionAttributesPane; + private ConditionAttrSingleConditionPane conditionAttrSingleConditionPane; + + public HighLightConditionAction(String name, ConditionAttributesPane conditionAttributesPane, ConditionAttrSingleConditionPane conditionAttrSingleConditionPane) { + this.setName(name); + this.conditionAttributesPane = conditionAttributesPane; + this.conditionAttrSingleConditionPane = conditionAttrSingleConditionPane; + } + + /** + * 响应事件 + * @param e 事件 + */ + @Override + public void actionPerformed(ActionEvent e) { + conditionAttributesPane.addConditionAttrSingleConditionPane(conditionAttrSingleConditionPane); + conditionAttributesPane.removeUpdateActionFromUsableList(this); + conditionAttributesPane.updateMenuDef(); + conditionAttributesPane.checkConditionPane(); + conditionAttributesPane.redraw(); + conditionAttrSingleConditionPane.setDefault(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/LiteConditionPane.java b/designer_base/src/com/fr/design/condition/LiteConditionPane.java new file mode 100644 index 0000000000..5c5eea0fff --- /dev/null +++ b/designer_base/src/com/fr/design/condition/LiteConditionPane.java @@ -0,0 +1,950 @@ +package com.fr.design.condition; + +import com.fr.base.BaseUtils; +import com.fr.base.Formula; +import com.fr.data.DataConstants; +import com.fr.data.condition.*; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.FormulaFactory; +import com.fr.design.formula.UIFormula; +import com.fr.design.formula.VariableResolver; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.scrollruler.ModLineBorder; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.general.data.Condition; + +import javax.swing.*; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * peter: LiteCondition Pane. + */ +public abstract class LiteConditionPane extends BasicBeanPane { + private static int MOVE_UP = 0; + private static int MOVE_DOWN = 1; + + private static final long serialVersionUID = 1L; + // peter:这两个变量在弹出公式编辑器的时候,需要用. + private UIRadioButton commonRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_LiteCondition_Common")); + private UIRadioButton formulaRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_LiteCondition_Formula")); + private JPanel conditionCardPane; + protected BasicBeanPane defaultConditionPane; + // card2 + private UITextArea formulaTextArea; + private UIButton modifyButton; + private UIButton addButton; + private UIRadioButton andRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_LiteCondition_ConditionB-AND") + " "); + private UIRadioButton orRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_LiteCondition_ConditionB-OR")); + protected JTree conditionsTree;// Conditions + private UIButton removeButton; + private UIButton moveUpButton; + private UIButton moveDownButton; + private UIButton bracketButton; + private UIButton unBracketButton; + + private ActionListener actionListener1 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + Formula formula; + + String text = formulaTextArea.getText(); + if (text == null || text.length() <= 0) { + formula = new Formula(""); + } else { + formula = new Formula(text); + } + + final UIFormula formulaPane = FormulaFactory.createFormulaPane(); + formulaPane.populate(formula, variableResolver4FormulaPane()); + formulaPane.showLargeWindow(SwingUtilities.getWindowAncestor(LiteConditionPane.this), new DialogActionAdapter() { + + @Override + public void doOk() { + Formula formula = formulaPane.update(); + if (formula.getContent().length() <= 1) {// 如果没有填任何字符,则是空白文本 + formulaTextArea.setText(""); + } else { + formulaTextArea.setText(formula.getContent().substring(1)); + } + } + }).setVisible(true); + } + }; + + + private ActionListener actionListener2 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + // peter:先获得当前的LiteCondition. + + Condition liteCondition = null; + if (commonRadioButton.isSelected()) { + liteCondition = defaultConditionPane.updateBean(); + } else { + liteCondition = new FormulaCondition(formulaTextArea.getText()); + } + + JoinCondition newJoinCondition = new JoinCondition(andRadioButton.isSelected() ? DataConstants.AND : DataConstants.OR, liteCondition); + ExpandMutableTreeNode parentTreeNode = getParentTreeNode(); + boolean result = isExistedInParentTreeNode(parentTreeNode, newJoinCondition); + if (result) { + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(LiteConditionPane.this), + Inter.getLocText("BindColumn-This_Condition_has_been_existed")); + return; + } + + ExpandMutableTreeNode newJionConditionTreeNode = new ExpandMutableTreeNode(newJoinCondition); + parentTreeNode.add(newJionConditionTreeNode); + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) conditionsTree.getModel(); + defaultTreeModel.reload(parentTreeNode); + parentTreeNode.expandCurrentTreeNode(conditionsTree); + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(newJionConditionTreeNode)); + + // peter:必须要检查Enabled. + checkButtonEnabledForList(); + } + }; + + + private MouseAdapter mouseAdapter = new MouseAdapter() { + + @Override + public void mouseEntered(MouseEvent evt) { + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + // peter:当前的节点 + if (selectedTreePath != null) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + JoinCondition oldJoinCondition = (JoinCondition) selectedTreeNode.getUserObject(); + oldJoinCondition.setJoin(andRadioButton.isSelected() ? DataConstants.AND : DataConstants.OR); + + Condition oldLiteCondition = oldJoinCondition.getCondition(); + // peter:如果当前选中的是ListCondition,只要改变Join为AND或者OR,直接返回. + if (oldLiteCondition instanceof ListCondition) { + GUICoreUtils.setEnabled(conditionCardPane, false); + } + } + } + + @Override + public void mouseExited(MouseEvent evt) { + GUICoreUtils.setEnabled(conditionCardPane, conditionCardPane.isEnabled()); + } + }; + + private TreeSelectionListener treeSelectionListener = new TreeSelectionListener() { + + @Override + public void valueChanged(TreeSelectionEvent evt) { + checkButtonEnabledForList(); + + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + if (selectedTreePath == null) { + return; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object userObject = selectedTreeNode.getUserObject(); + if (userObject instanceof JoinCondition) { + JoinCondition joinCondition = (JoinCondition) userObject; + + // peter:先弄join. + int join = joinCondition.getJoin(); + if (join == DataConstants.AND) { + andRadioButton.setSelected(true); + } else { + orRadioButton.setSelected(true); + } + + // peter:当前的liteCondtion. + Condition liteCondition = joinCondition.getCondition(); + // elake:两种Condition对应于数据列和高亮. + if (liteCondition instanceof CommonCondition || liteCondition instanceof ObjectCondition) { + Condition commonCondition = liteCondition; + commonRadioButton.setSelected(true); + applyCardsPane(); + + defaultConditionPane.populateBean((T) commonCondition); + + } else if (liteCondition instanceof FormulaCondition) { + FormulaCondition formulaCondition = (FormulaCondition) liteCondition; + + formulaRadioButton.setSelected(true); + applyCardsPane(); + + formulaTextArea.setText(formulaCondition.getFormula()); + } + } + } + }; + + + private ActionListener actionListener3 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + if (selectedTreePath == null) { + return; + } + + int returnVal = JOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(LiteConditionPane.this), + Inter.getLocText("Utils-Are_you_sure_to_remove_the_selected_item") + "?", Inter.getLocText("FR-Designer_Remove"), + JOptionPane.OK_CANCEL_OPTION); + if (returnVal == JOptionPane.OK_OPTION) { + DefaultTreeModel treeModel = (DefaultTreeModel) conditionsTree.getModel(); + + TreePath[] selectedTreePaths = conditionsTree.getSelectionPaths(); + for (int i = selectedTreePaths.length - 1; i >= 0; i--) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePaths[i].getLastPathComponent(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + + // peter:将要选择节点. + ExpandMutableTreeNode nextSelectTreeNode; + if (parentTreeNode.getChildAfter(selectedTreeNode) != null) { + nextSelectTreeNode = (ExpandMutableTreeNode) parentTreeNode.getChildAfter(selectedTreeNode); + } else if (parentTreeNode.getChildBefore(selectedTreeNode) != null) { + nextSelectTreeNode = (ExpandMutableTreeNode) parentTreeNode.getChildBefore(selectedTreeNode); + } else { + nextSelectTreeNode = parentTreeNode; + } + + parentTreeNode.remove(selectedTreeNode); + + if (!ComparatorUtils.equals(nextSelectTreeNode, treeModel.getRoot())) { + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(nextSelectTreeNode)); + } + treeModel.reload(parentTreeNode); + parentTreeNode.expandCurrentTreeNode(conditionsTree); + if (!ComparatorUtils.equals(nextSelectTreeNode, treeModel.getRoot())) { + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(nextSelectTreeNode)); + } + } + + // peter:检查Button Enabled. + checkButtonEnabledForList(); + } + } + }; + + + private ActionListener actionListener4 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + if (selectedTreePath == null) { + return; + } + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + if (parentTreeNode.getChildBefore(selectedTreeNode) != null) { + swapNodesOfConditionTree(parentTreeNode, (ExpandMutableTreeNode) parentTreeNode.getChildBefore(selectedTreeNode), + selectedTreeNode, MOVE_UP); + } + } + }; + + + private ActionListener actionListener5 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + if (selectedTreePath == null) { + return; + } + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + if (parentTreeNode.getChildAfter(selectedTreeNode) != null) { + swapNodesOfConditionTree(parentTreeNode, selectedTreeNode, (ExpandMutableTreeNode) parentTreeNode.getChildAfter(selectedTreeNode), MOVE_DOWN); + } + } + }; + + + private ActionListener actionListener6 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + TreePath[] selectedTreePaths = conditionsTree.getSelectionPaths(); + // peter:当前的节点 + if (selectedTreePaths == null || selectedTreePaths.length <= 1) { + return; + } + + // peter: 找到父亲节点,并且删除所有的节点. + TreePath topTreePath = GUICoreUtils.getTopTreePath(conditionsTree, selectedTreePaths); + ExpandMutableTreeNode leadTreeNode = (ExpandMutableTreeNode) topTreePath.getLastPathComponent(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) leadTreeNode.getParent(); + int topIndex = parentTreeNode.getIndex(leadTreeNode); + + JoinCondition firstJionCondition = (JoinCondition) leadTreeNode.getUserObject(); + for (int i = 0; i < selectedTreePaths.length; i++) { + ExpandMutableTreeNode tmpTreeNode = (ExpandMutableTreeNode) selectedTreePaths[i].getLastPathComponent(); + parentTreeNode.remove(tmpTreeNode); + } + + // peter:建立新的节点. + JoinCondition newJionCondition = new JoinCondition(); + newJionCondition.setJoin(firstJionCondition.getJoin()); + newJionCondition.setCondition(new ListCondition()); + ExpandMutableTreeNode newTreeNode = new ExpandMutableTreeNode(newJionCondition); + for (int i = 0; i < selectedTreePaths.length; i++) { + ExpandMutableTreeNode tmpTreeNode = (ExpandMutableTreeNode) selectedTreePaths[i].getLastPathComponent(); + newTreeNode.add(tmpTreeNode); + } + + // peter:添加新的节点 + parentTreeNode.insert(newTreeNode, topIndex); + + // peter:需要reload + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) conditionsTree.getModel(); + defaultTreeModel.reload(parentTreeNode); + parentTreeNode.expandCurrentTreeNode(conditionsTree); + + // peter:选择一个节点 + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(newTreeNode)); + } + }; + + + ActionListener actionListener7 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + // peter:当前的节点 + if (selectedTreePath == null) { + return; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + JoinCondition joinCondition = (JoinCondition) selectedTreeNode.getUserObject(); + Condition liteCondition = joinCondition.getCondition(); + if (liteCondition instanceof ListCondition) { + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + int index = parentTreeNode.getIndex(selectedTreeNode); + + // peter:添加节点 + List treePathList = new ArrayList(); + for (int i = selectedTreeNode.getChildCount() - 1; i >= 0; i--) { + ExpandMutableTreeNode tmpTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getChildAt(i); + parentTreeNode.insert(tmpTreeNode, index); + treePathList.add(GUICoreUtils.getTreePath(tmpTreeNode)); + } + + // peter;删除这个List节点 + parentTreeNode.remove(selectedTreeNode); + + // peter:需要reload + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) conditionsTree.getModel(); + defaultTreeModel.reload(parentTreeNode); + parentTreeNode.expandCurrentTreeNode(conditionsTree); + + // peter:选择所有选择的节点 + TreePath[] selectedTreePaths = new TreePath[treePathList.size()]; + treePathList.toArray(selectedTreePaths); + conditionsTree.setSelectionPaths(selectedTreePaths); + } + } + }; + + + private ActionListener actionListener8 = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + modify(); + } + }; + + + // 图表条件高亮时没有公式选择 + protected JPanel conditonTypePane; + + public LiteConditionPane() { + this.initComponents(); + } + + protected abstract BasicBeanPane createUnFormulaConditionPane(); + + protected abstract VariableResolver variableResolver4FormulaPane(); + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + // north + initNorth(); + + //center + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(centerPane, BorderLayout.CENTER); + centerPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + + // Control + JPanel controlPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + centerPane.add(controlPane, BorderLayout.NORTH); + // controlPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + + // conditionCardPane + initConditionCardPane(controlPane); + + // addControlPane, contains or,and Radio, add,modify Button + initControlPane(controlPane); + + // Preview + JPanel previewPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + centerPane.add(previewPane, BorderLayout.CENTER); + previewPane.setBorder(BorderFactory.createEmptyBorder(0, 2, 2, 0)); + + + // conTreeScrollPane.setPreferredSize(new Dimension(400, 125)); + previewPane.add(iniTreeScrollPane(), BorderLayout.CENTER); + conditionsTree.addTreeSelectionListener(treeSelectionListener); + + JPanel buttonPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(1); + previewPane.add(GUICoreUtils.createBorderPane(buttonPane, BorderLayout.NORTH), BorderLayout.EAST); + initButtonPane(buttonPane); + + // peter:必须要检查Enabled. + checkButtonEnabledForList(); + } + + + private void initButtonPane(JPanel buttonPane) { + removeButton = new UIButton(Inter.getLocText("FR-Designer_Remove")); + buttonPane.add(removeButton); + removeButton.setIcon(BaseUtils.readIcon("com/fr/base/images/cell/control/remove.png")); + removeButton.setEnabled(false); + removeButton.addActionListener(actionListener3); + + moveUpButton = new UIButton(Inter.getLocText("Utils-Move_Up")); + buttonPane.add(moveUpButton); + moveUpButton.setIcon(BaseUtils.readIcon("com/fr/design/images/control/up.png")); + moveUpButton.addActionListener(actionListener4); + + moveDownButton = new UIButton(Inter.getLocText("Utils-Move_Down")); + buttonPane.add(moveDownButton); + moveDownButton.setIcon(BaseUtils.readIcon("com/fr/design/images/control/down.png")); + moveDownButton.addActionListener(actionListener5); + + // peter:加括号 + bracketButton = new UIButton(Inter.getLocText("ConditionB-Add_bracket")); + buttonPane.add(bracketButton); + bracketButton.setIcon(BaseUtils.readIcon("com/fr/design/images/condition/bracket.png")); + bracketButton.addActionListener(actionListener6); + + // peter:去掉括号 + unBracketButton = new UIButton(Inter.getLocText("ConditionB-Remove_bracket")); + buttonPane.add(unBracketButton); + unBracketButton.setIcon(BaseUtils.readIcon("com/fr/design/images/condition/unBracket.png")); + unBracketButton.addActionListener(actionListener7); + } + + private JScrollPane iniTreeScrollPane() { + conditionsTree = new JTree(new DefaultTreeModel(new ExpandMutableTreeNode(new JoinCondition(DataConstants.AND, new ListCondition())))); + conditionsTree.setRootVisible(false); + conditionsTree.setCellRenderer(conditionsTreeCellRenderer); + conditionsTree.setSelectionModel(new ContinuousTreeSelectionModel()); + conditionsTree.addTreeExpansionListener(treeExpansionListener); + conditionsTree.setShowsRootHandles(true); + return new JScrollPane(conditionsTree); + + } + + private void initNorth() { + conditonTypePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(conditonTypePane, BorderLayout.NORTH); + conditonTypePane.setBorder(new ModLineBorder(ModLineBorder.BOTTOM)); + + UILabel conditionTypeLabel = new UILabel(Inter.getLocText("FR-Designer_Type") + ":"); + conditonTypePane.add(conditionTypeLabel, BorderLayout.WEST); + conditionTypeLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); + + JPanel northPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2); + conditonTypePane.add(northPane, BorderLayout.CENTER); + northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0)); + northPane.add(GUICoreUtils.createFlowPane(commonRadioButton, FlowLayout.CENTER)); + northPane.add(GUICoreUtils.createFlowPane(formulaRadioButton, FlowLayout.CENTER)); + commonRadioButton.addActionListener(radioActionListener); + formulaRadioButton.addActionListener(radioActionListener); + + ButtonGroup mainBg = new ButtonGroup(); + mainBg.add(commonRadioButton); + mainBg.add(formulaRadioButton); + commonRadioButton.setSelected(true); + } + + private void initConditionCardPane(JPanel controlPane) { + conditionCardPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + controlPane.add(conditionCardPane, BorderLayout.CENTER); + conditionCardPane.setLayout(new CardLayout()); + conditionCardPane.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0)); + + // defaultConditionPane + conditionCardPane.add(defaultConditionPane = createUnFormulaConditionPane(), "DEFAULT"); + + // formulaConditionPane + JPanel formulaConditionPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + conditionCardPane.add(formulaConditionPane, "FORMULA"); + // formulaConditionPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + + // formulaPane + JPanel formulaPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + formulaConditionPane.add(formulaPane, BorderLayout.CENTER); + formulaPane.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 2)); + formulaPane.add(GUICoreUtils.createBorderPane(new UILabel(Inter.getLocText("FR-Designer_LiteCondition_Formula") + "="), BorderLayout.NORTH), BorderLayout.WEST); + formulaTextArea = new UITextArea(); + formulaPane.add(new JScrollPane(formulaTextArea), BorderLayout.CENTER); + UIButton editFormulaButton = new UIButton(Inter.getLocText("FR-Designer_LiteCondition_Define")); + formulaPane.add(GUICoreUtils.createBorderPane(editFormulaButton, BorderLayout.NORTH), BorderLayout.EAST); + editFormulaButton.addActionListener(actionListener1); + applyCardsPane(); + } + + + private void initControlPane(JPanel controlPane) { + JPanel addControlPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + controlPane.add(addControlPane, BorderLayout.SOUTH); + addControlPane.setBorder(new ModLineBorder(ModLineBorder.TOP)); + + ButtonGroup bg = new ButtonGroup(); + bg.add(andRadioButton); + bg.add(orRadioButton); + + andRadioButton.setSelected(true); + + JPanel radioPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(3); + addControlPane.add(radioPane); + radioPane.add(andRadioButton); + addControlPane.add(Box.createHorizontalStrut(4)); + radioPane.add(orRadioButton); + + addControlPane.add(Box.createHorizontalStrut(12)); + + addButton = new UIButton(Inter.getLocText("FR-Designer_Add"), BaseUtils.readIcon("com/fr/base/images/cell/control/add.png")); + addButton.setMnemonic('A'); + addControlPane.add(addButton); + addButton.addActionListener(actionListener2); + + addControlPane.add(Box.createHorizontalStrut(4)); + + modifyButton = new UIButton(Inter.getLocText("FR-Designer_Modify"), BaseUtils.readIcon("com/fr/base/images/cell/control/rename.png")); + modifyButton.setMnemonic('M'); + addControlPane.add(modifyButton); + modifyButton.addActionListener(actionListener8); + + // peter:当鼠标进入修改按钮的时候,如果是ListConditon内容编辑区域不可编辑 + modifyButton.addMouseListener(mouseAdapter); + } + + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer-Submit_Condition"); + } + + // samuel:移出来,方便调用 + protected void modify() { + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + // peter:当前的节点 + if (selectedTreePath != null) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + JoinCondition oldJoinCondition = (JoinCondition) selectedTreeNode.getUserObject(); + oldJoinCondition.setJoin(andRadioButton.isSelected() ? DataConstants.AND : DataConstants.OR); + + Condition oldLiteCondition = oldJoinCondition.getCondition(); + // peter:如果当前选中的是ListCondition,只要改变Join为AND或者OR,直接返回. + if (oldLiteCondition != null && !(oldLiteCondition instanceof ListCondition)) { + // peter:先获得当前的LiteCondition. + Condition liteCondition; + if (commonRadioButton.isSelected()) { + liteCondition = defaultConditionPane.updateBean(); + } else { + liteCondition = new FormulaCondition(formulaTextArea.getText()); + } + + oldJoinCondition.setCondition(liteCondition); + } + + // peter:需要reload parent + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) conditionsTree.getModel(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + defaultTreeModel.reload(parentTreeNode); + parentTreeNode.expandCurrentTreeNode(conditionsTree); + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(selectedTreeNode)); + } + } + + protected void swapNodesOfConditionTree(ExpandMutableTreeNode parentTreeNode, ExpandMutableTreeNode firstSelectTreeNode, + ExpandMutableTreeNode secondTreeNode, int type) { + int nextIndex = parentTreeNode.getIndex(firstSelectTreeNode); + parentTreeNode.remove(firstSelectTreeNode); + parentTreeNode.remove(secondTreeNode); + + parentTreeNode.insert(firstSelectTreeNode, nextIndex); + parentTreeNode.insert(secondTreeNode, nextIndex); + + DefaultTreeModel treeModel = (DefaultTreeModel) conditionsTree.getModel(); + treeModel.reload(parentTreeNode); + + parentTreeNode.expandCurrentTreeNode(conditionsTree); + if (type == MOVE_UP) { + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(secondTreeNode)); + } else if (type == MOVE_DOWN) { + conditionsTree.setSelectionPath(GUICoreUtils.getTreePath(firstSelectTreeNode)); + } + + + // peter:检查Button Enabled. + checkButtonEnabledForList(); + } + + + ActionListener radioActionListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent evt) { + applyCardsPane(); + } + }; + + private void applyCardsPane() { + CardLayout cl = (CardLayout) (conditionCardPane.getLayout()); + if (this.commonRadioButton.isSelected()) { + this.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer_LiteCondition_Common_Condition"), null)); + cl.show(conditionCardPane, "DEFAULT"); + } else { + this.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer_LiteCondition_Formula_Condition"), null)); + cl.show(conditionCardPane, "FORMULA"); + } + } + + /** + * peter:检查Button是否可以编辑. + */ + private void checkButtonEnabledForList() { + modifyButton.setEnabled(false); + removeButton.setEnabled(false); + this.moveUpButton.setEnabled(false); + this.moveDownButton.setEnabled(false); + this.bracketButton.setEnabled(false); + this.unBracketButton.setEnabled(false); + + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + if (selectedTreePath != null) { + modifyButton.setEnabled(true); + removeButton.setEnabled(true); + + // peter:根据选中的节点的是否是第一个或者最后一个. + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + DefaultMutableTreeNode parentTreeNode = (DefaultMutableTreeNode) selectedTreeNode.getParent(); + if (parentTreeNode.getChildBefore(selectedTreeNode) != null) { + moveUpButton.setEnabled(true); + } + if (parentTreeNode.getChildAfter(selectedTreeNode) != null) { + moveDownButton.setEnabled(true); + } + + // peter: 连续选中了超过两个条件,同时没有选中所有的节点. + int selectionCount = conditionsTree.getSelectionCount(); + if (selectionCount > 1 && parentTreeNode.getChildCount() > selectionCount) { + this.bracketButton.setEnabled(true); + } + + // peter:选中的节点必须是ListCondition,才可以删除括号 + JoinCondition jonCondition = (JoinCondition) selectedTreeNode.getUserObject(); + Condition liteCondtion = jonCondition.getCondition(); + if (liteCondtion instanceof ListCondition) { + this.unBracketButton.setEnabled(true); + } + } + } + + /** + * 扩展事件. + */ + TreeExpansionListener treeExpansionListener = new TreeExpansionListener() { + + @Override + public void treeExpanded(TreeExpansionEvent event) { + TreePath selectedTreePath = event.getPath(); + if (selectedTreePath == null) { + return; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + selectedTreeNode.setExpanded(true); + } + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + TreePath selectedTreePath = event.getPath(); + if (selectedTreePath == null) { + return; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + selectedTreeNode.setExpanded(false); + } + }; + + private ExpandMutableTreeNode getParentTreeNode() { + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) conditionsTree.getModel(); + TreePath selectedTreePath = conditionsTree.getSelectionPath(); + // peter:如果没有选择的节点,直接添加到根节点. + ExpandMutableTreeNode parentTreeNode; + if (selectedTreePath == null) { + parentTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); + } else { + parentTreeNode = (ExpandMutableTreeNode) ((ExpandMutableTreeNode) selectedTreePath.getLastPathComponent()).getParent(); + } + // peter:如果没有选中的节点,直接返回. + return parentTreeNode; + } + + private boolean isExistedInParentTreeNode(ExpandMutableTreeNode parentTreeNode, JoinCondition newJoinCondition) { + + if (parentTreeNode == null) { + return false; + } + JoinCondition parentJoinCondition = (JoinCondition) parentTreeNode.getUserObject(); + Condition parentLiteCondition = parentJoinCondition.getCondition(); + if (parentLiteCondition instanceof ListCondition) { + // peter:在添加UserObject的节点. + + for (int i = 0; i < parentTreeNode.getChildCount(); i++) { + ExpandMutableTreeNode tempTreeNode = (ExpandMutableTreeNode) parentTreeNode.getChildAt(i); + Object tempObject = tempTreeNode.getUserObject(); + if (tempObject instanceof JoinCondition) { + JoinCondition tempJoinCondition = (JoinCondition) tempObject; + if (ComparatorUtils.equals(tempJoinCondition, newJoinCondition)) { + return true; + } + } + } + } + return false; + } + + private DefaultTreeCellRenderer conditionsTreeCellRenderer = new DefaultTreeCellRenderer() { + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + + DefaultMutableTreeNode currentTreeNode = (DefaultMutableTreeNode) value; + adjustParentListCondition(currentTreeNode); + DefaultMutableTreeNode parentTreeNode = (DefaultMutableTreeNode) currentTreeNode.getParent(); + + this.setIcon(null); + JoinCondition joinCondition = (JoinCondition) currentTreeNode.getUserObject(); + StringBuilder sBuf = new StringBuilder(); + + Condition liteCondition = joinCondition.getCondition(); + if (parentTreeNode != null && parentTreeNode.getFirstChild() != currentTreeNode) { + if (joinCondition.getJoin() == DataConstants.AND) { + sBuf.append("and "); + } else { + sBuf.append("or "); + } + } + + if (liteCondition != null) { + // TODO alex:这里得到的liteCondition为什么会是null呢? + sBuf.append(liteCondition.toString()); + } + this.setText(sBuf.toString()); + + return this; + } + }; + + // peter:根据孩子几点,调整当前节点的ListCondition的值. + protected void adjustParentListCondition(DefaultMutableTreeNode currentTreeNode) { + DefaultMutableTreeNode parentTreeNode = (DefaultMutableTreeNode) currentTreeNode.getParent(); + + Object userObj = currentTreeNode.getUserObject(); + if (userObj instanceof JoinCondition) { + StringBuilder sBuf = new StringBuilder(); + + JoinCondition joinCondition = (JoinCondition) userObj; + Condition liteCondition = joinCondition.getCondition(); + if (parentTreeNode != null && parentTreeNode.getFirstChild() != currentTreeNode) { + if (joinCondition.getJoin() == DataConstants.AND) { + sBuf.append("and "); + } else { + sBuf.append("or "); + } + } + + // peter:这个地方动态产生ListCondition,因为ListCondition的节点会变化的, + // 父亲节点的ListCondition这个UserObject需要跟着变化. + if (liteCondition instanceof ListCondition) { + ListCondition listCondition = (ListCondition) liteCondition; + listCondition.clearJoinConditions(); + + // peter:动态添加孩子节点 + int childCount = currentTreeNode.getChildCount(); + for (int i = 0; i < childCount; i++) { + Object tmpUserObject = ((DefaultMutableTreeNode) currentTreeNode.getChildAt(i)).getUserObject(); + if (tmpUserObject instanceof JoinCondition) { + listCondition.addJoinCondition((JoinCondition) tmpUserObject); + } + } + } + } + } + + /** + * Sets whether or not this component is enabled. + */ + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + // checkenabled. + checkButtonEnabledForList(); + } + + /** + * Populate. + * + * @param liteCondition lite condition. + */ + @Override + public void populateBean(Condition liteCondition) { + if(liteCondition == null){ + return; + } + // peter: 先删除所有的节点 + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) this.conditionsTree.getModel(); + ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); + rootTreeNode.setUserObject(new JoinCondition(DataConstants.AND, new ListCondition())); + rootTreeNode.removeAllChildren(); + + // peter:需要构建成ListCondition,加入到里面. + if (liteCondition instanceof ListCondition) { + ListCondition listCondition = (ListCondition) liteCondition; + + int joinConditionCount = listCondition.getJoinConditionCount(); + if (joinConditionCount == 0) { + commonRadioButton.setSelected(true); + applyCardsPane(); + + } + for (int i = 0; i < joinConditionCount; i++) { + addLiteConditionToListCondition(rootTreeNode, listCondition.getJoinCondition(i)); + } + } else if (needDoWithCondition(liteCondition)) { + // peter:直接添加 + ExpandMutableTreeNode newTreeNode = new ExpandMutableTreeNode(new JoinCondition(DataConstants.AND, liteCondition)); + rootTreeNode.add(newTreeNode); + } + + // peter:需要reload + defaultTreeModel.reload(rootTreeNode); + rootTreeNode.expandCurrentTreeNode(conditionsTree); + // marks:默认的选择第一行 + if (conditionsTree.getRowCount() > 0) { + conditionsTree.setSelectionRow(0); + } + this.checkButtonEnabledForList(); + if (liteCondition == null) { + try { + defaultConditionPane.checkValid(); + } catch (Exception e) {//not need + } + } + } + + protected boolean needDoWithCondition(Condition liteCondition) { + return true; + } + + // peter:运用递归方式,构建初始的节点 + private void addLiteConditionToListCondition(ExpandMutableTreeNode parentTreeNode, JoinCondition joinCondition) { + ExpandMutableTreeNode newTreeNode = new ExpandMutableTreeNode(joinCondition); + parentTreeNode.add(newTreeNode); + + // peter:继续添加. + Condition liteCondition = joinCondition.getCondition(); + if (liteCondition instanceof ListCondition) { + ListCondition listCondition = (ListCondition) liteCondition; + + int joinConditionCount = listCondition.getJoinConditionCount(); + for (int i = 0; i < joinConditionCount; i++) { + addLiteConditionToListCondition(newTreeNode, listCondition.getJoinCondition(i)); + } + } + } + + + /** + * Update. + * + * @return the new lite condition. + */ + @Override + public Condition updateBean() { + // Samuel:先按modifybutton + modify(); + // peter: 先删除所有的节点 + DefaultTreeModel defaultTreeModel = (DefaultTreeModel) this.conditionsTree.getModel(); + ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); + + int childCount = rootTreeNode.getChildCount(); + // peter: 如果只有一个孩子节点, 返回空的 ListCondition + if (childCount == 0) { + return new ListCondition(); + } // peter: 如果roottreeNode只有一个孩子节点. + else if (childCount == 1) { + JoinCondition joinCondition = (JoinCondition) ((ExpandMutableTreeNode) rootTreeNode.getChildAt(0)).getUserObject(); + return joinCondition.getCondition(); + } // peter: 有好多的孩子节点. + else { + // peter:深度遍历所有的孩子节点 + Enumeration depthEnumeration = rootTreeNode.depthFirstEnumeration(); + while (depthEnumeration.hasMoreElements()) { + this.adjustParentListCondition((ExpandMutableTreeNode) depthEnumeration.nextElement()); + } + + JoinCondition joinCondition = (JoinCondition) rootTreeNode.getUserObject(); + Condition newCondition = joinCondition.getCondition(); + //clone(),防止多个条件分组使用同一个condition对象 + try{ + newCondition = (Condition)joinCondition.getCondition().clone(); + }catch (CloneNotSupportedException e){ + FRLogger.getLogger().error(e.getMessage()); + } + return newCondition; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/ObjectLiteConditionPane.java b/designer_base/src/com/fr/design/condition/ObjectLiteConditionPane.java new file mode 100644 index 0000000000..2ba959840b --- /dev/null +++ b/designer_base/src/com/fr/design/condition/ObjectLiteConditionPane.java @@ -0,0 +1,103 @@ +package com.fr.design.condition; + +import java.awt.BorderLayout; +import java.awt.Component; + +import javax.swing.DefaultComboBoxModel; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JList; +import javax.swing.JPanel; + +import com.fr.data.condition.ObjectCondition; +import com.fr.data.core.Compare; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.formula.VariableResolver; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.general.Inter; + +public class ObjectLiteConditionPane extends LiteConditionPane { + + @Override + protected BasicBeanPane createUnFormulaConditionPane() { + return new ObjectConditionPane(); + } + + @Override + protected VariableResolver variableResolver4FormulaPane() { + return VariableResolver.DEFAULT; + } + + private class ObjectConditionPane extends BasicBeanPane { + + private UIComboBox conditionOPComboBox; + private ValueEditorPane conditionValuePane; + + ObjectConditionPane() { + this.initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + // condition operation + conditionOPComboBox = new UIComboBox(); + DefaultComboBoxModel opComboBoxModel = (DefaultComboBoxModel) conditionOPComboBox.getModel(); + int[] allOperators = Compare.getAllOperators(); + for (int i = 0; i < allOperators.length; i++) { + opComboBoxModel.addElement(new Integer(allOperators[i])); + } + // conditionOPComboBox.setPreferredSize(new Dimension(120, 25)); + + this.conditionOPComboBox.setRenderer(new UIComboBoxRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof Integer) { + this.setText(Compare.operator2String(((Integer) value).intValue())); + } + + return this; + } + }); + + conditionValuePane = ValueEditorPaneFactory.createAllValueEditorPane(); + + Component[][] components = { { new UILabel(Inter.getLocText("ConditionB-Operator") + ":"), new UILabel() }, + { conditionOPComboBox, conditionValuePane } }; + + double p = TableLayout.PREFERRED; + double rowSize[] = { p, p }; + double columnSize[] = { p, TableLayout.FILL }; + + JPanel leftPanel = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); + this.add(leftPanel, BorderLayout.CENTER); + } + + @Override + public ObjectCondition updateBean() { + Object value = conditionValuePane.update(); + + return new ObjectCondition(new Compare(((Integer) conditionOPComboBox.getSelectedItem()).intValue(), value)); + } + + @Override + public void populateBean(ObjectCondition condition) { + + Compare compare = condition.getCompare(); + conditionOPComboBox.setSelectedItem(new Integer(compare.getOp())); + + this.conditionValuePane.populate(compare.getValue()); + } + + @Override + protected String title4PopupWindow() { + return " "; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/condition/SingleConditionPane.java b/designer_base/src/com/fr/design/condition/SingleConditionPane.java new file mode 100644 index 0000000000..e5a8758499 --- /dev/null +++ b/designer_base/src/com/fr/design/condition/SingleConditionPane.java @@ -0,0 +1,54 @@ +package com.fr.design.condition; + + +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; + +public abstract class SingleConditionPane extends BasicPane { + private static final long serialVersionUID = -4274960170813368817L; + + protected UIButton cancel; + + public SingleConditionPane(){ + this(true); + } + + public SingleConditionPane(boolean isRemove) { + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + if (isRemove) { + + if(cancel == null) { + cancel = new UIButton(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + cancel.setToolTipText(Inter.getLocText("FR-Action_Remove")); + cancel.addActionListener(cancleListener); + cancel.setMargin(new Insets(0, 0, 0, 0)); + } + + this.add(cancel); + } + } + + ActionListener cancleListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doCancel(); + } + }; + + /** + * 取消 + */ + public abstract void doCancel(); + + public abstract void setDefault(); + + public abstract void populate(T condition); + + public abstract T update(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/constants/KeyWords.java b/designer_base/src/com/fr/design/constants/KeyWords.java new file mode 100644 index 0000000000..e4af629709 --- /dev/null +++ b/designer_base/src/com/fr/design/constants/KeyWords.java @@ -0,0 +1,206 @@ +package com.fr.design.constants; + +/** + * Created with IntelliJ IDEA. + * User: richie + * Date: 13-11-13 + * Time: 下午6:50 + */ +public class KeyWords { + private KeyWords() { + + } + + +/* parameterEl :object + 返回对象参数界面 + 例如: + contentPane.parameterEl + currentPageIndex + curLGP + reportTotalPage + zoom +*/ + public static final String[] JAVASCRIPT = new String[]{ + // normal js + "Array", + "attr", + "break", + "case", + "catch", + "children", + "close", + "concat", + "continue", + "default", + "delete", + "do", + "document", + "else", + "event", + "finally", + "fireEvent", + "for", + "function", + "getElementById", + "getText", + "html", + "if", + "in", + "instanceof", + "length", + "location", + "new", + "open", + "parent", + "parseFloat", + "parseInt", + "replace", + "return", + "search", + "setInterval", + "split", + "substr", + "switch", + "this", + "throw", + "tostring", + "try", + "typeof", + "var", + "void", + "while", + "window", + + // contentPane + "cellselect", + "contentPane", + "curLGP", + "currentPageIndex", + "lgps", + "options", + "parameterEl", + "reportTotalPage", + "selectedIndex", //当前选中的sheet号 + "zoom", + + "appendReportRC()", + "appletPrint()", + "deleteReportRC()", + "deleteRows()", + "emailReport()", + "exportReportToExcel(mode)", + "exportReportToImage(pattern)", + "exportReportToPDF(ori)", + "exportReportToWord()", + "flashPrint()", + "getCellValue(reportIndex, columnIndex, rowIndex)", + "getWidgetByCell(cell)", + "getWidgetByName(name)", + "getWidgetsByName(name)", + "gotoFirstPage()", + "gotoLastPage()", + "gotoNextPage()", + "gotoPage(n)", + "gotoPreviousPage()", + "importExcelData()", + "makeHighlight(color, op)", + "on()", + "pageSetup()", + "parameterCommit()", + "pdfPrint()", + "printPreview()", + "scale()", + "setCellValue([reportIndex], columnIndex, rowIndex, cv)", + "stopEditing()", + "verifyAndWriteReport(true)", //空或false为提交所有sheet,true为提交当前sheet + "verifyReport()", + "writeReportIgnoreVerify(true)", + "writeReport(index)", + + // curLGP + "currentTDCell", + "dirtyCell", + "write", + "form", + + "cut2ColumnRowString(td)", + "displayTDCell(tdCell, cv, presentValue)", + "getColumnWidth(i)", + "getRowHeight(i)", + "getTDCell()", + "getTDCol(td)", + "getTDRow(td)", + "getWidgetCell(widget)", + "resetCellValue(widget)", + "stopCellEditing()", + + // parameterEl + //getWidgetByName + "name_widgets", + + // widget + //"fireEvent", + "getValue()", + "isEnabled()", + "isVisible()", + "reset()", + "setValue(value)", + "setEnable()", + "setVisible()", + + // other + "${servletURL}?reportlet=" + + }; + + public static final String[][] JAVASCRIPT_SHORT = new String[][]{ + /* + * FR.Msg + */ + new String[]{"alert", "FR.Msg.alert(title, message, callback)"}, + new String[]{"confirm", "FR.Msg.confirm(title, message, callback)"}, + new String[]{"prompt", "FR.Msg.prompt(title, message, value, callback)"}, + new String[]{"toast", "FR.Msg.toast(message)"}, + + /* + * FR + */ + new String[]{"ajax","FR.ajax(o)"}, + new String[]{"cellStr2ColumnRow","FR.cellStr2ColumnRow(name)"}, + new String[]{"chart_Change_Parameter","FR.Chart.WebUtils.chart_Change_Parameter(pos, id, para)"}, + new String[]{"chart_Refresh()","FR.Chart.WebUtils.chart_Refresh(str)"}, + new String[]{"cjkDecode","FR.cjkDecode(str)"}, + new String[]{"cjkEncode","FR.cjkEncode(str)"}, + new String[]{"closeDialog","FR.closeDialog()"}, + new String[]{"columnRow2CellStr","FR.columnRow2CellStr(cr)"}, + new String[]{"destroyDialog","FR.destroyDialog()"}, + new String[]{"digit2Letter","FR.digit2Letter(k)"}, + new String[]{"doAppletPrint", "FR.doAppletPrint(sessionID)"}, + new String[]{"doFlashPrint", "FR.doFlashPrint(sessionID, currentPageIndex)"}, + new String[]{"doHyperlinkByGet","FR.doHyperlinkByGet(url, para, target, feature)"}, + new String[]{"doHyperlinkByPost","FR.doHyperlinkByPost(url, para, target, feature)"}, + new String[]{"doHyperlinkByGet4Reportlet","FR.doHyperlinkByGet4Reportlet(url,para,target,featrue)"}, + new String[]{"doPDFPrint", "FR.doPDFPrint(sessionID, popupSetup)"}, + new String[]{"doURLAppletPrint","FR.doURLAppletPrint(printurl,isPopUp,config)"}, + new String[]{"doURLFlashPrint","FR.doURLFlashPrint(printurl,isPopUp,config)"}, + new String[]{"doURLPDFPrint","FR.doURLPDFPrint(printurl,isPopUp,config)"}, + new String[]{"htmlDecode","FR.htmlDecode(text)"}, + new String[]{"htmlEncode","FR.htmlEncode(text)"}, + new String[]{"id2ColumnRow","FR.id2ColumnRow(id)"}, + new String[]{"id2ColumnRowStr","FR.id2ColumnRowStr(id)"}, + new String[]{"id2Location","FR.id2Location(id)"}, + new String[]{"isEmptyArray","FR.isEmptyArray(array)"}, + new String[]{"letter2Digit","FR.letter2Digit(abc)"}, + new String[]{"showDialog","FR.showDialog(title, width, height, innerContent)"}, + new String[]{"showIframeDialog","FR.showIframeDialog(o)"}, + new String[]{"showHyperlinkDialog","FR.showHyperlinkDialog(url,featur)"}, + + /* + * FS + */ + new String[]{"signOut","FS.Trans.signOut()"}, + new String[]{"closeActiveTab","FS.tabPane.closeActiveTab()"}, + new String[]{"addItem","FS.tabPane.addItem(o)"} + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/constants/LayoutConstants.java b/designer_base/src/com/fr/design/constants/LayoutConstants.java new file mode 100644 index 0000000000..2ff1ac72b3 --- /dev/null +++ b/designer_base/src/com/fr/design/constants/LayoutConstants.java @@ -0,0 +1 @@ +package com.fr.design.constants; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 12-12-27 * Time: 下午2:28 * 所有的间隙常数都从这里取,注意写上PMD检测规则来检查 */ public class LayoutConstants { private LayoutConstants() { } /** * 水平间隙 */ public static final int HGAP_SMALL = 1; /** * 水平间隙 */ public static final int HGAP_LARGE = 4; /** * 垂直间隙 */ public static final int VGAP_SMALL = 4; /** * 垂直间隙 */ public static final int VGAP_MEDIUM = 6; /** * 垂直间隙 */ public static final int VGAP_LARGE = 10; /** * 图表属性表中二级菜单距离右边框的距离 */ public static final int CHART_ATTR_TOMARGIN = 46; } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/constants/UIConstants.java b/designer_base/src/com/fr/design/constants/UIConstants.java new file mode 100644 index 0000000000..c63dcdea79 --- /dev/null +++ b/designer_base/src/com/fr/design/constants/UIConstants.java @@ -0,0 +1,172 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.constants; + +import com.fr.base.BaseUtils; +import com.fr.general.Inter; +import com.fr.stable.Constants; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; + +/** + * This class defines the constants used in the designer. + */ +public interface UIConstants { + + + public static final Icon BLACK_ICON = BaseUtils.readIcon("/com/fr/base/images/cell/blank.gif"); + + + public static final int SIZE = 17; + + /** + * Cell default cursor. + */ + public static final Cursor CELL_DEFAULT_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor( + BaseUtils.readImage("/com/fr/base/images/cell/cursor/cell_default.png"), + new Point(16, 16), "CellDefaultCursor"); + public static final Cursor DRAW_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor( + BaseUtils.readImage("/com/fr/base/images/cell/cursor/cursor_draw.png"), + new Point(16, 16), "DrawCursor"); + + + public static final Cursor FORMAT_BRUSH_CURSOR = Toolkit.getDefaultToolkit().createCustomCursor( + BaseUtils.readImage("/com/fr/base/images/cell/cursor/brush_cursor0.png"), + new Point(16, 16), "formatBrushCursor"); + + /** + * Border style array. + */ + public final static int[] BORDER_LINE_STYLE_ARRAY = new int[]{ + Constants.LINE_THIN, //Thin border. + Constants.LINE_MEDIUM, //Medium border + Constants.LINE_DASH, //dash border + Constants.LINE_HAIR, //hair-line border + Constants.LINE_HAIR2, //hair-line border + Constants.LINE_THICK, //Thick border + Constants.LINE_DOUBLE, //double-line border + Constants.LINE_DOT, //dot border + Constants.LINE_MEDIUM_DASH, //Medium dashed border + Constants.LINE_DASH_DOT, //dash-dot border + Constants.LINE_MEDIUM_DASH_DOT, //medium dash-dot border + Constants.LINE_DASH_DOT_DOT, //dash-dot-dot border + Constants.LINE_MEDIUM_DASH_DOT_DOT, //medium dash-dot-dot border + Constants.LINE_SLANTED_DASH_DOT, //slanted dash-dot border + }; + public static final Color LINE_COLOR = new Color(153, 153, 153); + public static final Color FONT_COLOR = new Color(51, 51, 51); + public static final Color LIGHT_BLUE = new Color(182, 217, 253); + public static final Color SKY_BLUE = new Color(164, 192, 220); + public static final Color OCEAN_BLUE = new Color(141, 179, 217); + public static final Color DARK_BLUE = new Color(0, 88, 144); + public static final Color NORMAL_BACKGROUND = new Color(240, 240, 240); + public static final Color SHADOW_GREY = new Color(0xe2e2e2); + public static final Color SHADOW_CENTER = new Color(200, 200, 200); + public static final Color SHADOW_PURPLE = new Color(255, 0, 255); + public static final Color FLESH_BLUE = new Color(168, 180, 202); + public static final Color HOVER_BLUE = new Color(0xd2d2d2); + public static final Color DOTTED_LINE_COLOR = new Color(35, 108, 184); + public static final Color AUTHORITY_COLOR = new Color(88, 125, 153); + public static final Color AUTHORITY_BLUE = new Color(0xe2e2e2); + public static final Color AUTHORITY_DARK_BLUE = new Color(136, 164, 186); + public static final Color AUTHORITY_PRESS_BLUE = new Color(131, 159, 181); + public static final Color AUTHORITY_LINE_COLOR = new Color(0, 124, 229); + public static final Color AUTHORITY_SHEET_DARK = new Color(86, 120, 143); + public static final Color AUTHORITY_SHEET_LIGHT = new Color(156, 204, 238); + public static final Color AUTHORITY_SHEET_UNSELECTED = new Color(146, 192, 225); + public static final Color ATTRIBUTE_PRESS = new Color(0xdfecfc); + public static final Color ATTRIBUTE_NORMAL = new Color(0xe2e2e2); + public static final Color ATTRIBUTE_HOVER = new Color(0xd3d3d3); + public static final Color CHECKBOX_HOVER_SELECTED = new Color(0x3394f0); + public static final Color TEXT_FILED_BORDER_SELECTED = new Color(0x3384f0); + public static final Color SHEET_NORMAL = new Color(0xc8c8ca); + public static final Color SELECTED_BACKGROUND = new Color(0xdeedfe); + public static final Color SELECTED_BORDER_LINE_COLOR = new Color(0x3384f0); + public static final Color DEFAULT_BG_RULER = new Color(0xf7f7f7); + public static final Color RULER_LINE_COLOR = new Color(0xababab); + public static final Color RULER_SCALE_COLOR = new Color(0x4e504f); + + + + public static final BufferedImage DRAG_BAR = BaseUtils.readImage("com/fr/design/images/control/bar.png"); + public static final BufferedImage DRAG_BAR_RIGHT = BaseUtils.readImage("com/fr/design/images/control/barm.png"); + public static final BufferedImage DRAG_BAR_LEFT = BaseUtils.readImage("com/fr/design/images/control/barl.png"); + public static final BufferedImage DRAG_UP_NORMAL = BaseUtils.readImage("com/fr/design/images/control/upnor.png"); + public static final BufferedImage DRAG_UP_PRESS = BaseUtils.readImage("com/fr/design/images/control/uppre.png"); + public static final BufferedImage DRAG_DOWN_NORMAL = BaseUtils.readImage("com/fr/design/images/control/downnor.png"); + public static final BufferedImage DRAG_DOWN_PRESS = BaseUtils.readImage("com/fr/design/images/control/downpre.png"); + public static final BufferedImage DRAG_RIGHT_NORMAL = BaseUtils.readImage("com/fr/design/images/control/rightnor.png"); + public static final BufferedImage DRAG_RIGHT_PRESS = BaseUtils.readImage("com/fr/design/images/control/rightpre.png"); + public static final BufferedImage DRAG_LEFT_NORMAL = BaseUtils.readImage("com/fr/design/images/control/leftnor.png"); + public static final BufferedImage DRAG_LEFT_PRESS = BaseUtils.readImage("com/fr/design/images/control/leftpre.png"); + public static final BufferedImage DRAG_DOT = BaseUtils.readImage("com/fr/design/images/control/dot.png"); + public static final BufferedImage DRAG_DOT_VERTICAL = BaseUtils.readImage("com/fr/design/images/control/dotv.png"); + public static final int MODEL_NORMAL = 0; + public static final int MODEL_PRESS = 1; + public static final Icon ARROW_DOWN_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/arrowdown.png"); + public static final Icon ARROW_UP_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/arrowup.png"); + public static final Icon YES_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/yes.png"); + public static final Icon CHOOSEN_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/select_item.png"); + public static final Icon PRE_WIDGET_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/prewidget.png"); + public static final Icon EDIT_NORMAL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/editn.png"); + public static final Icon EDIT_PRESSED_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/editp.png"); + public static final Icon HIDE_NORMAL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/hiden.png"); + public static final Icon HIDE_PRESSED_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/hidep.png"); + public static final Icon VIEW_NORMAL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/viewn.png"); + public static final Icon VIEW_PRESSED_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/viewp.png"); + public static final Icon RUN_BIG_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/run24.png"); + public static final Icon RUN_SMALL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/runs.png"); + public static final Icon PAGE_BIG_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/pageb24.png"); + public static final Icon WRITE_BIG_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/writeb24.png"); + public static final Icon ANA_BIG_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/anab24.png"); + public static final Icon PAGE_SMALL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/pages.png"); + public static final Icon WRITE_SMALL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/writes.png"); + public static final Icon ANA_SMALL_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/anas.png"); + public static final Icon REFRESH_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/refresh.png"); + public static final Icon FONT_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/color/foreground.png"); + public static final Icon HISTORY_ICON = BaseUtils.readIcon("com/fr/design/images/buttonicon/history.png"); + public static final Icon DELETE_ICON = BaseUtils.readIcon("com/fr/design/images/m_file/close.png"); + public static final Icon EDIT_ICON = BaseUtils.readIcon("com/fr/design/images/m_file/edit.png"); + public static final Icon SEARCH_ICON = BaseUtils.readIcon("/com/fr/design/images/data/search.png"); + public static final Icon CLEAR_ICON = BaseUtils.readIcon("/com/fr/design/images/data/source/delete.png"); + public static final Color PRESSED_DARK_GRAY = new Color(127, 127, 127); + public static final Color GRDIENT_DARK_GRAY = new Color(45, 45, 45); + public static final Color BARNOMAL = new Color(153, 153, 153); + public static final int ARC = 0; + public static final int LARGEARC = 0; + public static final Stroke BS = new BasicStroke(1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 2f, new float[]{3, 1}, 0); + public static final Icon PREVIEW_DOWN = BaseUtils.readIcon("com/fr/design/images/buttonicon/prevew_down_icon.png"); + public static final Icon CLOSE_OF_AUTHORITY = BaseUtils.readIcon("/com/fr/design/images/m_report/close.png"); + public static final Icon CLOSE_OVER_AUTHORITY = BaseUtils.readIcon("/com/fr/design/images/m_report/close_over.png"); + public static final Icon CLOSE_PRESS_AUTHORITY = BaseUtils.readIcon("/com/fr/design/images/m_report/close_press.png"); + public static final int CLOSE_AUTHORITY_HEIGHT_AND_WIDTH = 24; + + + /** + * 正在加载的界面 + */ + public static final Object PENDING = new Object() { + + @Override + public String toString() { + return Inter.getLocText("Loading") + "..."; + } + }; + /** + * 数据库连接失败的界面 + */ + public static final Object CONNECTION_FAILED = new Object() { + + public String toString() { + return Inter.getLocText(new String[]{"Database", "Datasource-Connection_failed"}) + "!"; + } + }; + + /** + * 自动补全的默认快捷键,一般来说是 alt + /. + */ + public static final String DEFAULT_AUTO_COMPLETE = "alt + SLASH"; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/DataCreatorUI.java b/designer_base/src/com/fr/design/data/DataCreatorUI.java new file mode 100644 index 0000000000..fd81fed30e --- /dev/null +++ b/designer_base/src/com/fr/design/data/DataCreatorUI.java @@ -0,0 +1,12 @@ +package com.fr.design.data; + +import javax.swing.*; + +/** + * Created by richie on 15/11/16. + */ +public interface DataCreatorUI { + + JComponent toSwingComponent(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/DesignTableDataManager.java b/designer_base/src/com/fr/design/data/DesignTableDataManager.java new file mode 100644 index 0000000000..5ec6dd1d57 --- /dev/null +++ b/designer_base/src/com/fr/design/data/DesignTableDataManager.java @@ -0,0 +1,468 @@ +package com.fr.design.data; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.base.StoreProcedureParameter; +import com.fr.base.TableData; +import com.fr.data.TableDataSource; +import com.fr.data.core.DataCoreXmlUtils; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.data.impl.EmbeddedTableData; +import com.fr.data.impl.storeproc.ProcedureDataModel; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.data.impl.storeproc.StoreProcedureConstants; +import com.fr.design.data.tabledata.wrapper.*; +import com.fr.design.DesignModelAdapter; +import com.fr.design.gui.iprogressbar.AutoProgressBar; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.parameter.ParameterInputPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.general.data.DataModel; +import com.fr.general.data.TableDataException; +import com.fr.script.Calculator; +import com.fr.stable.ArrayUtils; +import com.fr.stable.ParameterProvider; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLPrintWriter; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.io.ByteArrayOutputStream; +import java.text.Collator; +import java.util.*; +import java.util.Map.Entry; + +/** + * 设计器管理操作数据集的类: + * 1.对于每个TableData,会生成相应的TableDataWrapper.TableDataWrapper里面有TableData的数据列缓存 + * 2.TableDataWrapper是不支持对TableData的修改查询语句 重命名等修改删除操作 + * 如果TableData变化了,那么TableDataWrapper 也会重新生成,然后存进缓存.这样保证缓存是正确的,不会取到错误的数据列。 + * 3.对于模板数据集,关键词应该保证各个模板数据集之间不同,所以默认有个加上模板名的操作。 + * 4.个人觉得完全没有必要做成那种一个SQL语句对应一个数据列的情况,那样子太复杂了。而且每次比较关键词都很慢 + *

+ * !!!Notice: 除了预览数据集的操作,其他所有涉及到数据集的界面操作,都要经过这个类(因为它有数据集的缓存,不需要重复计算) + * + * @author zhou + */ +public abstract class DesignTableDataManager { + /** + * 其实globalDsCache没有绝对的必要,只是为了操作方便。如果没有它,那么每次清空服务器数据集或者存储过程的时候,还要去遍历找一下, + * 这个操作可能比较复杂 。 从减少代码复杂度的角度看,还是很有必要的 + */ + private static java.util.Map globalDsCache = new java.util.HashMap(); + private static java.util.Map dsNameChangedMap = new HashMap(); + private static List dsListeners = new ArrayList(); + + public static String NO_PARAMETER = "no_paramater_pane"; + + //用于记录是否要弹出参数框 + private static ThreadLocal threadLocal = new ThreadLocal(); + + + /** + * 清除全局 数据集缓存. + */ + public static void clearGlobalDs() { + globalDsCache.clear(); + } + + /** + * 响应数据集改变. + */ + private static void fireDsChanged() { + for (int i = 0; i < dsListeners.size(); i++) { + //增强for循环用的iterator实现的, 如果中间哪个listener修改或删除了(如ChartEditPane.dsChangeListener), + // 由于dsListeners是arraylist, 此时会ConcurrentModifyException +// for (ChangeListener l : dsListeners) { + ChangeEvent e = null; + dsListeners.get(i).stateChanged(e); + } + } + + /** + * 响应数据集改变 + * + * @param dsNameChangedMap 改变名字的数据集 + */ + public static void fireDSChanged(Map dsNameChangedMap) { + if (!dsNameChangedMap.isEmpty()) { + setDsNameChangedMap(dsNameChangedMap); + } + fireDsChanged(); + dsNameChangedMap.clear(); + } + + private static void setDsNameChangedMap(Map map) { + Iterator iterator = map.keySet().iterator(); + while (iterator.hasNext()) { + String key = (String) iterator.next(); + dsNameChangedMap.put(key, map.get(key)); + } + } + + /** + * 数据库是否改变 + * + * @param oldDsName 旧名字 + * @return 是则返回true + */ + public static boolean isDsNameChanged(String oldDsName) { + return dsNameChangedMap.containsKey(oldDsName); + } + + public static String getChangedDsNameByOldDsName(String oldDsName) { + if (isDsNameChanged(oldDsName)) { + return dsNameChangedMap.get(oldDsName); + } else { + return StringUtils.EMPTY; + } + } + + /** + * 添加模板数据集改变 监听事件. + * + * @param l ChangeListener监听器 + */ + public static void addDsChangeListener(ChangeListener l) { + dsListeners.add(l); + } + + /** + * 获取数据源source中dsName的所有字段 + * + * @param source 数据源 + * @param dsName 数据集名字 + * @return + */ + public static String[] getSelectedColumnNames(TableDataSource source, String dsName) { + java.util.Map resMap = getAllEditingDataSet(source); + java.util.Map dsMap = getAllDataSetIncludingProcedure(resMap); + TableDataWrapper tabledataWrapper = dsMap.get(dsName); + return tabledataWrapper == null ? new String[0] : tabledataWrapper.calculateColumnNameList().toArray(new String[0]); + } + + /** + * august:返回当前正在编辑的具有报表数据源的模板(基本报表、聚合报表) 包括 : 图表模板 + * + * @return TableDataSource + * attention:与这个方法有关系的静态组件(不随着切换模板tab而变化的),应该重新执行该方法,再刷新组件 + */ + public static TableDataSource getEditingTableDataSource() { + return DesignModelAdapter.getCurrentModelAdapter() == null ? null : DesignModelAdapter.getCurrentModelAdapter().getBook(); + } + + /** + * 返回当前模板(source)数据集、服务器数据集和存储过程中所有的数据集名字 + * + * @param source + * @return + */ + public static String[] getAllDSNames(TableDataSource source) { + Iterator> entryIt = getAllEditingDataSet(source).entrySet().iterator(); + List list = new ArrayList(); + while (entryIt.hasNext()) { + Entry entry = entryIt.next(); + list.add(entry.getKey()); + } + return list.toArray(new String[list.size()]); + } + + /** + * 不根据过滤设置,返回当前模板数据集、服务器数据集、存储过程本身,是有顺序的 + */ + public static java.util.Map getAllEditingDataSet(TableDataSource source) { + java.util.Map resMap = new java.util.LinkedHashMap(); + // 模板数据集 + addTemplateData(resMap, source); + + // 服务器数据集 + addServerData(resMap); + // 存储过程 + addStoreProcedureData(resMap); + + return resMap; + } + + public static java.util.Map getAllDataSetIncludingProcedure(java.util.Map resMap) { + java.util.LinkedHashMap dsMap = new java.util.LinkedHashMap(); + Iterator> entryIt = resMap.entrySet().iterator(); + while (entryIt.hasNext()) { + String key = entryIt.next().getKey(); + TableDataWrapper tableDataWrapper = resMap.get(key); + if (tableDataWrapper.getTableData() instanceof StoreProcedure) { + StoreProcedure storeProcedure = (StoreProcedure) tableDataWrapper.getTableData(); + boolean hasSchemaOrResult = false; + StoreProcedureParameter[] parameters = StoreProcedure.getSortPara(storeProcedure.getParameters()); + String name = tableDataWrapper.getTableDataName(); + ArrayList resultNames = storeProcedure.getResultNames(); + TableDataWrapper tdw = new StoreProcedureNameWrapper(name + "_Table", storeProcedure); + + for (StoreProcedureParameter parameter : parameters) { + if (parameter.getSchema() != StoreProcedureConstants.IN) { + String parameterName = name + "_" + parameter.getName(); + TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false); + dsMap.put(parameterName, newTwd); + hasSchemaOrResult = true; + } + } + + if (!resultNames.isEmpty()) { + hasSchemaOrResult = true; + for (int i = 0; i < resultNames.size(); i++) { + String parameterName = name + "_" + resultNames.get(i); + TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false); + dsMap.put(parameterName, newTwd); + } + } + + if (!hasSchemaOrResult) { + dsMap.put(name + "_Table", tdw); + } + } else { + dsMap.put(key, tableDataWrapper); + } + } + return dsMap; + } + + /** + * 不根据过滤设置,返回当前服务器数据集、存储过程所有的数据集,是有顺序的 + */ + public static java.util.Map getGlobalDataSet() { + java.util.Map resMap = new java.util.LinkedHashMap(); + + // 服务器数据集 + addServerData(resMap); + // 存储过程 + addStoreProcedureData(resMap); + + return resMap; + } + + /** + * 根据过滤设置,返回当前模板数据集、服务器数据集、存储过程所有的数据集,是有顺序的 + */ + public static List> getEditingDataSet(TableDataSource source) { + Map templateDataMap = new LinkedHashMap(); + Map serverDataMap = new LinkedHashMap(); + Map storeProcedureMap = new LinkedHashMap(); + + addTemplateData(templateDataMap, source); + addServerData(serverDataMap); + addStoreProcedureData(storeProcedureMap); + + List> list = new ArrayList>(); + list.add(templateDataMap); + list.add(serverDataMap); + list.add(storeProcedureMap); + return list; + } + + private static void addTemplateData(java.util.Map resMap, TableDataSource source) { + if (source != null) { + String[] namearray = TableDataFactory.getSortOfChineseNameOfTemplateData(source); + for (String tabledataname : namearray) { + TableData td = source.getTableData(tabledataname); + TableDataWrapper tdw = new TemplateTableDataWrapper(td, tabledataname); + resMap.put(tabledataname, tdw); + } + } + } + + private static void addServerData(java.util.Map resMap) { + DatasourceManagerProvider mgr = DatasourceManager.getProviderInstance(); + String[] namearray = TableDataFactory.getSortOfChineseNameOfServerData(mgr); + for (String name : namearray) { + if (globalDsCache.containsKey(name)) { + resMap.put(name, globalDsCache.get(name)); + } else { + TableDataWrapper tdw = new ServerTableDataWrapper(mgr.getTableData(name), name); + resMap.put(name, tdw); + globalDsCache.put(name, tdw); + } + } + } + + + + private static void addStoreProcedureData(java.util.Map resMap) { + DatasourceManagerProvider mgr = DatasourceManager.getProviderInstance(); + String[] namearray = new String[0]; + @SuppressWarnings("unchecked") + java.util.Iterator nameIt = mgr.getProcedureNameIterator(); + while (nameIt.hasNext()) { + namearray = (String[]) ArrayUtils.add(namearray, nameIt.next()); + } + Arrays.sort(namearray, Collator.getInstance(java.util.Locale.CHINA)); + + for (String name : namearray) { + StoreProcedure storeProcedure = mgr.getProcedure(name); + if (globalDsCache.containsKey(name)) { + resMap.put(name, globalDsCache.get(name)); + } else { + TableDataWrapper tdw = new StoreProcedureNameWrapper(name, storeProcedure); + resMap.put(name, tdw); + globalDsCache.put(name, tdw); + } + } + } + + + /** + * 预览需要参数的数据集 + * + * @param tabledata 数据集 + * @param rowCount 需要预览的行数 + * @param needLoadingBar 是否需要加载进度条 + * @return 数据集 + * @throws Exception 异常 + */ + public static EmbeddedTableData previewTableDataNeedInputParameters(TableData tabledata, int rowCount, boolean needLoadingBar) throws Exception { + return previewTableData(tabledata, rowCount, true, needLoadingBar); + } + + /** + * 预览不需要参数的数据集 + * + * @param tabledata 数据集 + * @param rowCount 需要预览的行数 + * @param needLoadingBar 是否需要加载进度条 + * @return 数据集 + * @throws Exception 异常 + */ + public static EmbeddedTableData previewTableDataNotNeedInputParameters(TableData tabledata, int rowCount, boolean needLoadingBar) throws Exception { + return previewTableData(tabledata, rowCount, false, needLoadingBar); + } + + /** + * 获取预览后的EmbeddedTableData,考虑到Env + * + * @param tabledata + * @param rowCount + * @param isMustInputParameters 是否必须输入参数值(不管参数有没有默认值)。一般预览时这个值为true,因为一般预览是要看不同的参数的结果的。 + * 而获取数据集的字段名字时,则没必要 + * @return + */ + private static EmbeddedTableData previewTableData(TableData tabledata, int rowCount, boolean isMustInputParameters, boolean needLoadingBar) throws Exception { + final AutoProgressBar loadingBar = PreviewTablePane.getInstance().getProgressBar(); + Env currentEnv = FRContext.getCurrentEnv(); + EmbeddedTableData embeddedTableData = null; + ParameterProvider[] parameters = currentEnv.getTableDataParameters(tabledata); + boolean isNullParameter = parameters == null || parameters.length == 0; + ParameterProvider[] tableDataParameter = tabledata.getParameters(Calculator.createCalculator()); + boolean isOriginalNUllParameter = tableDataParameter == null || tableDataParameter.length == 0; + if (isNullParameter && !isOriginalNUllParameter) { + parameters = tableDataParameter; + } + boolean hasValue = true; + for (ParameterProvider parameter : parameters) { + if (parameter.getValue() == null || ComparatorUtils.equals(StringUtils.EMPTY, parameter.getValue())) { + hasValue = false; + break; + } + } + final Map parameterMap = new HashMap(); + if (!hasValue || isMustInputParameters) { + if (parameters != null && parameters.length > 0) { + final ParameterInputPane pPane = new ParameterInputPane(parameters); + pPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + + public void doOk() { + parameterMap.putAll(pPane.update()); + } + }).setVisible(true); + } + } else { + for (int i = 0; i < parameters.length; i++) { + parameterMap.put(parameters[i].getName(), parameters[i].getValue()); + } + } + if (loadingBar != null && needLoadingBar) { + loadingBar.start(); + } + try { + embeddedTableData = currentEnv.previewTableData(tabledata, parameterMap, rowCount); + } catch (TableDataException e) { + throw new TableDataException(e.getMessage(), e); + } finally { + new Timer().schedule(new TimerTask() { + public void run() { + loadingBar.close(); + } + }, 100); + } + return embeddedTableData; + } + + /** + * 返回TableData的数据列,注意TableData + * 是没有考虑参数的。用于简单的查询语句生成的TableData, 或者 + * EmbeddedTableData. 比如说:数据字典-数据库表生成的TableData。 + * 使用该方法是没有数据集缓存的功能的 + * + * @return List + */ + public static List getColumnNamesByTableData(TableData tableData) { + List columnNames = new ArrayList(); + if (tableData != null) { + DataModel rs = tableData.createDataModel(Calculator.createCalculator()); + int value; + try { + value = rs.getColumnCount(); + for (int i = 0; i < value; i++) { + columnNames.add(rs.getColumnName(i)); + } + rs.release(); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + + } + + return columnNames; + } + + /** + * 该方法主要利用了StoreProcedure里面的“dataModelList有缓存作用”的机制 + * 所以用该方法,不会对一个已经计算了的存储过程重复计算.和分页预览时处理机制一样,这样对有多个返回数据集的存储过程来说很有必要 + * + * @param needLoadingBar 是否需要进度条 + * @param storeProcedure 存储过程 + * @return 数据 + */ + public static ProcedureDataModel[] createLazyDataModel(StoreProcedure storeProcedure, boolean needLoadingBar) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + XMLPrintWriter writer = XMLPrintWriter.create(out); + // 把storeProcedure写成xml文件到out + DataCoreXmlUtils.writeXMLStoreProcedure(writer, storeProcedure, null); + Env currentEnv = FRContext.getCurrentEnv(); + if (storeProcedure.getDataModelSize() > 0 && !storeProcedure.isFirstExpand()) { + return storeProcedure.creatLazyDataModel(); + } + ParameterProvider[] inParameters = currentEnv.getStoreProcedureParameters(storeProcedure); + final Map parameterMap = new HashMap(); + if (inParameters.length > 0 && !ComparatorUtils.equals(threadLocal.get(), NO_PARAMETER)) {// 检查Parameter. + final ParameterInputPane pPane = new ParameterInputPane(inParameters); + pPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + public void doOk() { + parameterMap.putAll(pPane.update()); + } + }).setVisible(true); + + } + storeProcedure.setFirstExpand(false); + if (needLoadingBar) { + StoreProcedureDataWrapper.loadingBar.start(); + } + return FRContext.getCurrentEnv().previewProcedureDataModel(storeProcedure, parameterMap, 0); + } + + public static void setThreadLocal(String value) { + threadLocal.set(value); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/ChoosePane.java b/designer_base/src/com/fr/design/data/datapane/ChoosePane.java new file mode 100644 index 0000000000..b6cfc25a7a --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/ChoosePane.java @@ -0,0 +1,602 @@ +package com.fr.design.data.datapane; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.TableData; +import com.fr.data.core.DataCoreUtils; +import com.fr.data.core.db.DBUtils; +import com.fr.data.core.db.TableProcedure; +import com.fr.data.core.db.dialect.DialectFactory; +import com.fr.data.impl.DBTableData; +import com.fr.dav.LocalEnv; +import com.fr.design.DesignerEnvManager; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.RefreshLabel.Refreshable; +import com.fr.design.data.datapane.preview.PreviewLabel; +import com.fr.design.data.datapane.preview.PreviewLabel.Previewable; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.data.tabledata.Prepare4DataSourceChange; +import com.fr.design.gui.icombobox.*; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +/** + * @author zhou + * @since 2012-7-11下午4:49:39 + */ +public class ChoosePane extends BasicBeanPane implements Refreshable, Previewable, Prepare4DataSourceChange { + private static final double COLUMN_SIZE = 24; + + /** + * 数据库 + */ + protected StringUIComboBox dsNameComboBox; + + /** + * 模式 + */ + protected StringUIComboBox schemaBox; + + /** + * 表名 + */ + protected FRTreeComboBox tableNameComboBox; + + private SwingWorker populateWorker; + + + private PopupMenuListener popupMenuListener = new PopupMenuListener() { + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + new Thread() { + @Override + public void run() { + calculateTableDataNames(); + } + }.start(); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + public void popupMenuCanceled(PopupMenuEvent e) { + } + }; + + + private PopupMenuListener listener = new PopupMenuListener() { + public void popupMenuCanceled(PopupMenuEvent e) { + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + executePopulateWorker(); + } + }; + + public ChoosePane() { + this(null); + } + + public ChoosePane(Previewable parent) { + this(parent, -1); + } + + public ChoosePane(Previewable parent, int labelSize) { + this.initBasicComponet(); + this.initComponentsLayout(new PreviewLabel(parent == null ? this : parent), labelSize); + } + + private void initBasicComponet() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + dsNameComboBox = new StringUIComboBox(); + initDsNameComboBox(); + + schemaBox = new StringUIComboBox(); + schemaBox.setEditor(new ComboBoxEditor()); + + tableNameComboBox = new FRTreeComboBox(new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer, false); + tableNameComboBox.setEditable(true); + tableNameComboBox.setRenderer(listCellRenderer); + registerDSChangeListener(); + initBoxListener(); + } + + private void initBoxListener() { + addDSBoxListener(); + schemaBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent evt) { + tableNameComboBox.setSelectedItem(""); + } + }); + schemaBox.addPopupMenuListener(listener); + addFocusListener(); + this.tableNameComboBox.addPopupMenuListener(popupMenuListener); + } + + protected void addDSBoxListener() { + dsNameComboBox.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + schemaBox.setSelectedIndex(-1); + tableNameComboBox.setSelectedItem(""); + JTree tree = tableNameComboBox.getTree(); + if (tree == null) { + return; + } + DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); + rootTreeNode.removeAllChildren(); + rootTreeNode.add(new ExpandMutableTreeNode("Loading...")); + ((DefaultTreeModel) tree.getModel()).reload(); + + } + }); + } + + protected void addFocusListener() { + schemaBox.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + if (schemaBox.getSelectedIndex() == -1) { + schemaBox.updateUI(); + schemaBox.showPopup(); + } + } + }); + } + + protected void initDsNameComboBox() { + dsNameComboBox.setRefreshingModel(true); + DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + @SuppressWarnings("unchecked") + Iterator datasourceNameIterator = datasourceManager.getConnectionNameIterator(); + List dsList = new ArrayList(); + while (datasourceNameIterator.hasNext()) { + dsList.add((String) datasourceNameIterator.next()); + } + FilterableComboBoxModel dsNameComboBoxModel = new FilterableComboBoxModel(dsList); + dsNameComboBox.setModel(dsNameComboBoxModel); + dsNameComboBox.setRefreshingModel(false); + } + + protected void initComponentsLayout(PreviewLabel previewLabel, int labelSize) { + UILabel l1 = new UILabel(Inter.getLocText("FR-Designer_Database") + ":"); + UILabel l2 = new UILabel(Inter.getLocText("FR-Designer_Model") + ":"); + UILabel l3 = new UILabel(Inter.getLocText("FR-Designer_Table") + ":"); + + if (labelSize > 0) { + Dimension pSize = new Dimension(labelSize, 25); + l1.setPreferredSize(pSize); + l2.setPreferredSize(pSize); + l3.setPreferredSize(pSize); + } + + Component[][] coms = new Component[][]{{l1, dsNameComboBox, l2, schemaBox, + l3, this.tableNameComboBox, new RefreshLabel(this), previewLabel}}; + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + JPanel northDSPane = TableLayoutHelper.createTableLayoutPane(coms, new double[]{p}, new double[]{p, f, p, f, p, f, COLUMN_SIZE, COLUMN_SIZE}); + + this.add(northDSPane, BorderLayout.CENTER); + + } + + @Override + public void populateBean(final DataBaseItems ob) { + this.dsNameComboBox.setSelectedItem(ob.getDatabaseName()); + schemaBox.setSelectedItem(ob.getSchemaName()); + this.tableNameComboBox.setSelectedItem(ob.getTableName()); + } + + + private void executePopulateWorker() { + if (populateWorker != null) { + populateWorker.cancel(true); + } + populateWorker = new SwingWorker() { + + protected com.fr.data.impl.Connection doInBackground() throws Exception { + schemaBox.addItem(Inter.getLocText("FR-Designer_Loading") + "..."); + schemaBox.setSelectedItem(null); + return getConnection(); + } + + public void done() { + try { + com.fr.data.impl.Connection selectedDatabase = get(); + String selectedItem = schemaBox.getSelectedItem(); + schemaBox.setRefreshingModel(true); + schemaBox.removeAllItems(); + schemaBox.updateUI(); + if (selectedDatabase == null) { + return; + } + String[] schema = DataCoreUtils.getDatabaseSchema(selectedDatabase); + schema = schema == null ? new String[]{""} : schema; + for (String aa : schema) { + schemaBox.addItem(aa); + } + int index = schemaBox.getSelectedIndex(); + if (selectedItem != null) { + schemaBox.setSelectedItem(selectedItem); + } else if (index < schema.length) { + schemaBox.setSelectedIndex(index); + } + } catch (Exception e) { + FRLogger.getLogger().error(e.getMessage()); + } + schemaBox.setRefreshingModel(false); + schemaBox.removePopupMenuListener(listener); + schemaBox.setPopupVisible(true); + schemaBox.addPopupMenuListener(listener); + } + }; + populateWorker.execute(); + } + + @Override + public DataBaseItems updateBean() { + return new DataBaseItems(this.getDSName(), this.schemaBox.getSelectedItem(), getTableName()); + } + + /** + * 重置选中的box + */ + public void resetComponets() { + GUICoreUtils.setSelectedItemQuietly(dsNameComboBox, -1); + GUICoreUtils.setSelectedItemQuietly(schemaBox, -1); + GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1); + } + + protected com.fr.data.impl.Connection getConnection() { + String selectedDSName = this.getDSName(); + if (StringUtils.isEmpty(selectedDSName)) { + return null; // peter:选中了当前的零长度的节点,直接返回. + } + DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + @SuppressWarnings("unchecked") + Iterator datasourceNameIterator = datasourceManager.getConnectionNameIterator(); + while (datasourceNameIterator.hasNext()) { + String datasourceName = datasourceNameIterator.next(); + if (ComparatorUtils.equals(selectedDSName, datasourceName)) { + return datasourceManager.getConnection(datasourceName); + } + } + return null; + } + + /** + * 刷新没多大用。而且要刷新也不是这儿刷新。 + */ + public void refresh() { + DBUtils.refreshDatabase(); + String schema = StringUtils.isEmpty(schemaBox.getSelectedItem()) ? null : schemaBox.getSelectedItem(); + DataCoreUtils.refreshTables(getConnection(), TableProcedure.TABLE, schema); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Designer_Refresh_Successfully") + "!", Inter.getLocText("FR-Designer_Refresh_Database"), + JOptionPane.INFORMATION_MESSAGE); + } + + TreeCellRenderer tableNameTreeRenderer = new DefaultTreeCellRenderer() { + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (value instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; + Object userObj = node.getUserObject(); + if (userObj instanceof String) { + this.setIcon(BaseUtils.readIcon("com/fr/design/images/m_insert/expandCell.gif")); + } else if (userObj instanceof TableProcedure) { + this.setText(((TableProcedure) userObj).getName()); + } + } + return this; + } + }; + + public static UIComboBoxRenderer listCellRenderer = new UIComboBoxRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof TreePath) { + DefaultMutableTreeNode dmt = (DefaultMutableTreeNode) ((TreePath) value).getLastPathComponent(); + if (dmt.getUserObject() instanceof TableProcedure) { + this.setText(((TableProcedure) dmt.getUserObject()).getName()); + } else { + this.setText(null); + } + } + return this; + } + }; + + + /** + * 添加项目监听事件 + * @param aListener 事件监听器 + */ + public void addItemListener(ItemListener aListener) { + this.tableNameComboBox.addItemListener(aListener); + } + + /** + * 删除项目监听事件 + * @param aListener 事件监听器 + */ + public void removeItemListener(ItemListener aListener) { + this.tableNameComboBox.removeItemListener(aListener); + } + + @Override + protected String title4PopupWindow() { + return "choosepane"; + } + + protected void calculateTableDataNames() { + JTree tree = tableNameComboBox.getTree(); + if (tree == null) { + return; + } + DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); + rootTreeNode.removeAllChildren(); + + String selectedDSName = this.getDSName(); + com.fr.data.impl.Connection selectedDatabase = this.getConnection(); + if (selectedDatabase == null) { + return; + } + try { + String schema = StringUtils.isEmpty(this.schemaBox.getSelectedItem()) ? null : this.schemaBox.getSelectedItem(); + TableProcedure[] sqlTableArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); + if (sqlTableArray.length > 0) { + ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + Inter.getLocText("FR-Designer_SQL-Table")); + rootTreeNode.add(tableTreeNode); + for (int i = 0; i < sqlTableArray.length; i++) { + ExpandMutableTreeNode tableChildTreeNode = new ExpandMutableTreeNode(sqlTableArray[i]); + tableTreeNode.add(tableChildTreeNode); + } + } + TableProcedure[] sqlViewArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace()); + if (sqlViewArray.length > 0) { + ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + Inter.getLocText("FR-Designer_SQL-View")); + rootTreeNode.add(viewTreeNode); + for (int i = 0; i < sqlViewArray.length; i++) { + ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(sqlViewArray[i]); + viewTreeNode.add(viewChildTreeNode); + } + } + ((DefaultTreeModel) tree.getModel()).reload(); + /** + * daniel 展开所有tree + */ + TreeNode root = (TreeNode) tree.getModel().getRoot(); + TreePath parent = new TreePath(root); + TreeNode node = (TreeNode) parent.getLastPathComponent(); + for (Enumeration e = node.children(); e.hasMoreElements(); ) { + TreeNode n = (TreeNode) e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + tree.expandPath(path); + } + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + + /** + * 创建选中的数据集数据 + * @return 数据集数据 + */ + public TableData createSelectTableData() { + DataBaseItems paras = this.updateBean(); + boolean connect = false; + com.fr.data.impl.Connection database = DBUtils.checkDBConnection(paras.getDatabaseName()); + if (database == null) { + failedToFindTable(); + return TableData.EMPTY_TABLEDATA; + } + try { + connect = FRContext.getCurrentEnv().testConnection(database); + } catch (Exception e1) { + connect = false; + } + if (!connect) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + JOptionPane.showMessageDialog(designerFrame, Inter.getLocText("Datasource-Connection_failed"), + Inter.getLocText("FR-Designer_Failed"), JOptionPane.INFORMATION_MESSAGE); + failedToFindTable(); + return null; + } + // 显示Table数据. + + TableData tableData = null; + if (FRContext.getCurrentEnv() instanceof LocalEnv) { + TableData tableDataLocal = new DBTableData(database, DataCoreUtils.createSelectSQL(paras.getSchemaName(), paras.getTableName(), + DialectFactory.getDialectByName(paras.getDatabaseName()))); + tableData = tableDataLocal; + } else { + try { + TableData tableDataLocal = new DBTableData(database, DataCoreUtils.createSelectSQL(paras.getSchemaName(), paras.getTableName(), DialectFactory.getDialectByName(paras.getDatabaseName()))); + tableData = FRContext.getCurrentEnv().previewTableData(tableDataLocal, java.util.Collections.EMPTY_MAP, + DesignerEnvManager.getEnvManager().getMaxNumberOrPreviewRow()); + } catch (Exception e) { + failedToFindTable(); + FRContext.getLogger().error(e.getMessage(), e); + } + } + + return tableData; + } + + protected String getDSName() { + return this.dsNameComboBox.getSelectedItem(); + } + + protected void failedToFindTable() { + } + + protected String getTableName() { + String tableName = ""; + Object obj = this.tableNameComboBox.getSelectedItem(); + if (obj == null) { + obj = this.tableNameComboBox.getEditor().getItem(); + } + if (obj instanceof TreePath) { + Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject(); + if (tp instanceof TableProcedure) { + tableName = ((TableProcedure) tp).getName(); + } + } else if (obj instanceof String) { + tableName = (String) obj; + } + return tableName; + } + + /** + * 得到当前的ColumnName[] + * @return 返回当前的ColumnName[] + */ + public String[] currentColumnNames() { + String[] colNames = null; + + DataBaseItems paras = this.updateBean(); + String selectedDSName = paras.getDatabaseName(); + if (StringUtils.isBlank(selectedDSName)) { + return colNames = new String[0]; // peter:选中了当前的零长度的节点,直接返回. + } + + String selectedTableObject = paras.getTableName(); + if (StringUtils.isEmpty(selectedTableObject)) { + return colNames = new String[0]; + } + java.sql.Connection conn = null; + try { + // daniel:增加参数 + colNames = FRContext.getCurrentEnv().getColumns(selectedDSName, paras.getSchemaName(), selectedTableObject); + } catch (Exception e2) { + FRContext.getLogger().error(e2.getMessage(), e2); + } finally { + DBUtils.closeConnection(conn); + } + + if (colNames == null) { + colNames = new String[0]; + } + return colNames; + } + + /** + * 预览key value对应的数据 + * @param key 键 + * @param value 值 + */ + public void preview(int key, int value) { + PreviewTablePane.previewTableData(createSelectTableData(), key, value); + } + + /** + * 默认预览 + */ + public void preview() { + preview(-1, -1); + } + + /** + * 设置数据集名. + */ + public void setTableNameComboBoxPopSize(int width, int height) { + tableNameComboBox.setPopSize(width, height); + } + + /** + *注册listener,相应数据集改变 + */ + public void registerDSChangeListener() { + DesignTableDataManager.addDsChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + initDsNameComboBox(); + } + }); + } + + + protected class StringUIComboBox extends UIComboBox { + private boolean refreshingModel = false; + + @Override + protected void fireItemStateChanged(ItemEvent e) { + if (!isRefreshingModel()) { + super.fireItemStateChanged(e); + } + } + + @Override + public String getSelectedItem() { + Object ob = super.getSelectedItem(); + if (ob instanceof String) { + return (String) ob; + } else + return StringUtils.EMPTY; + } + + public boolean isRefreshingModel() { + return refreshingModel; + } + + public void setRefreshingModel(boolean refreshingModel) { + this.refreshingModel = refreshingModel; + } + + public void setSelectedItem(Object ob) { + this.getModel().setSelectedItem(ob); + if (ob != null && StringUtils.isEmpty(ob.toString())) { + super.setSelectedIndex(-1); + } else { + super.setSelectedItem(ob); + } + } + } + + private class ComboBoxEditor extends UIComboBoxEditor { + private Object item; + + public void setItem(Object item) { + this.item = item; + textField.setText((item == null) ? "" : item.toString()); + } + + public Object getItem() { + return this.item; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/ChoosePaneSupportFormula.java b/designer_base/src/com/fr/design/data/datapane/ChoosePaneSupportFormula.java new file mode 100644 index 0000000000..c59f187f56 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/ChoosePaneSupportFormula.java @@ -0,0 +1 @@ +package com.fr.design.data.datapane; import com.fr.base.*; import com.fr.design.data.datapane.preview.PreviewLabel; import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.data.impl.EmbeddedTableData; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.parameter.ParameterInputPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.general.ComparatorUtils; import com.fr.script.Calculator; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.*; /** * Author : Shockway * Date: 13-8-16 * Time: 下午3:46 */ public class ChoosePaneSupportFormula extends ChoosePane { private String ori_ds_formula; private String ori_ds_name; private String ori_table_formula; private String ori_table_name; public ChoosePaneSupportFormula() { this(null); } public ChoosePaneSupportFormula(PreviewLabel.Previewable parent) { this(parent, -1); } public ChoosePaneSupportFormula(PreviewLabel.Previewable parent, int labelSize) { super(parent, labelSize); this.dsNameComboBox.setEditable(true); } protected void addDSBoxListener() { dsNameComboBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { schemaBox.setSelectedIndex(-1); // 如果table是用公式编辑的 没必要联动清除 if (Utils.objectToString(tableNameComboBox.getEditor().getItem()).startsWith("=")) { return; } tableNameComboBox.setSelectedItem(""); JTree tree = tableNameComboBox.getTree(); if (tree == null) { return; } DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot(); rootTreeNode.removeAllChildren(); rootTreeNode.add(new ExpandMutableTreeNode("Loading...")); ((DefaultTreeModel) tree.getModel()).reload(); } }); } protected void addFocusListener() { } /** * 只弹出数据库框里的参数 * * @return */ protected String getDSName() { String selectedDSName = null; String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem()); // 没有选中的列表项 那么看看是不是手输值 if (item == null) { return null; } if (ComparatorUtils.equals(ori_ds_formula, item)) { return ori_ds_name; } ori_ds_formula = item; // 公式 需要解析 输入默认值 if (item.startsWith("=")) { Calculator ca = Calculator.createCalculator(); boolean isFormula = true; Parameter[] parameters = ParameterHelper.analyze4Parameters(new String[]{item}, isFormula); if (parameters.length > 0) { final Map paraMap = new HashMap(); analyseParaDefaultValue(parameters); final ParameterInputPane pPane = new ParameterInputPane(parameters, false); pPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { public void doOk() { paraMap.putAll(pPane.update()); } }).setVisible(true); ca.pushNameSpace(ParameterMapNameSpace.create(paraMap)); } try { selectedDSName = Utils.objectToString(ca.eval(new Formula(item))); // selectedDSName = ParameterHelper.analyzeCurrentContextTableData4Templatee(item, parameters); } catch (Exception e) { FRContext.getLogger().error(e.getMessage()); } } else { selectedDSName = item; } ori_ds_name = selectedDSName; return selectedDSName; } /** * 在一个参数弹窗中弹出数据库框和表框的参数 * * @return */ protected String[] getDSAndTableName() { String dsName = "", tableName = ""; String dsItem = Utils.objectToString(this.dsNameComboBox.getEditor().getItem()); String tableItem = this.getTableName(); if (ComparatorUtils.equals(ori_ds_formula, dsItem) && ComparatorUtils.equals(ori_table_formula, tableItem)) { return new String[]{ori_ds_name, ori_table_name}; } ori_ds_formula = dsItem; ori_table_formula = tableItem; List paraList = new ArrayList(); pushPara(dsItem, paraList); pushPara(tableItem, paraList); Calculator ca = Calculator.createCalculator(); if (!paraList.isEmpty()) { Parameter[] parameters = (Parameter[]) paraList.toArray(new Parameter[paraList.size()]); final Map paraMap = new HashMap(); analyseParaDefaultValue(parameters); final ParameterInputPane pPane = new ParameterInputPane(parameters, false); pPane.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { public void doOk() { paraMap.putAll(pPane.update()); } }).setVisible(true); ca.pushNameSpace(ParameterMapNameSpace.create(paraMap)); } try { dsName = dsItem.startsWith("=") ? Utils.objectToString(ca.eval(new Formula(dsItem))) : dsItem; tableName = tableItem.startsWith("=") ? Utils.objectToString(ca.eval(new Formula(tableItem))) : tableItem; } catch (Exception e) { FRContext.getLogger().error(e.getMessage()); } ori_ds_name = dsName; ori_table_name = tableName; return new String[]{dsName, tableName}; } private void pushPara(String item, List paraList) { if (item.startsWith("=")) { Parameter[] parameters = ParameterHelper.analyze4Parameters(new String[]{item}, true); for (Parameter p : parameters) { if (!paraList.contains(p)) { paraList.add(p); } } } } protected void failedToFindTable() { this.ori_ds_formula = null; this.ori_table_formula = null; } /** * 预览key value对应的数据 * @param key 键 * @param value 值 */ public void preview(int key, int value) { EmbeddedTableData tb = PreviewTablePane.previewTableData(createSelectTableData(), key, value); if (tb == null) { failedToFindTable(); } } public DataBaseItems updateBean() { return updateBean(false); } /** * 这个分两种情况 设计的时候弹窗填入参数 需要返回计算后的值 * 而当写入xml的时候 需要取他的原始formula * * @param getFormula * @return */ public DataBaseItems updateBean(boolean getFormula) { String[] names; if (getFormula) { names = new String[]{Utils.objectToString(this.dsNameComboBox.getEditor().getItem()), this.getTableName()}; } else { names = getDSAndTableName(); } if (names != null && names.length == 2) { return new DataBaseItems(names[0], this.schemaBox.getSelectedItem(), names[1]); } else { return new DataBaseItems("", "", ""); } } /** * 从模板参数和全局参数中取参数的默认值 * * @param ps 参数 */ public void analyseParaDefaultValue(Parameter[] ps) { JTemplate jTemplate = DesignerContext.getDesignerFrame().getSelectedJTemplate(); Parameter[] allParas = jTemplate.getParameters(); for (int i = 0; i < ps.length; i++) { Parameter p = ps[i]; for (int j = 0; j < allParas.length; j++) { if (ComparatorUtils.equals(p.getName(), allParas[j].getName())) { p.setValue(allParas[j].getValue()); } } } } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/DSButtonGroup.java b/designer_base/src/com/fr/design/data/datapane/DSButtonGroup.java new file mode 100644 index 0000000000..c0c806cfbf --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/DSButtonGroup.java @@ -0,0 +1,48 @@ +package com.fr.design.data.datapane; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.mainframe.WestRegionContainerPane; + +import javax.swing.*; +import java.awt.*; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-4-27 + * Time: 上午10:32 + * To change this template use File | Settings | File Templates. + */ +public class DSButtonGroup extends UIButtonGroup { + + public DSButtonGroup(Icon[] iconArray, Integer[] objects) { + super(iconArray, objects); + } + + + + + protected void paintBorder(Graphics g) { + int tabledatatreepaneWidth = WestRegionContainerPane.getInstance().getWidth()-10; + int labelX = 54 - (290 - tabledatatreepaneWidth) / 4 - 1; + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(UIConstants.LINE_COLOR); + + int width = 0; + + width += labelButtonList.get(0).getWidth() + 1; + int height = labelButtonList.get(0).getHeight(); + g.drawLine(width + labelX, 0, width + labelX, height); + + width += labelButtonList.get(labelButtonList.size() - 1).getWidth() + 1; + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect( labelX, 0, width, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + + g2d.drawLine(labelX / 2, getHeight() / 2, width + 3 * labelX / 2 , getHeight() / 2); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/DataBaseItems.java b/designer_base/src/com/fr/design/data/datapane/DataBaseItems.java new file mode 100644 index 0000000000..fda5282ba1 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/DataBaseItems.java @@ -0,0 +1,49 @@ +package com.fr.design.data.datapane; + +import com.fr.stable.StringUtils; + +/** + * + * @author zhou + * @since 2012-7-11下午5:11:31 + */ +public class DataBaseItems { + private String databaseName; + private String schemaName; + private String tableName; + + public DataBaseItems() { + this(null, null, null); + } + + public DataBaseItems(String databaseName, String schemaName, String tableName) { + this.setDatabaseName(databaseName); + this.setSchemaName(schemaName); + this.setTableName(tableName); + } + + public String getDatabaseName() { + return databaseName; + } + + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName == null ? StringUtils.EMPTY : databaseName; + } + + public String getSchemaName() { + return schemaName; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName == null ? StringUtils.EMPTY : schemaName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName == null ? StringUtils.EMPTY : tableName; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/EditOrNewLabel.java b/designer_base/src/com/fr/design/data/datapane/EditOrNewLabel.java new file mode 100644 index 0000000000..7a0c9b3490 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/EditOrNewLabel.java @@ -0,0 +1,34 @@ +package com.fr.design.data.datapane; + +import java.awt.Cursor; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.base.BaseUtils; +import com.fr.design.data.datapane.FlashLookLabelMouseAdapter.ReleaseAction; +import com.fr.general.Inter; + + +public class EditOrNewLabel extends UILabel { + JPanel editTablePane; + Editable editable; + + public EditOrNewLabel(Editable editable, JPanel editPane) { + super(BaseUtils.readIcon("/com/fr/design/images/m_file/edit.png")); + this.setToolTipText(Inter.getLocText("Edit")); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.editable = editable; + this.editTablePane = editPane; + this.addMouseListener(new FlashLookLabelMouseAdapter(this, new ReleaseAction() { + @Override + public void releaseAction() { + EditOrNewLabel.this.editable.edit(EditOrNewLabel.this.editTablePane); + } + })); + } + + public static interface Editable { + public void edit(JPanel jPanel); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/FlashLookLabelMouseAdapter.java b/designer_base/src/com/fr/design/data/datapane/FlashLookLabelMouseAdapter.java new file mode 100644 index 0000000000..b7d14b4d79 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/FlashLookLabelMouseAdapter.java @@ -0,0 +1,57 @@ +package com.fr.design.data.datapane; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.BorderFactory; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.border.Border; + +public class FlashLookLabelMouseAdapter extends MouseAdapter { + boolean mouseEntered = false; + boolean buttonPressed = false; + + private UILabel label; + private ReleaseAction releaseAction; + private static final Border NORMAL_BORDER = BorderFactory.createLineBorder(UIConstants.NORMAL_BACKGROUND); + private static final Border ENTERED_BORDER = BorderFactory.createLineBorder(java.awt.Color.GRAY); + + public FlashLookLabelMouseAdapter(UILabel label, ReleaseAction releaseAction) { + this.label = label; + label.setBorder(NORMAL_BORDER); + this.releaseAction = releaseAction; + } + + public void mouseEntered(MouseEvent e) { //当鼠标进入时候调用. + mouseEntered = true; + if(!buttonPressed){ + label.setBackground(java.awt.Color.WHITE); + label.setOpaque(true); + label.setBorder(ENTERED_BORDER); + } + } + public void mouseExited(MouseEvent e) { + mouseEntered = false; + label.setOpaque(false); + label.setBorder(NORMAL_BORDER); + } + + public void mousePressed(MouseEvent e){ + buttonPressed = true; + label.setBackground(java.awt.Color.lightGray); + } + public void mouseReleased(MouseEvent e){ + buttonPressed = false; + if(mouseEntered){ + label.setBackground(java.awt.Color.WHITE); + + this.releaseAction.releaseAction(); + } + } + + public static interface ReleaseAction { + public void releaseAction(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/GlobalTableDataComboBox.java b/designer_base/src/com/fr/design/data/datapane/GlobalTableDataComboBox.java new file mode 100644 index 0000000000..b3baf85d3f --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/GlobalTableDataComboBox.java @@ -0,0 +1,22 @@ +package com.fr.design.data.datapane; + +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.TableDataSource; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-4-20 + * Time: 上午11:16 + * To change this template use File | Settings | File Templates. + */ +public class GlobalTableDataComboBox extends TableDataComboBox { + + public GlobalTableDataComboBox(TableDataSource source, String treeName) { + super(source, treeName); + } + protected void setResMap(TableDataSource source){ + resMap = DesignTableDataManager.getGlobalDataSet(); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java b/designer_base/src/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java new file mode 100644 index 0000000000..7278047a27 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/GlobalTreeTableDataDictPane.java @@ -0,0 +1,21 @@ +package com.fr.design.data.datapane; + +import com.fr.design.data.DesignTableDataManager; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-4-20 + * Time: 上午11:27 + * To change this template use File | Settings | File Templates. + */ +public class GlobalTreeTableDataDictPane extends TreeTableDataDictPane { + + public GlobalTreeTableDataDictPane(String treeName) { + super(treeName); + } + + protected void setTableDataNameComboBox(String string) { + tableDataNameComboBox = new GlobalTableDataComboBox(DesignTableDataManager.getEditingTableDataSource(),string); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/RefreshLabel.java b/designer_base/src/com/fr/design/data/datapane/RefreshLabel.java new file mode 100644 index 0000000000..341956ae3f --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/RefreshLabel.java @@ -0,0 +1,37 @@ +package com.fr.design.data.datapane; + +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.general.Inter; + + + +public class RefreshLabel extends UIButton { + private Refreshable refreshable; + + public RefreshLabel(Refreshable refreshable) { + super(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + + this.refreshable = refreshable; + + this.setToolTipText(Inter.getLocText("Refresh_Database")); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + RefreshLabel.this.refreshable.refresh(); + } + }); + this.setPreferredSize(new Dimension(24, 20)); + } + + public static interface Refreshable { + public void refresh(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/ReportTableDataPane.java b/designer_base/src/com/fr/design/data/datapane/ReportTableDataPane.java new file mode 100644 index 0000000000..e62aaa5304 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/ReportTableDataPane.java @@ -0,0 +1,62 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.data.datapane; + +import com.fr.data.TableDataSource; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.frpane.LoadingBasicPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.util.Map; + +/** + * @author richer + * @since 6.5.5 + * 创建于2011-6-14 + */ +public class ReportTableDataPane extends LoadingBasicPane { + private TableDataListPane tdListPane; + + @Override + protected void initComponents(JPanel container) { + container.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.tdListPane = new TableDataListPane() { + @Override + public NameableCreator[] createNameableCreators() { + + return TableDataCreatorProducer.getInstance().createReportTableDataCreator(); + } + }; + container.add(tdListPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("DS-Report_TableData"); + } + + public void populate(TableDataSource tds) { + tdListPane.populate(tds); + } + + public void update(TableDataSource tds) { + tdListPane.update(tds); + } + + /** + * 检查tdListPane有效性check Valid + * + * @throws Exception 异常 + */ + public void checkValid() throws Exception { + this.tdListPane.checkValid(); + } + + public Map getDsNameChangedMap() { + return tdListPane.getDsNameChangedMap(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataComboBox.java b/designer_base/src/com/fr/design/data/datapane/TableDataComboBox.java new file mode 100644 index 0000000000..711c2fc717 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataComboBox.java @@ -0,0 +1,149 @@ +package com.fr.design.data.datapane; + +import java.awt.Component; +import java.awt.event.ItemEvent; +import java.util.Iterator; +import java.util.Map.Entry; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.design.constants.UIConstants; +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.TableDataSource; +import com.fr.design.data.tabledata.Prepare4DataSourceChange; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; + +/** + * 包含所有数据集的下拉框 + * + * @author zhou + * @since 2012-4-20上午10:34:30 + */ +public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceChange { + protected java.util.Map resMap; + private java.util.Map dsMap; + private static final long serialVersionUID = 1L; + private boolean refresModel = false; + private String treeName; //树数据集本身的名字 + + public TableDataComboBox(TableDataSource source){ + this(source,StringUtils.EMPTY); + } + public TableDataComboBox(TableDataSource source, String treeName) { + super(); + this.treeName = treeName; + this.setRenderer(new UIComboBoxRenderer() { + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel renderer = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof TableDataWrapper) { + TableDataWrapper tabledatawrappe = (TableDataWrapper)value; + renderer.setIcon(tabledatawrappe.getIcon()); + renderer.setText(tabledatawrappe.getTableDataName()); + renderer.setToolTipText(tabledatawrappe.getTableDataName()); + } else { + renderer.setIcon(null); + renderer.setText(StringUtils.EMPTY); + } + return renderer; + } + }); + refresh(source); + registerDSChangeListener(); + } + + /** + * refresh ComboBox + * @param source + */ + public void refresh(TableDataSource source) { + TableDataWrapper dataWrapper = getSelectedItem(); + refresModel = true; + setResMap(source); + setDsMap(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + this.setModel(model); + model.addElement(UIConstants.PENDING); + Iterator> entryIt = dsMap.entrySet().iterator(); + while (entryIt.hasNext()) { + TableDataWrapper tableDataWrapper = entryIt.next().getValue(); + if (!ComparatorUtils.equals(tableDataWrapper.getTableDataName(), treeName)) { + model.addElement(tableDataWrapper); + } + } + if (dataWrapper != null) { + if (DesignTableDataManager.isDsNameChanged(dataWrapper.getTableDataName())) { + this.setSelectedTableDataByName(DesignTableDataManager.getChangedDsNameByOldDsName(dataWrapper.getTableDataName())); + } else { + this.getModel().setSelectedItem(dataWrapper); + } + } + refresModel = false; + } + + protected void setResMap(TableDataSource source) { + this.resMap = DesignTableDataManager.getAllEditingDataSet(source); + } + + private void setDsMap() { + dsMap = DesignTableDataManager.getAllDataSetIncludingProcedure(resMap); + } + + + + /** + * 向resMap中添加TableData信息 + * @param name 数据集名字 + * @param templateTableDataWrappe 数据集 + */ + public void putTableDataIntoMap(String name, TemplateTableDataWrapper templateTableDataWrappe) { + if (dsMap.containsKey(name)) { + return; + } + this.addItem(templateTableDataWrappe); + dsMap.put(name, templateTableDataWrappe); + } + + public void setSelectedTableDataByName(String name) { + TableDataWrapper tableDataWrappe = dsMap.get(name) == null? dsMap.get(name + "_P_CURSOR") : dsMap.get(name); + this.getModel().setSelectedItem(tableDataWrappe); + } + + @Override + public TableDataWrapper getSelectedItem() { + if (dataModel.getSelectedItem() instanceof TableDataWrapper) { + return (TableDataWrapper)dataModel.getSelectedItem(); + } + return null; + } + + //august:addElement方法竟然会fireItemStateChanged,蛋疼 + @Override + protected void fireItemStateChanged(ItemEvent e) { + if (!refresModel) { + super.fireItemStateChanged(e); + } + } + + /** + *注册listener,相应数据集改变 + */ + public void registerDSChangeListener() { + DesignTableDataManager.addDsChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + TableDataComboBox.this.refresh(DesignTableDataManager.getEditingTableDataSource()); + } + }); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataCreatorProducer.java b/designer_base/src/com/fr/design/data/datapane/TableDataCreatorProducer.java new file mode 100644 index 0000000000..5f60be6b94 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataCreatorProducer.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.data.datapane; + +import com.fr.data.impl.*; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.data.tabledata.tabledatapane.*; +import com.fr.design.fun.TableDataCreatorProvider; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author : richie + * @since : 8.0 + */ +public class TableDataCreatorProducer { + + private static TableDataCreatorProducer ourInstance = new TableDataCreatorProducer(); + + public static TableDataCreatorProducer getInstance() { + return ourInstance; + } + + private TableDataCreatorProducer() { + + } + + public TableDataNameObjectCreator[] createReportTableDataCreator() { + TableDataNameObjectCreator dataBase = new TableDataNameObjectCreator(Inter.getLocText("DS-Database_Query"), + "ds", + "/com/fr/design/images/data/database.png", DBTableData.class, DBTableDataPane.class); + TableDataNameObjectCreator ds_Class = new TableDataNameObjectCreator(Inter.getLocText("DS-Class"), + "/com/fr/design/images/data/source/classTableData.png", ClassTableData.class, ClassTableDataPane.class); + TableDataNameObjectCreator table = new TableDataNameObjectCreator(Inter.getLocText("DS-Embedded_TableData"), + "Embedded", + "/com/fr/design/images/data/dataTable.png", EmbeddedTableData.class, EmbeddedTableDataPane.class); + TableDataNameObjectCreator multiTable = new TableDataNameObjectCreator(Inter.getLocText("DS-Relation_TableData"), + "Multi", + "/com/fr/design/images/data/multi.png", ConditionTableData.class, MultiTDTableDataPane.class) { + public boolean isNeedParameterWhenPopulateJControlPane() { + return true; + } + }; + TableDataNameObjectCreator fileTable = new TableDataNameObjectCreator(Inter.getLocText(new String[]{"File", "DS-TableData"}), + "File", + "/com/fr/design/images/data/file.png", FileTableData.class, FileTableDataSmallHeightPane.class); + TableDataNameObjectCreator treeTable = new TableDataNameObjectCreator(Inter.getLocText(new String[]{"Tree", "DS-TableData"}), + "Tree", + "/com/fr/design/images/data/tree.png", RecursionTableData.class, TreeTableDataPane.class) { + public boolean isNeedParameterWhenPopulateJControlPane() { + return true; + } + }; + TableDataNameObjectCreator storeProcedure = new TableDataNameObjectCreator(Inter.getLocText("Datasource-Stored_Procedure"), + "Proc", + "/com/fr/design/images/data/store_procedure.png", + StoreProcedure.class, ProcedureDataPane.class) { + public boolean shouldInsertSeparator() { + return true; + } + }; + TableDataNameObjectCreator[] creators = new TableDataNameObjectCreator[]{dataBase, ds_Class, table, fileTable, storeProcedure, multiTable, treeTable}; + return merge(creators, ExtraDesignClassManager.getInstance().getReportTableDataCreators()); + } + + public TableDataNameObjectCreator[] createServerTableDataCreator() { + TableDataNameObjectCreator dataBase = new TableDataNameObjectCreator(Inter.getLocText("DS-Database_Query"), "/com/fr/design/images/data/dock/serverdatabase.png", DBTableData.class, + DBTableDataPane.class); + TableDataNameObjectCreator ds_Class = new TableDataNameObjectCreator(Inter.getLocText("DS-Class"), "/com/fr/design/images/data/dock/serverclasstabledata.png", ClassTableData.class, + ClassTableDataPane.class); + TableDataNameObjectCreator table = new TableDataNameObjectCreator(Inter.getLocText("DS-Embedded_TableData"), "/com/fr/design/images/data/dock/serverdatatable.png", EmbeddedTableData.class, + EmbeddedTableDataPane.class); + TableDataNameObjectCreator fileTable = new TableDataNameObjectCreator(Inter.getLocText(new String[]{"File", "DS-TableData"}), "/com/fr/design/images/data/file.png", FileTableData.class, + FileTableDataSmallPane.class); + + TableDataNameObjectCreator treeTable = new TableDataNameObjectCreator(Inter.getLocText(new String[]{"Tree", "DS-TableData"}), "/com/fr/design/images/data/tree.png", + RecursionTableData.class, GlobalTreeTableDataPane.class) { + public boolean isNeedParameterWhenPopulateJControlPane() { + return true; + } + }; + TableDataNameObjectCreator multiTable = new TableDataNameObjectCreator(Inter.getLocText("DS-Relation_TableData"), "/com/fr/design/images/data/multi.png", + ConditionTableData.class, GlobalMultiTDTableDataPane.class) { + public boolean isNeedParameterWhenPopulateJControlPane() { + return true; + } + }; + TableDataNameObjectCreator storeProcedure = new TableDataNameObjectCreator(Inter.getLocText("Datasource-Stored_Procedure"), "/com/fr/design/images/data/store_procedure.png", + StoreProcedure.class, ProcedureDataPane.class) { + public boolean shouldInsertSeparator() { + return true; + } + }; + + TableDataNameObjectCreator[] creators = new TableDataNameObjectCreator[]{dataBase, ds_Class, table, fileTable, storeProcedure, multiTable, treeTable}; + + TableDataCreatorProvider creatorProvider = ExtraDesignClassManager.getInstance().getTableDataCreatorProvider(); + if (creatorProvider != null) { + return creatorProvider.produceServerTableDataCreator(creators); + } + return merge(creators, ExtraDesignClassManager.getInstance().getServerTableDataCreators()); + } + + private TableDataNameObjectCreator[] merge(TableDataNameObjectCreator[] creators, TableDataNameObjectCreator[] extraCreators) { + if (ArrayUtils.isEmpty(extraCreators)) { + return creators; + } + List list = new ArrayList<>(); + List coverIndexList = new ArrayList<>(); + List coverCreators = new ArrayList<>(); + for (TableDataNameObjectCreator ex : extraCreators) { + int index = ArrayUtils.indexOf(creators, ex); + // 说明已经存在了一个同类型的数据集,需要用插件的覆盖掉原先的 + if (index != ArrayUtils.INDEX_NOT_FOUND) { + // 需要替换到列表里的 + coverIndexList.add(index); + coverCreators.add(ex); + } else { + // 需要添加到列表中去的 + list.add(ex); + } + } + for (int i = 0; i < coverIndexList.size(); i ++) { + creators[coverIndexList.get(i)] = coverCreators.get(i); + } + return (TableDataNameObjectCreator[])ArrayUtils.addAll(creators, list.toArray(new TableDataNameObjectCreator[list.size()])); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataListPane.java b/designer_base/src/com/fr/design/data/datapane/TableDataListPane.java new file mode 100644 index 0000000000..8de293f292 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataListPane.java @@ -0,0 +1,261 @@ +package com.fr.design.data.datapane; + +import com.fr.base.TableData; +import com.fr.data.TableDataSource; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.gui.controlpane.JControlPane; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; +import com.fr.stable.core.PropertyChangeAdapter; + +import javax.swing.*; +import java.util.*; + +/** + * TableDataList Pane. + */ +public class TableDataListPane extends JControlPane { + private Map dsNameChangedMap = new HashMap(); + private boolean isNamePermitted = true; + + public TableDataListPane() { + super(); + dsNameChangedMap.clear(); + this.addEditingListner(new PropertyChangeAdapter() { + @Override + public void propertyChange() { + isNamePermitted = true; + TableDataSource source = DesignTableDataManager.getEditingTableDataSource(); + String[] allDSNames = DesignTableDataManager.getAllDSNames(source); + String[] allListNames = nameableList.getAllNames(); + allListNames[nameableList.getSelectedIndex()] = StringUtils.EMPTY; + String tempName = getEditingName(); + Object editingType = getEditingType(); + if (StringUtils.isEmpty(tempName)) { + String[] warning = new String[]{"NOT_NULL_Des", "Please_Rename"}; + String[] sign = new String[]{",", "!"}; + isNamePermitted = false; + nameableList.stopEditing(); + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataListPane.this), Inter.getLocText(warning, sign)); + setWarnigText(editingIndex); + return; + } + + if (!ComparatorUtils.equals(tempName, selectedName) + && isNameRepeted(new List[]{Arrays.asList(allDSNames), Arrays.asList(allListNames)}, tempName)) { + String[] waning = new String[]{"already_exists", "TableData", "Please_Rename"}; + String[] sign = new String[]{"", tempName + ",", "!"}; + isNamePermitted = false; + nameableList.stopEditing(); + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataListPane.this), Inter.getLocText(waning, sign)); + setWarnigText(editingIndex); + } else if (editingType instanceof StoreProcedure && isIncludeUnderline(tempName)) { + String[] datasource_underline = new String[]{"Datasource-Stored_Procedure", "Name", "can_not_include_underline"}; + String[] sign = new String[]{"", "", "!"}; + isNamePermitted = false; + nameableList.stopEditing(); + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(TableDataListPane.this), Inter.getLocText(datasource_underline, sign)); + setWarnigText(editingIndex); + } + if (nameableList.getSelectedValue() instanceof ListModelElement) { + Nameable selected = ((ListModelElement) nameableList.getSelectedValue()).wrapper; + if (!ComparatorUtils.equals(tempName, selected.getName())) { + rename(selected.getName(), tempName); + + } + } + } + }); + } + + protected void rename(String oldName, String newName) { + dsNameChangedMap.put(oldName, newName); + } + + /** + * 名字是否允许 + * + * @return 是/否 + */ + public boolean isNamePermitted() { + return isNamePermitted; + } + + + /** + * 检查按钮可用状态 Check button enabled. + */ + public void checkButtonEnabled() { + super.checkButtonEnabled(); + isNamePermitted = !isContainsRename(); + } + + private boolean isIncludeUnderline(String name) { + return ComparatorUtils.equals(name.indexOf(StoreProcedure.SPLIT), -1) ? false : true; + } + + /** + * 创建服务器数据集所需要的NameableCreator数组 + * + * @return 数组 + */ + public NameableCreator[] createNameableCreators() { + return TableDataCreatorProducer.getInstance().createServerTableDataCreator(); + } + + + // 只能保证当前模板不重名了 + + /** + * 新建不重名的面板 + * + * @param prefix 前缀字符 + * @return 生成的名字 + */ + @Override + public String createUnrepeatedName(String prefix) { + TableDataSource source = DesignTableDataManager.getEditingTableDataSource(); + if (source == null) { + return super.createUnrepeatedName(prefix); + } + String[] allDsNames = DesignTableDataManager.getAllDSNames(source); + DefaultListModel model = this.getModel(); + Nameable[] all = new Nameable[model.getSize()]; + for (int i = 0; i < model.size(); i++) { + all[i] = ((ListModelElement) model.get(i)).wrapper; + } + // richer:生成的名字从1开始. kunsnat: 添加属性从0开始. + int count = all.length + 1; + while (true) { + String name_test = prefix + count; + boolean repeated = false; + for (int i = 0, len = model.size(); i < len; i++) { + Nameable nameable = all[i]; + if (ComparatorUtils.equals(nameable.getName(), name_test)) { + repeated = true; + break; + } + } + for (String dsname : allDsNames) { + if (ComparatorUtils.equals(dsname, name_test)) { + repeated = true; + break; + } + } + + if (!repeated) { + return name_test; + } + + count++; + } + } + + @Override + protected String title4PopupWindow() { + return "TableData"; + } + + /** + * Populate. + */ + public void populate(TableDataSource tds) { + List nameObjectList = new ArrayList(); + + Iterator tableDataNameIterator = tds.getTableDataNameIterator(); + while (tableDataNameIterator.hasNext()) { + String tableDataName = (String) tableDataNameIterator.next(); + TableData tableData = tds.getTableData(tableDataName); + + if (tableData != null) { + nameObjectList.add(new NameObject(tableDataName, tableData)); + } + } + + populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); + } + + /** + * Populate. + */ + public void populate(DatasourceManagerProvider datasourceManager) { + Iterator nameIt = datasourceManager.getTableDataNameIterator(); + Iterator procedurenameIt = datasourceManager.getProcedureNameIterator(); + List nameObjectList = new ArrayList(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + nameObjectList.add(new NameObject(name, datasourceManager.getTableData(name))); + } + while (procedurenameIt.hasNext()) { + String name = procedurenameIt.next(); + nameObjectList.add(new NameObject(name, datasourceManager.getProcedureByName(name))); + } + + populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); + } + + public void update(DatasourceManagerProvider datasourceManager) { + datasourceManager.clearAllTableData(); + datasourceManager.clearAllProcedure(); + Nameable[] tableDataArray = this.update(); + for (int i = 0; i < tableDataArray.length; i++) { + NameObject nameObject = (NameObject) tableDataArray[i]; + datasourceManager.putTableData(nameObject.getName(), (TableData) nameObject.getObject()); + } + } + + public void update(TableDataSource tds) { + tds.clearAllTableData(); + + Nameable[] tableDataArray = this.update(); + for (int i = 0; i < tableDataArray.length; i++) { + NameObject nameObject = (NameObject) tableDataArray[i]; + tds.putTableData(nameObject.getName(), (TableData) nameObject.getObject()); + } + } + + /** + * 判断数据集是否重名 + */ + public void checkValid() throws Exception { + List exsitTableDataNameList = new ArrayList(); + // _denny: 判断是否有重复的数据集名 + checkRepeatedDSName(exsitTableDataNameList); + + Nameable[] tableDataArray = this.update(); + for (int i = 0; i < tableDataArray.length; i++) { + NameObject nameObject = (NameObject) tableDataArray[i]; + + if (exsitTableDataNameList.contains(nameObject.getName())) { + String[] waring = new String[]{"TableData", "Error_TableDataNameRepeat"}; + String[] sign = new String[]{": " + nameObject.getName()}; + throw new Exception(Inter.getLocText(waring, sign)); + } + + exsitTableDataNameList.add(nameObject.getName()); + } + } + + protected void checkRepeatedDSName(List exsitTableDataNameList) { + } + + /** + * 在JJControlPane的左侧Tree里面选中某一Item + * + * @param name 被选择的Item名称 + */ + public void selectName(String name) { + this.setSelectedName(name); + } + + public Map getDsNameChangedMap() { + return this.dsNameChangedMap; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataNameObjectCreator.java b/designer_base/src/com/fr/design/data/datapane/TableDataNameObjectCreator.java new file mode 100644 index 0000000000..12d5e885b4 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataNameObjectCreator.java @@ -0,0 +1,178 @@ +package com.fr.design.data.datapane; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.data.impl.DBTableData; +import com.fr.design.actions.tabledata.TableDataAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.icon.WarningIcon; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.text.Collator; +import java.util.*; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-20 + * Time: 上午9:55 + */ +public class TableDataNameObjectCreator extends NameObjectCreator { + private boolean b = false; + private Image menuImage; + private String iconPath; + private boolean isNeedInsertSeparator = false; + private String prefix = ""; + private java.util.List names = new ArrayList(); + + public TableDataNameObjectCreator(TableDataAction action) { + super(action.getDisplayName(), action.getIconPath(), action.getTableDataClass(), action.getUpdateTableDataPaneClass()); + this.iconPath = action.getIconPath(); + menuImage = BaseUtils.readImage(iconPath); + isNeedInsertSeparator = action.isNeedInsertSeparator(); + prefix = action.getPrefix(); + } + + public TableDataNameObjectCreator(TableDataAction action, Class clazz4Init) { + super(action.getDisplayName(), action.getIconPath(), action.getTableDataClass(), clazz4Init, action.getUpdateTableDataPaneClass()); + isNeedInsertSeparator = action.isNeedInsertSeparator(); + prefix = action.getPrefix(); + } + + public TableDataNameObjectCreator(String menuName, String iconPath, Class clazz, Class updatePane) { + super(menuName, iconPath, clazz, updatePane); + if (iconPath != null) { + this.iconPath = iconPath; + menuImage = BaseUtils.readImage(iconPath); + } + } + + public TableDataNameObjectCreator(String menuName, String prefix, String iconPath, Class clazz, Class updatePane) { + super(menuName, iconPath, clazz, updatePane); + if (iconPath != null) { + this.iconPath = iconPath; + menuImage = BaseUtils.readImage(iconPath); + } + this.prefix = prefix; + } + + public TableDataNameObjectCreator(String menuName, String iconPath, Class clazz, Class clazz4Init, Class updatePane) { + super(menuName, iconPath, clazz, clazz4Init, updatePane); + if (iconPath != null) { + this.iconPath = iconPath; + menuImage = BaseUtils.readImage(iconPath); + } + } + + public TableDataNameObjectCreator(String menuName, String prefix, String iconPath, Class clazz, Class clazz4Init, Class updatePane) { + super(menuName, iconPath, clazz, clazz4Init, updatePane); + if (iconPath != null) { + this.iconPath = iconPath; + menuImage = BaseUtils.readImage(iconPath); + } + this.prefix = prefix; + } + + + @Override + protected void doSthChanged4Icon(Object ob) { + if (ob instanceof DBTableData) { + DBTableData db = (DBTableData) ob; + b = StringUtils.isBlank(db.getQuery()); + } + } + + /** + * 取得菜单的图片 + * + * @return 图片 + */ + public Icon menuIcon() { + return createMenuIcon(); + } + + public String getIconPath() { + return iconPath; + } + + private Icon createMenuIcon() { + return b ? new WarningIcon(this.menuImage) : this.menuIcon; + } + + /** + * 创建提示 + * + * @return 提示 + */ + public String createTooltip() { + return b ? Inter.getLocText("Connect_SQL_Cannot_Null") : null; + } + + public String getPrefix() { + return StringUtils.isNotBlank(prefix) ? prefix : menuName(); + } + + /** + * 将names排序 + * + * @return + */ + public List getNames() { + String[] namearray = names.toArray(ArrayUtils.EMPTY_STRING_ARRAY); + Arrays.sort(namearray, Collator.getInstance(java.util.Locale.CHINA)); + return Arrays.asList(namearray); + } + + public Object createObject() { + try { + return clazzOfObject.newInstance(); + } catch (InstantiationException e) { + try { + return clazzOfInitCase.newInstance(); + } catch (InstantiationException | IllegalAccessException e1) { + FRContext.getLogger().error(e.getMessage(), e); + } + } catch (IllegalAccessException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return null; + } + + /** + * 加入名字 + * + * @param names 名字 + */ + public void addNames(String names) { + this.names.add(names); + } + + /** + * 清除 + */ + public void clear() { + this.names.clear(); + } + + public boolean shouldInsertSeparator() { + return false; + } + + public boolean equals(Object obj) { + return obj instanceof TableDataNameObjectCreator + && ComparatorUtils.equals(menuName, ((TableDataNameObjectCreator) obj).menuName); + } + + @Override + public int hashCode() { + return menuName == null ? 0 : menuName.hashCode(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataSourceOP.java b/designer_base/src/com/fr/design/data/datapane/TableDataSourceOP.java new file mode 100644 index 0000000000..03ed0dfbb6 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataSourceOP.java @@ -0,0 +1,236 @@ +package com.fr.design.data.datapane; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.fr.general.NameObject; +import com.fr.base.StoreProcedureParameter; +import com.fr.base.TableData; +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.TableDataSource; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.data.impl.storeproc.StoreProcedureConstants; +import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper; +import com.fr.design.data.tabledata.wrapper.StoreProcedureNameWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.DesignModelAdapter; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.gui.itree.refreshabletree.UserObjectOP; +import com.fr.general.Inter; + +/** + * 数据集树的操作 + * + * @editor zhou + * @since 2012-3-28下午9:58:53 + */ +public class TableDataSourceOP implements UserObjectOP { + public static final int TEMPLATE_TABLE_DATA = 0; + public static final int SERVER_TABLE_DATA = 1; + public static final int STORE_PRECEDURE_DATA = 2; + public static int dataMode = -1; + + private DesignModelAdapter tc; + + + public TableDataSourceOP(DesignModelAdapter tc) { + this.tc = tc; + } + + /** + * 初始化数据集的list + * + * @return + */ + @Override + public List> init() { + if (tc != null) { + return DesignTableDataManager.getEditingDataSet(tc.getBook()); + } + List> empty = new ArrayList>(); + empty.add(Collections.emptyMap());//数据集 + empty.add(Collections.emptyMap());//服务器数据集 + empty.add(Collections.emptyMap());//存储过程 + return empty; + } + + /** + * ButtonEnabled intercept + * @return interceptbuttonEnabled + */ + @Override + public boolean interceptButtonEnabled() { + return tc == null; + } + + /** + * 移除名字是name的TableData + * @param name tabledata name + */ + public void removeAction(String name) { + if (tc != null) { + TableDataSource tds = tc.getBook(); + tds.removeTableData(name); + + tc.fireTargetModified(); + } + } + + private ExpandMutableTreeNode[] getNodeArrayFromMap(Map map) { + List dataList = new ArrayList(); + Iterator> entryIt = map.entrySet().iterator(); + while (entryIt.hasNext()) { + Entry entry = entryIt.next(); + String name = entry.getKey(); + TableDataWrapper t = entry.getValue(); + + ExpandMutableTreeNode newChildTreeNode = new ExpandMutableTreeNode(new NameObject(name, t)); + dataList.add(newChildTreeNode); + newChildTreeNode.add(new ExpandMutableTreeNode()); + } + return dataList.toArray(new ExpandMutableTreeNode[dataList.size()]); + } + + private ExpandMutableTreeNode initTemplateDataNode(Map templateDataMap) { + ExpandMutableTreeNode templateNode = new ExpandMutableTreeNode(new NameObject(Inter.getLocText("DS-TableData"), TEMPLATE_TABLE_DATA), true); + templateNode.addChildTreeNodes(getNodeArrayFromMap(templateDataMap)); + return templateNode; + } + + private ExpandMutableTreeNode initServerDataNode(Map serverDataMap) { + ExpandMutableTreeNode templateNode = new ExpandMutableTreeNode(new NameObject(Inter.getLocText("DS-Server_TableData"), SERVER_TABLE_DATA), false); + templateNode.addChildTreeNodes(getNodeArrayFromMap(serverDataMap)); + return templateNode; + } + + private ExpandMutableTreeNode initStoreProcedureNode(Map storeProcedureMap) { + ExpandMutableTreeNode templateNode = new ExpandMutableTreeNode(new NameObject(Inter.getLocText("Datasource-Stored_Procedure"), STORE_PRECEDURE_DATA), false); + templateNode.addChildTreeNodes(getNodeArrayFromMap(storeProcedureMap)); + return templateNode; + } + + /** + * 根据不同模式生成子节点 + * + * @return + */ + @Override + public ExpandMutableTreeNode[] load() { + Map templateDataMap = null; + Map serverDataMap = null; + Map storeProcedureMap = null; + + if (this != null) { + templateDataMap = this.init().get(0); + serverDataMap = this.init().get(1); + storeProcedureMap = this.init().get(2); + } else { + templateDataMap = Collections.emptyMap(); + serverDataMap = Collections.emptyMap(); + storeProcedureMap = Collections.emptyMap(); + } + List list = new ArrayList(); //所有的数据集 + List templist = new ArrayList(); //模板数据集 + List serverlist = new ArrayList(); //服务器数据集 + + list.add(initTemplateDataNode(templateDataMap)); + addNodeToList(templateDataMap, templist); + if (!serverDataMap.isEmpty()) { + list.add(initServerDataNode(serverDataMap)); + addNodeToList(serverDataMap, serverlist); + } + if (!storeProcedureMap.isEmpty()) { + list.add(initStoreProcedureNode(storeProcedureMap)); + for (int i = 0; i < getNodeArrayFromMap(storeProcedureMap).length; i++) { + ExpandMutableTreeNode tmpNode = getNodeArrayFromMap(storeProcedureMap)[i]; + if (((NameObject) tmpNode.getUserObject()).getObject() instanceof StoreProcedureNameWrapper) { + TableData tableData = ((StoreProcedureNameWrapper) (((NameObject) tmpNode.getUserObject()).getObject())).getStoreProcedure(); + setStoreProcedureTree(tableData, tmpNode); + serverlist.add(tmpNode); + } + } + } + switch (dataMode) { + case TEMPLATE_TABLE_DATA: + return templist.toArray(new ExpandMutableTreeNode[templist.size()]); + case SERVER_TABLE_DATA: + return serverlist.toArray(new ExpandMutableTreeNode[serverlist.size()]); + default: + return list.toArray(new ExpandMutableTreeNode[list.size()]); + } + } + + private void addNodeToList(Map dataMap, List dataList) { + for (int i = 0; i < getNodeArrayFromMap(dataMap).length; i++) { + ExpandMutableTreeNode tmpNode = getNodeArrayFromMap(dataMap)[i]; + TableData tableData = ((TableDataWrapper) (((NameObject) tmpNode.getUserObject()).getObject())).getTableData(); + if (tableData instanceof StoreProcedure) { + setStoreProcedureTree(tableData, tmpNode); + dataList.add(tmpNode); + } else { + dataList.add(tmpNode); + } + } + } + + private void setStoreProcedureTree(TableData tableData, ExpandMutableTreeNode tmpNode) { + ArrayList nodeName = new ArrayList(); + StoreProcedure storeProcedure = (StoreProcedure) tableData; + String name = ((NameObject) tmpNode.getUserObject()).getName(); + StoreProcedureParameter[] parameters = StoreProcedure.getSortPara(storeProcedure.getParameters()); + ArrayList resultNames = storeProcedure.getResultNames(); + boolean hasChild = false; + tmpNode.remove(0); + TableDataWrapper tdw = new StoreProcedureNameWrapper(name + "_Table1", storeProcedure); + ExpandMutableTreeNode childNode = new ExpandMutableTreeNode(new NameObject("Table", tdw)); + childNode.add(new ExpandMutableTreeNode()); + tmpNode.add(childNode); + for (StoreProcedureParameter parameter : parameters) { + if (parameter.getSchema() != StoreProcedureConstants.IN) { + if (!nodeName.contains(parameter.getName())) { + nodeName.add(parameter.getName()); + hasChild = true; + String parameterName = name + "_" + parameter.getName(); + TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false); + ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(parameter.getName(), newTwd)); + newChildNode.add(new ExpandMutableTreeNode()); + tmpNode.add(newChildNode); + } + } + } + + if (!resultNames.isEmpty()) { + for (int i = 0; i < resultNames.size(); i++) { + if (!nodeName.contains(resultNames.get(i))) { + nodeName.add(resultNames.get(i)); + hasChild = true; + String parameterName = name + "_" + resultNames.get(i); + TableDataWrapper newTwd = new StoreProcedureDataWrapper(storeProcedure, name, parameterName, false); + ExpandMutableTreeNode newChildNode = new ExpandMutableTreeNode(new NameObject(resultNames.get(i), newTwd)); + newChildNode.add(new ExpandMutableTreeNode()); + tmpNode.add(newChildNode); + } + + } + + } + + if (hasChild) { + tmpNode.remove(0); + } + } + + + protected void setDataMode(int i) { + this.dataMode = i; + } + + protected int getDataMode() { + return dataMode; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataTree.java b/designer_base/src/com/fr/design/data/datapane/TableDataTree.java new file mode 100644 index 0000000000..2b2238a9d1 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataTree.java @@ -0,0 +1,244 @@ +package com.fr.design.data.datapane; + +import com.fr.base.BaseUtils; +import com.fr.general.NameObject; +import com.fr.design.constants.UIConstants; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.gui.itree.refreshabletree.UserObjectRefreshJTree; +import com.fr.design.icon.IconPathConstants; +import com.fr.general.ComparatorUtils; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import java.awt.*; + +/** + * TableData Tree + */ +public class TableDataTree extends UserObjectRefreshJTree { + private static final long serialVersionUID = 1L; + + /** + * Constructor. + */ + public TableDataTree() { + super(); + this.setCellRenderer(tableDataTreeCellRenderer); + this.setEditable(false); + } + + // CellRenderer + private DefaultTreeCellRenderer tableDataTreeCellRenderer = new DefaultTreeCellRenderer() { + private static final long serialVersionUID = 1L; + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) value; + Object userObj = treeNode.getUserObject(); + if (userObj instanceof String) { + // p:这个是column field. + this.setIcon(BaseUtils.readIcon("com/fr/design/images/data/field.png")); + this.setText((String) userObj); + } else if (userObj instanceof NameObject) { + NameObject nameObject = (NameObject) userObj; + this.setText(nameObject.getName()); + if (nameObject.getObject() instanceof TableDataWrapper) { + TableDataWrapper tableDataWrappe = (TableDataWrapper) nameObject.getObject(); + this.setIcon(tableDataWrappe.getIcon()); + } else if (nameObject.getObject() instanceof Integer) { + int num = (Integer) nameObject.getObject(); + if (num == TableDataSourceOP.SERVER_TABLE_DATA) { + this.setIcon(BaseUtils.readIcon(IconPathConstants.STD_SHOW_ICON_PATH)); + } else if (num == TableDataSourceOP.STORE_PRECEDURE_DATA) { + this.setIcon(BaseUtils.readIcon(IconPathConstants.SP_SHOW_ICON_PATH)); + } else { + this.setIcon(BaseUtils.readIcon(IconPathConstants.DS_QUERY_ICON_PATH)); + } + } else { + this.setIcon(BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png")); + } + } else if (userObj == PENDING) { + this.setIcon(null); + this.setText(PENDING.toString()); + } + // 这里新建一个Label作为render是因为JTree在动态刷新的时候,节点上render画布的的宽度不会变,会使得一部分比较长的数据显示为"..." + UILabel label = new UILabel(); + label.setText(getText()); + label.setIcon(getIcon()); + Dimension dim = label.getPreferredSize(); + dim.height += 2; + this.setSize(dim); + this.setPreferredSize(dim); + this.setBackgroundNonSelectionColor(UIConstants.NORMAL_BACKGROUND); + this.setForeground(UIConstants.FONT_COLOR); + this.setBackgroundSelectionColor(UIConstants.FLESH_BLUE); + return this; + } + }; + + + protected void refreshTreeNode(ExpandMutableTreeNode eTreeNode, String childName) { + if (interceptRefresh(eTreeNode)) { + return; + } + boolean refreshall = childName.isEmpty(); + ExpandMutableTreeNode[] new_nodes = loadChildTreeNodes(eTreeNode); + + java.util.List childTreeNodeList = new java.util.ArrayList(); + for (int i = 0, len = eTreeNode.getChildCount(); i < len; i++) { + if (eTreeNode.getChildAt(i) instanceof ExpandMutableTreeNode) { + childTreeNodeList.add((ExpandMutableTreeNode) eTreeNode.getChildAt(i)); + } else { + childTreeNodeList.add((DefaultMutableTreeNode) eTreeNode.getChildAt(i)); + } + } + + eTreeNode.removeAllChildren(); + + for (int ci = 0; ci < new_nodes.length; ci++) { + Object cUserObject = new_nodes[ci].getUserObject(); + ExpandMutableTreeNode cTreeNode = null; + for (int ni = 0, nlen = childTreeNodeList.size(); ni < nlen; ni++) { + cTreeNode = (ExpandMutableTreeNode) childTreeNodeList.get(ni); + if (ComparatorUtils.equals(cTreeNode.getUserObject(), cUserObject)) { + if (!refreshall && !ComparatorUtils.equals(childName, ((NameObject) cUserObject).getName())) { + new_nodes[ci] = cTreeNode; + break; + } + new_nodes[ci].setExpanded(cTreeNode.isExpanded()); + if (cTreeNode.getFirstChild() instanceof ExpandMutableTreeNode && cTreeNode.isExpanded()) { + checkChildNodes(cTreeNode, new_nodes[ci]); + } + break; + } + } + + eTreeNode.add(new_nodes[ci]); + } + } + + + protected void checkChildNodes(ExpandMutableTreeNode oldNode, ExpandMutableTreeNode newNode) { + for (int i = 0; i < oldNode.getChildCount(); i++) { + ExpandMutableTreeNode oldChild = (ExpandMutableTreeNode) oldNode.getChildAt(i); + for (int j = 0; j < newNode.getChildCount(); j++) { + ExpandMutableTreeNode newChild = (ExpandMutableTreeNode) newNode.getChildAt(j); + newChild.removeAllChildren(); + ExpandMutableTreeNode[] nodes = TableDataTree.this.loadChildTreeNodes(newChild); + for (int k = 0; k < nodes.length; k++) { + newChild.add(nodes[k]); + } + if (newChild.getChildCount() > 1 && ((ExpandMutableTreeNode) newChild.getFirstChild()).getUserObject() == PENDING) { + newChild.remove(0); + } + if (ComparatorUtils.equals(oldChild.getUserObject(), newChild.getUserObject())) { + newChild.setExpanded(oldChild.isExpanded()); + } + } + } + } + + /* + * p:获得选中的NameObject = name + tabledata. + */ + public NameObject getSelectedNameObject() { + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath == null) { + return null; + } + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + Object parentUserObject = parentTreeNode.getUserObject(); + if (parentUserObject instanceof NameObject && ((NameObject) parentUserObject).getObject() instanceof Integer) { + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + } else { + parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + parentUserObject = parentTreeNode.getUserObject(); + + if (parentUserObject != null) { + if (!(parentUserObject instanceof NameObject)) { + return (NameObject) selectedUserObject; + } else { + return (NameObject) parentUserObject; + } + } + } + return null; + + } + + public TableDataWrapper[] getSelectedDatas() { + TreePath[] selectedTreePaths = this.getSelectionPaths(); + if (selectedTreePaths == null || selectedTreePaths.length == 0) { + return null; + } + TableDataWrapper[] nameobjs = new TableDataWrapper[selectedTreePaths.length]; + for (int i = 0; i < selectedTreePaths.length; i++) { + TreePath selectedTreePath = selectedTreePaths[i]; + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + Object parentUserObject = parentTreeNode.getUserObject(); + if (parentUserObject instanceof NameObject && ((NameObject) parentUserObject).getObject() instanceof Integer) { + if (selectedUserObject instanceof NameObject) { + Object obj = ((NameObject) selectedUserObject).getObject(); + if (obj instanceof TableDataWrapper) { + nameobjs[i] = (TableDataWrapper) obj; + } + } + } else { + return new TableDataWrapper[0]; + } + } + + return nameobjs; + } + + public NameObject getRealSelectedNameObject() { + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath == null) { + return null; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + + selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + return null; + } + + /** + * p:添加一个NameObject节点. + */ + public void addNameObject(NameObject no) { + if (no == null) { + return; + } + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + + // 新建一个放着NameObject的newChildTreeNode,加到Root下面 + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + + ExpandMutableTreeNode newChildTreeNode = new ExpandMutableTreeNode(no); + root.add(newChildTreeNode); + newChildTreeNode.add(new ExpandMutableTreeNode()); + + treeModel.reload(root); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataTreeDragSource.java b/designer_base/src/com/fr/design/data/datapane/TableDataTreeDragSource.java new file mode 100644 index 0000000000..36d1b5d763 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataTreeDragSource.java @@ -0,0 +1,102 @@ +package com.fr.design.data.datapane; + +import java.awt.Component; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JTree; +import javax.swing.tree.TreePath; + +import com.fr.general.NameObject; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.mainframe.dnd.ArrayTransferable; + +/** + * 从数据源树开始drag. + */ +public class TableDataTreeDragSource extends DragSourceAdapter implements DragGestureListener { + private DragSource source; + private String[][] doubleArray; + public TableDataTreeDragSource(JTree tree, int actions) { + source = new DragSource(); + source.createDefaultDragGestureRecognizer(tree, actions, this); + } + + /* + * Drag Gesture Handler + */ + public void dragGestureRecognized(DragGestureEvent dge) { + Component comp = dge.getComponent(); + if (comp instanceof TableDataTree) { + + List stringList = new ArrayList(); + TableDataTree tree = (TableDataTree) comp; + + TreePath[] paths = tree.getSelectionPaths(); + if (paths == null) { + return; + } + doubleArray = null; + setnameArray(paths, stringList); + + source.startDrag(dge, DragSource.DefaultLinkDrop, new ArrayTransferable(doubleArray), this); + } + } + + private void setnameArray(TreePath[] paths, List stringList) { + for (int i = 0; i < paths.length; i++) { + if ((paths[i] == null) || (paths[i].getPathCount() <= 1)) { + return;// We can't move the root node or an empty selection + } + ExpandMutableTreeNode segmentMutableTreeNode = (ExpandMutableTreeNode) paths[i].getLastPathComponent(); + Object userObj = segmentMutableTreeNode.getUserObject(); + List tableAddress = new ArrayList(); + String displayName; + StringBuffer dsNameBuf = new StringBuffer(); + if (userObj instanceof NameObject) { + continue; + } else { + if (!(userObj instanceof String)) { + continue; + } + displayName = (String) userObj; + // james 读取表名 + while (segmentMutableTreeNode.getParent().getParent() != null) { + segmentMutableTreeNode = (ExpandMutableTreeNode) segmentMutableTreeNode.getParent(); + ExpandMutableTreeNode datasheetExpandMutableTreeNode = segmentMutableTreeNode; + Object parentUserObj = datasheetExpandMutableTreeNode.getUserObject(); + if (parentUserObj instanceof NameObject && !(((NameObject) parentUserObj).getObject() instanceof Integer)) { + NameObject nameObject = (NameObject) parentUserObj; + tableAddress.add(nameObject.getName()); + } + } + } + for (int j = tableAddress.size() - 1; j > -1; j--) { + dsNameBuf.append(tableAddress.get(j)); + if (j != 0) { + dsNameBuf.append('_'); + } + } + String dsName; + if (dsNameBuf.toString() != null) { + dsName = dsNameBuf.toString(); + } else { + return; + } + String[] attributes = {dsName, displayName}; + stringList.add(attributes); + Object[] bo = stringList.toArray(); + doubleArray = new String[bo.length][]; + for (int io = 0; io < bo.length; io++) { + if (bo[io] instanceof String[]) { + doubleArray[io] = (String[]) bo[io]; + } + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TableDataTreePane.java b/designer_base/src/com/fr/design/data/datapane/TableDataTreePane.java new file mode 100644 index 0000000000..a0b4fb3bf3 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TableDataTreePane.java @@ -0,0 +1,647 @@ +package com.fr.design.data.datapane; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.TableData; +import com.fr.data.TableDataSource; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.DesignModelAdapter; +import com.fr.design.actions.UpdateAction; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.tabledata.ResponseDataSourceChange; +import com.fr.design.data.tabledata.StoreProcedureWorkerListener; +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.ibutton.UIHeadGroup; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.icon.IconPathConstants; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DockingView; +import com.fr.design.menu.LineSeparator; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.SeparatorDef; +import com.fr.design.menu.ToolBarDef; +import com.fr.general.ComparatorUtils; +import com.fr.general.GeneralContext; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.stable.StringUtils; +import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.stable.plugin.PluginReadListener; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.tree.TreeCellEditor; +import java.awt.*; +import java.awt.dnd.DnDConstants; +import java.awt.event.*; +import java.util.EventObject; +import java.util.HashMap; +import java.util.Map; + +public class TableDataTreePane extends DockingView implements ResponseDataSourceChange { + + private static final int PROCEDURE_NAME_INDEX = 4; + private static final int TEMPLATE_TABLE_DATA = 0; + private static final int SERVER_TABLE_DATA = 1; + private static final long serialVersionUID = -12168467370000617L; + private static TableDataTreePane singleton = new TableDataTreePane(); + private String type = ""; + + /** + * 得到实例 + * + * @param tc + * @return + */ + public synchronized static TableDataTreePane getInstance(DesignModelAdapter tc) { + if (singleton.tc == null) { + singleton.addMenuDef.clearShortCuts(); + singleton.createAddMenuDef(); + } + singleton.tc = tc; + singleton.op = new TableDataSourceOP(tc); + singleton.op.setDataMode(singleton.buttonGroup.getSelectedIndex() == 0 ? TEMPLATE_TABLE_DATA : SERVER_TABLE_DATA); + singleton.refreshDockingView(); + return singleton; + } + + private static TableDataTree dataTree; + private TableDataSourceOP op; + + private MenuDef addMenuDef; + private EditAction editAction; + private RemoveAction removeAction; + private DesignModelAdapter tc; + private PreviewTableDataAction previewTableDataAction; + private ConnectionTableAction connectionTableAction; + private UIHeadGroup buttonGroup; + private String[] allDSNames; + + private TableDataTreePane() { + this.setLayout(new BorderLayout(4, 0)); + this.setBorder(null); + dataTree = new TableDataTree(); + ToolTipManager.sharedInstance().registerComponent(dataTree); + ToolTipManager.sharedInstance().setDismissDelay(3000); + ToolTipManager.sharedInstance().setInitialDelay(0); + addMenuDef = new MenuDef(Inter.getLocText("FR-Action_Add")); + addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + + createAddMenuDef(); + + GeneralContext.addPluginReadListener(new PluginReadListener() { + @Override + public void success() { + addMenuDef.clearShortCuts(); + createAddMenuDef(); + } + }); + + editAction = new EditAction(); + removeAction = new RemoveAction(); + previewTableDataAction = new PreviewTableDataAction(); + connectionTableAction = new ConnectionTableAction(); + ToolBarDef toolbarDef = new ToolBarDef(); + toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction); + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolbarDef.updateToolBar(toolBar); + + JPanel toolbarPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + toolbarPane.add(toolBar, BorderLayout.CENTER); + this.add(toolbarPane, BorderLayout.NORTH); + + UIScrollPane scrollPane = new UIScrollPane(dataTree); + scrollPane.setBorder(null); + initbuttonGroup(); + JPanel jPanel = new JPanel(new BorderLayout(4, 4)); + JPanel buttonPane = new JPanel(new GridLayout()); + buttonPane.add(buttonGroup, BorderLayout.CENTER); + jPanel.add(buttonPane, BorderLayout.NORTH); + jPanel.add(scrollPane, BorderLayout.CENTER); + this.add(jPanel, BorderLayout.CENTER); + dataTree.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + checkButtonEnabled(); + } + }); + dataTree.addKeyListener(getTableTreeNodeListener()); + // TreeCellEditor + dataTree.setEditable(true); + TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField()); + treeCellEditor.addCellEditorListener(treeCellEditor); + dataTree.setCellEditor(treeCellEditor); + new TableDataTreeDragSource(dataTree, DnDConstants.ACTION_COPY); + checkButtonEnabled(); + } + + private KeyAdapter getTableTreeNodeListener() { + return new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + //F2重命名先屏蔽了, 有bug没时间弄 + if (e.getKeyCode() == KeyEvent.VK_F2){ + return; + } + + super.keyPressed(e); + } + + @Override + public void keyReleased(KeyEvent e) { + checkButtonEnabled(); + } + }; + } + + private void createAddMenuDef() { + TableDataNameObjectCreator[] creators = TableDataCreatorProducer.getInstance().createReportTableDataCreator(); + for (final TableDataNameObjectCreator creator : creators) { + if (creator.shouldInsertSeparator()) { + addMenuDef.addShortCut(new LineSeparator()); + } + + addMenuDef.addShortCut(new TDAction() { + @Override + protected String getTDName() { + return creator.menuName(); + } + + @Override + protected Icon getTDIcon() { + return creator.menuIcon(); + } + + @Override + protected String getNamePrefix() { + return creator.getPrefix(); + } + + @Override + protected TemplateTableDataWrapper getTableDataInstance() { + return new TemplateTableDataWrapper((TableData) creator.createObject()); + } + }); + } + } + + private void initbuttonGroup() { + Icon[] iconArray = {BaseUtils.readIcon("/com/fr/design/images/data/datasource.png"), BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png")}; + final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA}; + String[] textArray = {Inter.getLocText(new String[]{"Template", "DS-TableData"}), Inter.getLocText("DS-Server_TableData")}; + buttonGroup = new UIHeadGroup(iconArray, textArray) { + public void tabChanged(int index) { + if (op != null) { + op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); + addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA ? true : false); + refreshDockingView(); + } + + } + }; + buttonGroup.setNeedLeftRightOutLine(false); + } + + /** + * getViewIcon + * + * @return + */ + public Icon getViewIcon() { + return BaseUtils.readIcon(IconPathConstants.DS_ICON_PATH); + } + + /** + * 刷新 + */ + public static void refresh() { + dataTree.refresh(); + } + + private void checkButtonEnabled() { + // august:BUG 9344 + addMenuDef.setEnabled(true); + connectionTableAction.setEnabled(FRContext.getCurrentEnv() != null && FRContext.getCurrentEnv().isRoot()); + if (this.op == null || this.op.interceptButtonEnabled()) { + addMenuDef.setEnabled(false); + editAction.setEnabled(false); + removeAction.setEnabled(false); + previewTableDataAction.setEnabled(false); + return; + } + if (this.op.getDataMode() == SERVER_TABLE_DATA) { + addMenuDef.setEnabled(false); + removeAction.setEnabled(false); + } + int selectioncount = dataTree.getSelectionCount(); + switch (selectioncount) { + case 0: + editAction.setEnabled(false); + removeAction.setEnabled(false); + previewTableDataAction.setEnabled(false); + break; + case 1: + boolean istmp = dataTree.getSelectedNameObject().getObject() instanceof TemplateTableDataWrapper; + editAction.setEnabled(istmp); + removeAction.setEnabled(istmp); + previewTableDataAction.setEnabled(true); + break; + default: + editAction.setEnabled(false); + previewTableDataAction.setEnabled(false); + + } + if (dataTree.getSelectionPath() != null) { + if (((ExpandMutableTreeNode) dataTree.getSelectionPath().getLastPathComponent()).getUserObject() instanceof String) { + previewTableDataAction.setEnabled(false); + editAction.setEnabled(false); + removeAction.setEnabled(false); + } + } + } + + + /** + * 刷新 + */ + public void refreshDockingView() { + populate(new TableDataSourceOP(tc)); + this.checkButtonEnabled(); + } + + /** + * getViewTitle() + * + * @return + */ + public String getViewTitle() { + return Inter.getLocText("FR-Designer_TableData"); + } + + + /** + * 最佳位置 + * + * @return 返回位置 + */ + public Location preferredLocation() { + return Location.WEST_ABOVE; + } + + /** + * 响应数据集改变 + */ + public void fireDSChanged() { + fireDSChanged(new HashMap()); + } + + + /** + * 响应数据集改变 + * + * @param map 数据集变化Map + */ + public void fireDSChanged(Map map) { + DesignTableDataManager.fireDSChanged(map); + } + + private class TableDataTreeCellEditor extends DefaultCellEditor implements TreeCellEditor, CellEditorListener { + + private NameObject editingNO; + private String oldName; + private String newName; + private UITextField jTextField; + + public TableDataTreeCellEditor(final UITextField textField) { + super(textField); + this.jTextField = textField; + } + + @Override + public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { + editingNO = dataTree.getSelectedNameObject(); + + oldName = editingNO.getName(); + + delegate.setValue(oldName); + + if (jTextField != null) { + jTextField.addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + // stopCellEditing 执行过程中会调用到 getCellEditorValue + stopCellEditing(); + } + }); + } + + editorComponent.setPreferredSize(new java.awt.Dimension(TableDataTreePane.this.getPreferredSize().width, editorComponent.getPreferredSize().height)); + + return editorComponent; + } + + @Override + public boolean isCellEditable(EventObject anEvent) { + NameObject no = dataTree.getSelectedNameObject(); + return no != null && anEvent == null; + + } + + @Override + public Object getCellEditorValue() { + newName = super.getCellEditorValue().toString(); + + editingNO.setName(newName); + + // 如果没有重命名成功,则还原成原来的oldName + if (tc != null && !tc.renameTableData(oldName, newName)) { + editingNO.setName(oldName); + } + if (dataTree.isNameRepeated(newName)) { + editingNO.setName(oldName); + } + + return editingNO; + } + + /* + * 下面两个方法是CellEditorListener的 + */ + @Override + public void editingCanceled(ChangeEvent e) { + } + + @Override + public void editingStopped(ChangeEvent e) { + } + } + + + /** + * 编辑面板 + * + * @param uPanel 面板 + * @param originalName 原始名字 + */ + public void dgEdit(final AbstractTableDataPane uPanel, String originalName) { + uPanel.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { + public void fireDoneAction() { + if (dataTree.getSelectionPath() == null) { + dataTree.refresh(); + } else { + Object object = dataTree.getSelectionPath().getLastPathComponent(); + int[] rows = dataTree.getSelectionRows(); + dataTree.refreshChildByName(object.toString()); + dataTree.setSelectionRows(rows); + } + } + }); + final BasicPane.NamePane nPanel = uPanel.asNamePane(); + nPanel.setObjectName(originalName); + final String oldName = originalName; + final BasicDialog dg; + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + dg = nPanel.showLargeWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { + public void doOk() { + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + tc.renameTableData(oldName, nPanel.getObjectName(), false); + TableDataSource tds = tc.getBook(); + TableData td = uPanel.updateBean(); + String tdName = nPanel.getObjectName(); + tds.putTableData(tdName, td); + Map map = new HashMap(); + if (!ComparatorUtils.equals(oldName, tdName)) { + map.put(oldName, tdName); + } + fireDSChanged(map); + tc.fireTargetModified(); + tc.parameterChanged(); + int[] rows = dataTree.getSelectionRows(); + dataTree.refreshChildByName(tdName); + dataTree.setSelectionRows(rows); + } + }); + nPanel.addPropertyChangeListener(new PropertyChangeAdapter() { + @Override + public void propertyChange() { + doPropertyChange(dg, nPanel, oldName); + } + }); + dg.setVisible(true); + } + + private void doPropertyChange(BasicDialog dg, BasicPane.NamePane nPanel, final String oldName) { + type = dg.getTitle(); + nPanel.setShowText(StringUtils.BLANK); + dg.setButtonEnabled(true); + String tempName = nPanel.getObjectName(); + if (StringUtils.isBlank(tempName)) { + nPanel.setShowText(Inter.getLocText(new String[]{"DS-TableData", "ISEMPTY", "PLEASE", "GIVE-NAME"}, new String[]{"", ",", "", "!"})); + dg.setButtonEnabled(false); + } else if (!ComparatorUtils.equals(oldName, tempName) && isDsNameRepeaded(tempName, allDSNames)) { + String[] waring = new String[]{"DS-TableData", "Utils-has_been_existed", "PLEASE", "Rename"}; + String[] sign = new String[]{tempName, ",", "", "!"}; + nPanel.setShowText(Inter.getLocText(waring, sign)); + dg.setButtonEnabled(false); + } else if (isProcedureName(oldName)) { + if (isIncludeUnderline(tempName)) { + String[] datasource_underline = new String[]{"Datasource-Stored_Procedure", "Name", "can_not_include_underline"}; + String[] sign = new String[]{"", "", "!"}; + nPanel.setShowText(Inter.getLocText(datasource_underline, sign)); + dg.setButtonEnabled(false); + } + } else { + nPanel.setShowText(StringUtils.BLANK); + dg.setButtonEnabled(true); + } + } + + + private boolean isProcedureName(String oldName) { + return oldName.length() >= PROCEDURE_NAME_INDEX && ComparatorUtils.equals(type, Inter.getLocText("Datasource-Stored_Procedure")); + } + + + private boolean isDsNameRepeaded(String name, String[] names) { + boolean repeat = false; + for (int i = 0; i < names.length; i++) { + if (ComparatorUtils.equals(name, names[i])) { + repeat = true; + } + } + return repeat; + } + + + private boolean isIncludeUnderline(String name) { + return ComparatorUtils.equals(name.indexOf(StoreProcedure.SPLIT), -1) ? false : true; + } + + + private abstract class TDAction extends UpdateAction { + + protected abstract String getTDName(); + + protected abstract Icon getTDIcon(); + + protected abstract String getNamePrefix(); + + protected abstract TemplateTableDataWrapper getTableDataInstance(); + + public TDAction() { + this.setName(this.getTDName()); + this.setSmallIcon(this.getTDIcon()); + } + + public void actionPerformed(ActionEvent e) { + dgEdit(getTableDataInstance().creatTableDataPane(), createDsName(getNamePrefix())); + } + } + + private String createDsName(String prefix) { + int count = 1; + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + while (isDsNameRepeaded(prefix + count, allDSNames)) { + count++; + } + return prefix + count; + } + + /** + * 创建不重复的名字即初始的默认名 + * + * @param tree 树 + * @param prefix 后缀 + * @return 返回名字 + */ + public static String createUnrepeatedName(TableDataTree tree, String prefix) { + int count = 1; + + while (tree.isNameRepeated(prefix + count)) { + count++; + } + return prefix + count; + } + + private class PreviewTableDataAction extends UpdateAction { + + public PreviewTableDataAction() { + this.setName(Inter.getLocText("FR-Designer_Preview")); + this.setMnemonic('p'); + this.setSmallIcon(BaseUtils.readIcon(IconPathConstants.PREVIEW_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject selectedNO = dataTree.getRealSelectedNameObject(); + Object data = null; + if (selectedNO != null) { + data = selectedNO.getObject(); + } + try { + if (((TableDataWrapper) data).getTableData() instanceof StoreProcedure) { + ((StoreProcedure) (((TableDataWrapper) data).getTableData())).resetDataModelList(); + if (data instanceof StoreProcedureDataWrapper) { + StoreProcedureDataWrapper oldSdw = ((StoreProcedureDataWrapper) data); + StoreProcedureDataWrapper newSdw = new StoreProcedureDataWrapper((StoreProcedure) oldSdw.getTableData(), oldSdw.getStoreprocedureName(), oldSdw.getTableDataName()); + newSdw.previewData(StoreProcedureDataWrapper.PREVIEW_ONE); + } else { + StoreProcedure storeProcedure = (StoreProcedure) ((TableDataWrapper) data).getTableData(); + StoreProcedureDataWrapper storeProcedureDataWrapper = new StoreProcedureDataWrapper(storeProcedure, StringUtils.EMPTY, StringUtils.EMPTY); + storeProcedureDataWrapper.previewData(StoreProcedureDataWrapper.PREVIEW_ALL); + } + } else { + ((TableDataWrapper) data).previewData(); + } + + } catch (Exception ex) { + FRContext.getLogger().error(ex.getMessage(), ex); + } + + } + } + + private class EditAction extends UpdateAction { + public EditAction() { + this.setName(Inter.getLocText("FR-Designer_Edit")); + this.setMnemonic('E'); + this.setSmallIcon(BaseUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH)); + } + + public void actionPerformed(ActionEvent e) { + final NameObject selectedNO = dataTree.getSelectedNameObject(); + if (selectedNO == null) { + return; + } + + dgEdit(((AbstractTableDataWrapper) selectedNO.getObject()).creatTableDataPane(), selectedNO.getName()); + } + } + + private class RemoveAction extends UpdateAction { + + public RemoveAction() { + this.setName(Inter.getLocText("FR-Designer_Remove")); + this.setMnemonic('R'); + this.setSmallIcon(BaseUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject selectedNO = dataTree.getSelectedNameObject(); + + if (selectedNO == null) { + return; + } + + int returnVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Utils-Are_you_sure_to_remove_the_selected_item") + ":" + selectedNO.getName() + "?", + Inter.getLocText("FR-Designer_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (returnVal == JOptionPane.OK_OPTION) { + // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 + op.removeAction(selectedNO.getName()); + dataTree.refresh(); + // Richie:默认最后一行获得焦点. + dataTree.requestFocus(); + dataTree.setSelectionRow(dataTree.getRowCount() - 1); + fireDSChanged(); + checkButtonEnabled(); + } + } + } + + private void populate(TableDataSourceOP op) { + this.op = op; + dataTree.populate(op); + checkButtonEnabled(); + } + + private class ConnectionTableAction extends com.fr.design.actions.server.ConnectionListAction { + + public ConnectionTableAction() { + this.setName(Inter.getLocText("Server-Define_Data_Connection")); + this.setMnemonic('D'); + this.setSmallIcon(BaseUtils.readIcon(IconPathConstants.TD_CONNECTION_ICON_PATH)); + } + } + + /** + * @return + */ + public TableDataTree getDataTree() { + return dataTree; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TreeTableDataComboBox.java b/designer_base/src/com/fr/design/data/datapane/TreeTableDataComboBox.java new file mode 100644 index 0000000000..27bfa7d87c --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TreeTableDataComboBox.java @@ -0,0 +1,87 @@ +package com.fr.design.data.datapane; + +import com.fr.data.TableDataSource; +import com.fr.data.impl.RecursionTableData; +import com.fr.design.data.tabledata.wrapper.ServerTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; + +import javax.swing.*; +import java.awt.*; + +public class TreeTableDataComboBox extends UIComboBox { + private static final long serialVersionUID = 1L; + private java.util.Map res_map = new java.util.LinkedHashMap(); + private TableDataSource source; + + public TreeTableDataComboBox(TableDataSource source) { + this.source = source; + this.setRenderer(new UIComboBoxRenderer() { + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof TableDataWrapper) { + TableDataWrapper tabledatawrappe = (TableDataWrapper) value; + this.setIcon(tabledatawrappe.getIcon()); + this.setText(tabledatawrappe.getTableDataName()); + } + return this; + } + }); + refresh(); + } + + /** + * 刷新 + */ + public void refresh() { + java.util.Iterator nameIt; + DefaultComboBoxModel model = new DefaultComboBoxModel(); + this.setModel(model); + if (source != null) { + // 报表数据集 + nameIt = source.getTableDataNameIterator(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + if(source.getTableData(name) instanceof RecursionTableData) { + TemplateTableDataWrapper templateTableDataWrappe = new TemplateTableDataWrapper(source.getTableData(name), name); + model.addElement(templateTableDataWrappe); + res_map.put(name, templateTableDataWrappe); + } + } + } + + // 全局数据集 + DatasourceManagerProvider mgr = DatasourceManager.getProviderInstance(); + nameIt = mgr.getTableDataNameIterator(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + if(mgr.getTableData(name) instanceof RecursionTableData) { + ServerTableDataWrapper serverTableDataWrappe = new ServerTableDataWrapper(mgr.getTableData(name), name); + model.addElement(serverTableDataWrappe); + res_map.put(name, serverTableDataWrappe); + } + } + } + + public void setSelectedTableDataByName(String name) { + TableDataWrapper tableDataWrappe = res_map.get(name); + this.getModel().setSelectedItem(tableDataWrappe); + } + + @Override + public TableDataWrapper getSelectedItem() { + return (TableDataWrapper) dataModel.getSelectedItem(); + } + + public RecursionTableData getSelcetedTableData() { + String name = ((TableDataWrapper) dataModel.getSelectedItem()).getTableDataName(); + return (RecursionTableData)source.getTableData(name); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/TreeTableDataDictPane.java b/designer_base/src/com/fr/design/data/datapane/TreeTableDataDictPane.java new file mode 100644 index 0000000000..7623ac37d3 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/TreeTableDataDictPane.java @@ -0,0 +1,299 @@ +package com.fr.design.data.datapane; + +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.impl.RecursionTableData; +import com.fr.design.data.datapane.preview.PreviewLabel; +import com.fr.design.data.datapane.preview.PreviewLabel.Previewable; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.editor.editor.ColumnIndexEditor; +import com.fr.design.editor.editor.ColumnNameEditor; +import com.fr.design.editor.editor.Editor; +import com.fr.general.Inter; +import com.fr.script.Calculator; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.List; + +public class TreeTableDataDictPane extends BasicPane implements Previewable { + + private UILabel selectTableDataLabel; + protected TableDataComboBox tableDataNameComboBox; + private UIRadioButton parentMarkRadio; + private UIRadioButton lengthMarkRadio; + private ButtonGroup markButtonGroup; + + UILabel originalMarkedFieldLabel1; + UILabel parentMarkedFieldLabel1; + UILabel treeDataFieldLabel1; + UILabel originalMarkedFieldLabel2; + UILabel treeDataFieldLabel2; + + private ValueEditorPane originalMarkedFieldPane1; + private ValueEditorPane parentMarkedFieldPane1; + private ValueEditorPane originalMarkedFieldPane2; + + public TreeTableDataDictPane(){ + this(StringUtils.EMPTY); + } + public TreeTableDataDictPane(String treeName) { + this.setLayout(new BorderLayout(5,30)); + this.setBorder(BorderFactory.createEmptyBorder(20, 20, 0, 0)); + selectTableDataLabel = new UILabel(Inter.getLocText(new String[]{"Please_Select","Single", "DS-TableData"}) + " :"); + setTableDataNameComboBox(treeName); + tableDataNameComboBox.setPreferredSize(new Dimension(180, 20)); + JPanel tableFlowPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(); + tableFlowPane.add(selectTableDataLabel); + tableFlowPane.add(tableDataNameComboBox); + tableDataNameComboBox.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + tdChange(); + } + }); + tableFlowPane.add(new PreviewLabel(this)); + this.add(tableFlowPane, BorderLayout.NORTH); + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(centerPane,BorderLayout.CENTER); + parentMarkRadio = new UIRadioButton(Inter.getLocText("Build_Tree_Accord_Parent_Marked_Filed"), true); + lengthMarkRadio = new UIRadioButton(Inter.getLocText("Build_Tree_Accord_Marked_Filed_Length")); + parentMarkRadio.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if(isBuildByParentFiled()) { + makeParentEnable(); + tdChange(); + } + } + }); + lengthMarkRadio.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if(!isBuildByParentFiled()) { + makeLengthEnable(); + tdChange(); + } + } + }); + markButtonGroup = new ButtonGroup(); + markButtonGroup.add(parentMarkRadio); + markButtonGroup.add(lengthMarkRadio); + + originalMarkedFieldLabel1 = new UILabel(Inter.getLocText("Original_Marked_Filed") + " :", SwingConstants.RIGHT); + parentMarkedFieldLabel1 = new UILabel(" " + Inter.getLocText("Parent_Marked_Field") + " :", SwingConstants.RIGHT); + treeDataFieldLabel1 = new UILabel(" " + Inter.getLocText("Tree_Data_Field") + " :", SwingConstants.RIGHT); + originalMarkedFieldLabel2 = new UILabel(Inter.getLocText("Original_Marked_Filed") + " :", SwingConstants.RIGHT); + treeDataFieldLabel2 = new UILabel(" " + Inter.getLocText("Tree_Data_Field") + " :", SwingConstants.RIGHT); + +// originalMarkedFieldPane1 = ValueEditorPaneFactory.createValueEditorPane(new Editor[] {new OldColumnIndexEditor(Inter.getLocText("Columns"))}); +// parentMarkedFieldPane1 = ValueEditorPaneFactory.createValueEditorPane(new Editor[] {new OldColumnIndexEditor(Inter.getLocText("Columns"))}); +// originalMarkedFieldPane2 = ValueEditorPaneFactory.createValueEditorPane(new Editor[] {new OldColumnIndexEditor(Inter.getLocText("Columns"))}); + originalMarkedFieldPane1 = ValueEditorPaneFactory.createValueEditorPane(new Editor[] { new ColumnNameEditor(), new ColumnIndexEditor() }); + parentMarkedFieldPane1 = ValueEditorPaneFactory.createValueEditorPane(new Editor[] { new ColumnNameEditor(), new ColumnIndexEditor() }); + originalMarkedFieldPane2 = ValueEditorPaneFactory.createValueEditorPane(new Editor[] { new ColumnNameEditor(), new ColumnIndexEditor() }); + + makeParentEnable(); + + JPanel p1 = createCenterFlowZeroGapBorderPane(originalMarkedFieldLabel1, originalMarkedFieldPane1); + JPanel p2 = createCenterFlowZeroGapBorderPane(parentMarkedFieldLabel1, parentMarkedFieldPane1); + JPanel border1 = new JPanel(); + border1.setLayout(new BorderLayout(0, 10)); + border1.add(p1, BorderLayout.NORTH); + border1.add(p2, BorderLayout.CENTER); + JPanel p4 = createCenterFlowZeroGapBorderPane(originalMarkedFieldLabel2, originalMarkedFieldPane2); + JPanel border2 = new JPanel(); + border2.setLayout(new BorderLayout(0, 20)); + border2.add(p4, BorderLayout.NORTH); + + JPanel xx = FRGUIPaneFactory.createBorderLayout_S_Pane(); + xx.add(parentMarkRadio,BorderLayout.NORTH); + xx.add(border1,BorderLayout.CENTER); + JPanel xxx = FRGUIPaneFactory.createBorderLayout_S_Pane(); + xxx.add(lengthMarkRadio,BorderLayout.NORTH); + xxx.add(border2,BorderLayout.CENTER); + JPanel buildTreePanel = new JPanel(new BorderLayout(5, 30)); + buildTreePanel.add(xx,BorderLayout.NORTH); + buildTreePanel.add(xxx,BorderLayout.CENTER); + centerPane.add(buildTreePanel, BorderLayout.NORTH); + JPanel previewPanel = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + UIButton treeDataPreviewButton = new UIButton(Inter.getLocText("Preview")); + previewPanel.add(treeDataPreviewButton); + treeDataPreviewButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + TableDataWrapper tableDataWrappe = tableDataNameComboBox.getSelectedItem(); + if(tableDataWrappe == null) { + return; + } + RecursionTableData rtd = new RecursionTableData(); + rtd.setOriginalTableDataName(tableDataWrappe.getTableDataName()); + if(isBuildByParentFiled()) { + rtd.setMarkFields((Integer.parseInt(originalMarkedFieldPane1.update().toString()) - 1) + ""); + rtd.setParentmarkFields(Integer.parseInt(parentMarkedFieldPane1.update().toString()) - 1 + ""); + } else { + rtd.setMarkFields(Integer.parseInt(originalMarkedFieldPane2.update().toString()) - 1 + ""); + rtd.setParentmarkFields("-1"); + } + rtd.setTableDataSource(DesignTableDataManager.getEditingTableDataSource()); + rtd.createDataModel(Calculator.createCalculator()); + PreviewTablePane.previewTableData(rtd); + } + }); + centerPane.add(previewPanel, BorderLayout.CENTER); + } + + protected void setTableDataNameComboBox(String treeName) { + tableDataNameComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource(),treeName); + + } + + private void tdChange(){ + TableDataWrapper tableDataWrappe = this.tableDataNameComboBox.getSelectedItem(); + if (tableDataWrappe == null) { + return; + } + ValueEditorPane[] valueEditorPanes; + if(isBuildByParentFiled()) { + valueEditorPanes = new ValueEditorPane[]{originalMarkedFieldPane1, parentMarkedFieldPane1}; + } else { + valueEditorPanes = new ValueEditorPane[]{originalMarkedFieldPane2}; + } + try { + List namelist = tableDataWrappe.calculateColumnNameList(); + int len = namelist.size(); + String[] columnNames = new String[len]; + namelist.toArray(columnNames); + for(int i = 0; i < valueEditorPanes.length; i ++) { + valueEditorPanes[i].setEditors(new Editor[] { new ColumnNameEditor(columnNames), new ColumnIndexEditor(len) }, columnNames[0]); + } + } catch (Exception e) { + for(int i = 0; i < valueEditorPanes.length; i ++) { + valueEditorPanes[i].setEditors(new Editor[] { new ColumnNameEditor(), new ColumnIndexEditor() }, 1); + } + } finally { + valueEditorPanes = null; + } + } + + @Override + protected String title4PopupWindow() { + return "TreeTableDataDictionay"; + } + + public RecursionTableData update() { + RecursionTableData td = new RecursionTableData(); + if(tableDataNameComboBox.getSelectedItem()==null){ + td.setOriginalTableDataName(null); + }else{ + td.setOriginalTableDataName(tableDataNameComboBox.getSelectedItem().getTableDataName()); + } + if(isBuildByParentFiled()) { + Object o = parentMarkedFieldPane1.update(StringUtils.EMPTY); + if(o instanceof Object[]){ + Object[] temp = (Object[]) o; + td.setParentmarkFields(((Integer)temp[0]).intValue() - 1 + ""); + td.setParentmarkFieldName((String) temp[1]); + } + Object o2 = originalMarkedFieldPane1.update(StringUtils.EMPTY); + if(o2 instanceof Object[]){ + Object[] temp = (Object[]) o2; + td.setMarkFields(((Integer)temp[0]).intValue() - 1 + ""); + td.setMarkFieldName((String) temp[1]); + } + } else { + Object o = originalMarkedFieldPane2.update(StringUtils.EMPTY); + if(o == null || !(o instanceof Object[])){ + td.setMarkFields("-1"); + } else { + Object[] temp = (Object[]) o; + td.setMarkFields(((Integer)temp[0]).intValue() - 1 + ""); + td.setMarkFieldName((String) temp[1]); + } + } + td.setTableDataSource(DesignTableDataManager.getEditingTableDataSource()); + return td; + } + + public void populate(RecursionTableData rtb) { + if(StringUtils.isNotEmpty(rtb.getParentmarkFields())) { + makeParentEnable(); + parentMarkRadio.setSelected(true); + lengthMarkRadio.setSelected(false); + tableDataNameComboBox.setSelectedTableDataByName(rtb.getOriginalTableDataName()); + if(StringUtils.isNotEmpty(rtb.getMarkFieldName())){ + originalMarkedFieldPane1.populate(rtb.getMarkFieldName()); + }else{ + originalMarkedFieldPane1.populate(rtb.getMarkFieldIndex() + 1); + } + if(StringUtils.isNotEmpty(rtb.getParentmarkFieldName())){ + parentMarkedFieldPane1.populate(rtb.getParentmarkFieldName()); + }else{ + parentMarkedFieldPane1.populate(rtb.getParentmarkFieldIndex() + 1); + } + } else { + makeLengthEnable(); + lengthMarkRadio.setSelected(true); + parentMarkRadio.setSelected(false); + tableDataNameComboBox.setSelectedTableDataByName(rtb.getOriginalTableDataName()); + if(StringUtils.isNotEmpty(rtb.getMarkFieldName())){ + originalMarkedFieldPane2.populate(rtb.getMarkFieldName()); + }else{ + originalMarkedFieldPane2.populate(rtb.getMarkFieldIndex() + 1); + } + } + } + + /** + * + */ + public void preview() { + TableDataWrapper tableDataWrappe = tableDataNameComboBox.getSelectedItem(); + if (tableDataWrappe == null) { + return; + } + tableDataWrappe.previewData(); + } + + private JPanel createCenterFlowZeroGapBorderPane(Component p1, Component p2) { + JPanel p = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + p.add(p1); + p.add(p2); + return p; + } + + private boolean isBuildByParentFiled() { + return parentMarkRadio.isSelected(); + } + + private void makeParentEnable() { + originalMarkedFieldPane1.setEnabled(true); + parentMarkedFieldPane1.setEnabled(true); + originalMarkedFieldLabel1.setEnabled(true); + parentMarkedFieldLabel1.setEnabled(true); + treeDataFieldLabel1.setEnabled(true); + originalMarkedFieldLabel2.setEnabled(false); + treeDataFieldLabel2.setEnabled(false); + originalMarkedFieldPane2.setEnabled(false); + } + + private void makeLengthEnable() { + originalMarkedFieldPane1.setEnabled(false); + parentMarkedFieldPane1.setEnabled(false); + originalMarkedFieldLabel1.setEnabled(false); + parentMarkedFieldLabel1.setEnabled(false); + treeDataFieldLabel1.setEnabled(false); + originalMarkedFieldLabel2.setEnabled(true); + treeDataFieldLabel2.setEnabled(true); + originalMarkedFieldPane2.setEnabled(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/VerticalChoosePane.java b/designer_base/src/com/fr/design/data/datapane/VerticalChoosePane.java new file mode 100644 index 0000000000..f20c58c8d0 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/VerticalChoosePane.java @@ -0,0 +1,69 @@ +package com.fr.design.data.datapane; + +import java.awt.*; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.design.constants.LayoutConstants; +import com.fr.design.data.datapane.preview.PreviewLabel; +import com.fr.design.data.datapane.preview.PreviewLabel.Previewable; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerBean; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.Inter; +import com.fr.design.utils.gui.GUICoreUtils; + +public class VerticalChoosePane extends ChoosePane implements DesignerBean{ + + public VerticalChoosePane(Previewable previewable) { + this(previewable, -1); + } + + public VerticalChoosePane(Previewable previewable, int labelSize) { + super(previewable, labelSize); + DesignerContext.setDesignerBean("databasename", this); + } + + @Override + protected void initComponentsLayout(PreviewLabel previewLabel, int labelSize) { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = { p, f }; + double[] rowSize = { p, p, p }; + + JPanel rs = new JPanel(new BorderLayout(0, 0)); + rs.add(tableNameComboBox, BorderLayout.CENTER); + rs.add(GUICoreUtils.createFlowPane(new Component[]{new RefreshLabel(this), previewLabel}, FlowLayout.LEFT, LayoutConstants.HGAP_LARGE), BorderLayout.EAST); + + UILabel l1 = new UILabel(Inter.getLocText("Database") + ":", UILabel.RIGHT); + UILabel l2 = new UILabel(Inter.getLocText("Model") + ":", UILabel.RIGHT); + UILabel l3 = new UILabel(Inter.getLocText(new String[]{"Database", "Table"}) + ":", UILabel.RIGHT); + + if (labelSize > 0) { + Dimension pSize = new Dimension(labelSize, 20); + l1.setPreferredSize(pSize); + l2.setPreferredSize(pSize); + l3.setPreferredSize(pSize); + } + + Component[][] components = new Component[][]{ + new Component[]{l1, dsNameComboBox}, + new Component[]{l2, schemaBox}, + new Component[]{l3, rs} + }; + + JPanel content = TableLayoutHelper.createTableLayoutPane(components,rowSize,columnSize); + this.setLayout(new BorderLayout()); + this.add(content,BorderLayout.CENTER); + } + + + + @Override + public void refreshBeanElement() { + initDsNameComboBox(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java new file mode 100644 index 0000000000..cc75b7ca22 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java @@ -0,0 +1,128 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.data.impl.AbstractDatabaseConnection; +import com.fr.data.impl.Connection; +import com.fr.data.impl.NameDatabaseConnection; +import com.fr.design.DesignerEnvManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.List; + +/** + * 选择数据连接的下拉框 + * + * @editor zhou + * @since 2012-3-28下午3:02:30 + */ +public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { + /** + * + */ + private static final long serialVersionUID = 1L; + private Class cls; // 所取的Connection都是cls及其子类 + private java.util.List nameList = new ArrayList(); + + public ConnectionComboBoxPanel(Class cls) { + super(); + + this.cls = cls; + + // alex:添加item change监听,当改变时改变DesignerEnvManager中的最近选中的数据连接 + this.itemComboBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + String selected = ConnectionComboBoxPanel.this.getSelectedItem(); + if (StringUtils.isNotBlank(selected)) { + DesignerEnvManager.getEnvManager().setRecentSelectedConnection(selected); + } + } + }); + refreshItems(); + } + + /* + * 刷新ComboBox.items + */ + protected java.util.Iterator items() { + nameList = new ArrayList(); + + DatasourceManagerProvider mgr = DatasourceManager.getProviderInstance(); + java.util.Iterator nameIt = mgr.getConnectionNameIterator(); + while (nameIt.hasNext()) { + String conName = nameIt.next(); + Connection connection = mgr.getConnection(conName); + filterConnection(connection, conName, nameList); + } + + return nameList.iterator(); + } + + protected void filterConnection(Connection connection, String conName, List nameList) { + connection.addConnection(nameList, conName, new Class[]{AbstractDatabaseConnection.class}); + } + + + public int getConnectionSize() { + return nameList.size(); + } + + public String getConnection(int i) { + return nameList.get(i); + } + + /* + * 弹出对话框编辑Items + */ + protected void editItems() { + final ConnectionListPane connectionListPane = new ConnectionListPane(); + final DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + connectionListPane.populate(datasourceManager); + BasicDialog connectionListDialog = connectionListPane.showLargeWindow( + SwingUtilities.getWindowAncestor(ConnectionComboBoxPanel.this), new DialogActionAdapter() { + public void doOk() { + connectionListPane.update(datasourceManager); + // marks:保存数据 + Env currentEnv = FRContext.getCurrentEnv(); + try { + currentEnv.writeResource(datasourceManager); + } catch (Exception ex) { + FRContext.getLogger().error(ex.getMessage(), ex); + } + } + }); + connectionListDialog.setVisible(true); + refreshItems(); + } + + public void populate(com.fr.data.impl.Connection connection) { + editButton.setEnabled(FRContext.getCurrentEnv().isRoot()); + if (connection instanceof NameDatabaseConnection) { + this.setSelectedItem(((NameDatabaseConnection) connection).getName()); + } else { + String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection(); + if (StringUtils.isNotBlank(s)) { + for (int i = 0; i < this.getConnectionSize(); i++) { + String t = this.getConnection(i); + if (ComparatorUtils.equals(s, t)) { + this.setSelectedItem(s); + break; + } + } + } + // alex:如果这个ComboBox还是没有选中,那么选中第一个 + if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) { + this.setSelectedItem(this.getConnection(0)); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/ConnectionListPane.java b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionListPane.java new file mode 100644 index 0000000000..1d5dd260aa --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionListPane.java @@ -0,0 +1,153 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.data.impl.Connection; +import com.fr.data.impl.JDBCDatabaseConnection; +import com.fr.data.impl.JNDIDatabaseConnection; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.gui.controlpane.JControlPane; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; +import com.fr.stable.core.PropertyChangeAdapter; + +import javax.swing.*; +import java.util.*; + +/** + * Connection List Pane. + */ +public class ConnectionListPane extends JControlPane { + public static final String TITLE_NAME = Inter.getLocText("Server-Define_Data_Connection"); + private boolean isNamePermitted = true; + private HashMap renameMap = new HashMap(); + + public ConnectionListPane() { + renameMap.clear(); + this.addEditingListner(new PropertyChangeAdapter() { + public void propertyChange() { + isNamePermitted = true; + String[] allListNames = nameableList.getAllNames(); + allListNames[nameableList.getSelectedIndex()] = StringUtils.EMPTY; + String tempName = getEditingName(); + if (StringUtils.isEmpty(tempName)) { + String[] warning = new String[]{"NOT_NULL_Des", "Please_Rename"}; + String[] sign = new String[]{",", "!"}; + nameableList.stopEditing(); + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ConnectionListPane.this), Inter.getLocText(warning, sign)); + setWarnigText(editingIndex); + isNamePermitted = false; + return; + } + if (!ComparatorUtils.equals(tempName, selectedName) + && isNameRepeted(new List[]{Arrays.asList(allListNames)}, tempName)) { + isNamePermitted = false; + nameableList.stopEditing(); + String message = Inter.getLocText(new String[]{"Utils-has_been_existed", "DashBoard-ConnectionList", "Please_Rename"}, new String[]{"", tempName + ",", "!"}); + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ConnectionListPane.this), message); + setWarnigText(editingIndex); + } + if (isNamePermitted && !ComparatorUtils.equals(tempName, selectedName)) { + rename(selectedName, tempName); + } + + } + }); + } + + + protected void rename(String oldName, String newName) { + if (renameMap.containsKey(selectedName)) { + renameMap.remove(selectedName); + } + renameMap.put(selectedName, newName); + } + + /** + * 名字是否允许 + * + * @return 是/否 + */ + public boolean isNamePermitted() { + return isNamePermitted; + } + + /** + * 检查按钮可用状态 Check button enabled. + */ + public void checkButtonEnabled() { + super.checkButtonEnabled(); + isNamePermitted = !isContainsRename(); + } + + + public HashMap getRenameMap() { + return renameMap; + } + + /** + * 创建菜单项 + * + * @return 菜单项 + */ + public NameableCreator[] createNameableCreators() { + NameableCreator[] creators = new NameableCreator[]{new NameObjectCreator( + "JDBC", + "/com/fr/design/images/data/source/jdbcTableData.png", + JDBCDatabaseConnection.class, + DatabaseConnectionPane.JDBC.class + ), new NameObjectCreator( + "JNDI", + "/com/fr/design/images/data/source/jdbcTableData.png", + JNDIDatabaseConnection.class, + DatabaseConnectionPane.JNDI.class + )}; + NameObjectCreator[] pluginCreators = ExtraDesignClassManager.getInstance().getConnections(); + + return (NameableCreator[]) ArrayUtils.addAll(creators, pluginCreators); + } + + @Override + protected String title4PopupWindow() { + return TITLE_NAME; + } + + /** + * Populate. + * + * @param datasourceManager the new datasourceManager. + */ + public void populate(DatasourceManagerProvider datasourceManager) { + Iterator nameIt = datasourceManager.getConnectionNameIterator(); + + List nameObjectList = new ArrayList(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + nameObjectList.add(new NameObject(name, datasourceManager.getConnection(name))); + } + this.populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); + + } + + /** + * Update. + */ + public void update(DatasourceManagerProvider datasourceManager) { + // Nameable[]居然不能强转成NameObject[],一定要这么写... + Nameable[] res = this.update(); + NameObject[] res_array = new NameObject[res.length]; + java.util.Arrays.asList(res).toArray(res_array); + + datasourceManager.clearAllConnection(); + + for (int i = 0; i < res_array.length; i++) { + NameObject nameObject = res_array[i]; + datasourceManager.putConnection(nameObject.getName(), (Connection) nameObject.getObject()); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/ConnectionManagerPane.java b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionManagerPane.java new file mode 100644 index 0000000000..ace69ff692 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionManagerPane.java @@ -0,0 +1,78 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.base.FRContext; +import com.fr.design.gui.frpane.LoadingBasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.util.HashMap; + +public class ConnectionManagerPane extends LoadingBasicPane { + private UITextField connectionTextField; + private ConnectionListPane connectionListPane; + + protected void initComponents(JPanel container) { + container.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel connectionPathPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + container.add(connectionPathPane, BorderLayout.NORTH); + + connectionPathPane.setBorder(BorderFactory.createEmptyBorder(6, 2, 2, 2)); + + connectionPathPane.add(new UILabel(Inter.getLocText("FR-Designer_Save_Path") + ":"), BorderLayout.WEST); + this.connectionTextField = new UITextField(); + connectionPathPane.add(connectionTextField, BorderLayout.CENTER); + this.connectionTextField.setEditable(false); + connectionListPane = new ConnectionListPane(){ + protected void rename(String oldName,String newName) { + super.rename(oldName,newName); + renameConnection(oldName,newName); + } + }; + container.add(connectionListPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Server-Define_Data_Connection"); + } + + public HashMap getRenameMap() { + return connectionListPane.getRenameMap(); + } + + public void populate(DatasourceManagerProvider datasourceManager) { + this.connectionTextField.setText(FRContext.getCurrentEnv().getPath() + File.separator + ProjectConstants.RESOURCES_NAME + + File.separator + datasourceManager.fileName()); + this.connectionListPane.populate(datasourceManager); + } + + public void update(DatasourceManagerProvider datasourceManager) { + this.connectionListPane.update(datasourceManager); + } + + /** + * 设置选中项 + * + * @param index 选中项的序列号 + */ + public void setSelectedIndex(int index) { + this.connectionListPane.setSelectedIndex(index); + } + + /** + * 名字是否允许 + * @return 允许返回true + */ + public boolean isNamePermitted() { + return connectionListPane.isNamePermitted(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java new file mode 100644 index 0000000000..44b71999ba --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java @@ -0,0 +1,188 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.data.core.db.TableProcedure; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.ilist.TableViewList; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.*; + +/** + * 数据集编辑面板左边的部分 + * + * @editor zhou + * @since 2012-3-28下午10:14:59 + */ +public class ConnectionTableProcedurePane extends BasicPane { + private static int WIDTH = 155; + private ConnectionComboBoxPanel connectionComboBox; + private UICheckBox tableCheckBox; + private UICheckBox viewCheckBox; + private UITextField searchField; + private TableViewList tableViewList; + private java.util.List listeners = new java.util.ArrayList(); + + public ConnectionTableProcedurePane() { + this.setLayout(new BorderLayout(4, 4)); + connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class){ + protected void refreshItems(){ + super.refreshItems(); + if (tableViewList != null) { + search(); + } + } + }; + tableViewList = new TableViewList(); + ToolTipManager.sharedInstance().registerComponent(tableViewList); + connectionComboBox.addComboBoxActionListener(filter); + tableViewList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + if (evt.getClickCount() >= 2) { + Object obj = tableViewList.getSelectedValue(); + TableProcedure tableProcedure = null; + if (obj instanceof TableProcedure) { + tableProcedure = (TableProcedure)obj; + }else { + return; + } + for (int i = 0; i < ConnectionTableProcedurePane.this.listeners.size(); i++) { + ConnectionTableProcedurePane.this.listeners.get(i).actionPerformed(tableProcedure); + } + } + } + }); + JPanel filterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel checkBoxgroupPane = createCheckBoxgroupPane(); + if (checkBoxgroupPane != null) { + filterPane.add(createCheckBoxgroupPane(), BorderLayout.NORTH); + } + JPanel searchPane = new JPanel(new BorderLayout(10, 0)); + searchField = new UITextField(); + searchPane.add(searchField, BorderLayout.CENTER); + searchField.getDocument().addDocumentListener(searchListener); + filterPane.add(searchPane, BorderLayout.CENTER); + UIScrollPane tableViewListPane = new UIScrollPane(tableViewList); + tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + this.add(connectionComboBox, BorderLayout.NORTH); + this.add(tableViewListPane, BorderLayout.CENTER); + this.add(filterPane, BorderLayout.SOUTH); + this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height)); + } + + protected JPanel createCheckBoxgroupPane() { + JPanel checkBoxgroupPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2); + JPanel first = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + tableCheckBox = new UICheckBox(); + tableCheckBox.setSelected(true); + tableCheckBox.addActionListener(filter); + first.add(tableCheckBox); + first.add(new UILabel(Inter.getLocText("Table"), BaseUtils.readIcon("/com/fr/design/images/data/tables.png"), UILabel.LEADING)); + + JPanel second = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + viewCheckBox = new UICheckBox(); + viewCheckBox.setSelected(true); + viewCheckBox.addActionListener(filter); + second.add(viewCheckBox); + second.add(new UILabel(Inter.getLocText("SQL-View"), BaseUtils.readIcon("/com/fr/design/images/data/views.png"), UILabel.LEADING)); + + checkBoxgroupPane.add(first); + checkBoxgroupPane.add(second); + + return checkBoxgroupPane; + } + + /** + * 给 itemComboBox 加上 itemListener + * @param itemListener + */ + public void addItemListener(ItemListener itemListener) { + connectionComboBox.itemComboBox.addItemListener(itemListener); + } + private DocumentListener searchListener = new DocumentListener() { + + @Override + public void removeUpdate(DocumentEvent e) { + search(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + search(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + search(); + } + }; + + private ActionListener filter = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + search(); + } + }; + + /** + * 选项改变,需要重新刷新下拉列表里面的项 + */ + protected void search() { + String selectedObj = connectionComboBox.getSelectedItem(); + + String[] types = ArrayUtils.EMPTY_STRING_ARRAY; + if (tableCheckBox != null) { + if (tableCheckBox.isSelected()) { + types = (String[])ArrayUtils.add(types, TableProcedure.TABLE); + } + if (viewCheckBox.isSelected()) { + types = (String[])ArrayUtils.add(types, TableProcedure.VIEW); + } + } else { + types = (String[])ArrayUtils.add(types, TableProcedure.PROCEDURE); + } + tableViewList.populate(selectedObj, searchField.getText().trim(), types); + } + + @Override + protected String title4PopupWindow() { + return "Connection"; + } + + /** + * + * @param l + */ + public void addDoubleClickListener(DoubleClickSelectedNodeOnTreeListener l) { + this.listeners.add(l); + } + + public void setSelectedDatabaseConnection(com.fr.data.impl.Connection db) { + connectionComboBox.populate(db); + } + + public String getSelectedDatabaseConnnectonName() { + return connectionComboBox.getSelectedItem(); + } + + public static interface DoubleClickSelectedNodeOnTreeListener { + /** + * 处理双击事件 + * @param target + */ + public void actionPerformed(TableProcedure target); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/DataConnectionAction.java b/designer_base/src/com/fr/design/data/datapane/connect/DataConnectionAction.java new file mode 100644 index 0000000000..f2d0fd3c38 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/DataConnectionAction.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.data.datapane.connect; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.gui.controlpane.NameObjectCreator; + +import java.awt.event.ActionEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-25 + * Time: 下午5:05 + */ +public abstract class DataConnectionAction extends UpdateAction { + public static final String XML_TAG = "connectionType"; + + public DataConnectionAction() { + this.setName(this.getDisplayName()); + this.setSmallIcon(BaseUtils.readIcon(this.getIconPath())); + } + + /** + * 名字 + * + * @return + */ + public abstract String getDisplayName(); + + /** + * 图标 + * + * @return + */ + public abstract String getIconPath(); + + /** + * 得到数据连接的声明类 + * + * @return + */ + public abstract Class getConnectionClass(); + + /** + * 得到相应面板的类 + * + * @return + */ + public abstract Class getUpdateConnectionPaneClass(); + + + public NameObjectCreator getConnectionCreator() { + return new NameObjectCreator(getDisplayName(), getIconPath(), getConnectionClass(), getUpdateConnectionPaneClass()); + } + + /** + * 动作 + * @param e 动作 + */ + public void actionPerformed(ActionEvent e) { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java b/designer_base/src/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java new file mode 100644 index 0000000000..b622fd9815 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/DatabaseConnectionPane.java @@ -0,0 +1,241 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.data.datapane.connect; + +import com.fr.base.FRContext; +import com.fr.data.impl.JDBCDatabaseConnection; +import com.fr.data.impl.JNDIDatabaseConnection; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.scrollruler.ModLineBorder; +import com.fr.general.Inter; +import com.fr.stable.EncodeConstants; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +/** + * Database Connection pane. + */ +public abstract class DatabaseConnectionPane extends BasicBeanPane { + + // 编码转换. + private UIComboBox originalCharSetComboBox; + private UIComboBox newCharSetComboBox; + private UILabel message; + private UIButton okButton; + private UIButton cancelButton; + private JDialog dialog; + + // Database pane + public DatabaseConnectionPane() { + this.initComponents(); + } + + protected void initComponents() { + originalCharSetComboBox = new UIComboBox(EncodeConstants.ALL_ENCODING_ARRAY); + newCharSetComboBox = new UIComboBox(EncodeConstants.ALL_ENCODING_ARRAY); + message = new UILabel(); + okButton = new UIButton(Inter.getLocText("OK")); + cancelButton = new UIButton(Inter.getLocText("Cancel")); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel northPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + this.add(northPane, BorderLayout.NORTH); + + // 按钮. + JPanel testPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + northPane.add(testPane, BorderLayout.NORTH); + UIButton testButton = new UIButton(Inter.getLocText("Datasource-Test_Connection")); + testPane.add(testButton); + testButton.addActionListener(testConnectionActionListener); + testPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 3, 4)); + + // Center + northPane.add(mainPanel(), BorderLayout.CENTER); + if (!isFineBI()) { + // ChartSet + JPanel chartSetPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(2); + northPane.add(chartSetPane); + chartSetPane.setBorder(BorderFactory.createTitledBorder( + new ModLineBorder(ModLineBorder.TOP), + Inter.getLocText("Datasource-Convert_Charset") + )); + + chartSetPane.add(GUICoreUtils.createNamedPane(originalCharSetComboBox, Inter.getLocText("Datasource-Original_Charset") + ":")); + chartSetPane.add(GUICoreUtils.createNamedPane(newCharSetComboBox, Inter.getLocText("Datasource-New_Charset") + ":")); + } + } + + protected abstract JPanel mainPanel(); + + protected abstract boolean isFineBI(); + + @Override + public void populateBean(com.fr.data.impl.Connection ob) { + this.originalCharSetComboBox.setSelectedItem(ob.getOriginalCharsetName()); + this.newCharSetComboBox.setSelectedItem(ob.getNewCharsetName()); + + populateSubDatabaseConnectionBean((E) ob); + } + + protected abstract void populateSubDatabaseConnectionBean(E ob); + + @Override + public com.fr.data.impl.Connection updateBean() { + E ob = updateSubDatabaseConnectionBean(); + + if (this.originalCharSetComboBox.getSelectedIndex() == 0) { + ob.setOriginalCharsetName(null); + } else { + ob.setOriginalCharsetName((String) this.originalCharSetComboBox.getSelectedItem()); + } + + if (this.newCharSetComboBox.getSelectedIndex() == 0) { + ob.setNewCharsetName(null); + } else { + ob.setNewCharsetName((String) this.newCharSetComboBox.getSelectedItem()); + } + + return ob; + } + + protected abstract E updateSubDatabaseConnectionBean(); + + ActionListener testConnectionActionListener = new ActionListener() { + public void actionPerformed(ActionEvent evt) { + // Try the java connection. + final SwingWorker connectionThread = new SwingWorker() { + protected Object doInBackground() throws Exception { + try { + com.fr.data.impl.Connection database = DatabaseConnectionPane.this.updateBean(); + boolean connect = FRContext.getCurrentEnv().testConnection(database); + okButton.setEnabled(true); + message.setText(database.connectMessage(connect)); + } catch (Exception exp) { + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + } + return null; + } + }; + + connectionThread.execute(); + initDialogPane(); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + }); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + connectionThread.cancel(true); + } + }); + + dialog.addWindowListener(new WindowAdapter() { + public void windowClosed(WindowEvent e) { + connectionThread.cancel(true); + } + }); + + dialog.show(); + dialog.dispose(); + } + }; + + private void initDialogPane() { + + message.setText(Inter.getLocText("Datasource-Test_Connection") + "..."); + message.setBorder(BorderFactory.createEmptyBorder(8, 5, 0, 0)); + okButton.setEnabled(false); + + dialog = new JDialog((Dialog) SwingUtilities.getWindowAncestor(DatabaseConnectionPane.this), Inter.getLocText("Datasource-Test_Connection"), true); + dialog.setSize(new Dimension(268, 118)); + okButton.setEnabled(false); + JPanel jp = new JPanel(); + JPanel upPane = new JPanel(); + JPanel downPane = new JPanel(); + UILabel uiLabel = new UILabel(UIManager.getIcon("OptionPane.informationIcon")); + upPane.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10)); + upPane.add(uiLabel); + upPane.add(message); + downPane.setLayout(new FlowLayout(FlowLayout.CENTER, 6, 0)); + downPane.add(okButton); + downPane.add(cancelButton); + jp.setLayout(new BoxLayout(jp, BoxLayout.Y_AXIS)); + jp.add(upPane); + jp.add(downPane); + dialog.add(jp); + dialog.setResizable(false); + dialog.setLocationRelativeTo(SwingUtilities.getWindowAncestor(DatabaseConnectionPane.this)); + } + + + public static class JDBC extends DatabaseConnectionPane { + private static JDBCDefPane jdbcDefPane = new JDBCDefPane(); + + @Override + protected JPanel mainPanel() { + return jdbcDefPane; + } + + @Override + protected boolean isFineBI() { + return false; + } + + @Override + protected void populateSubDatabaseConnectionBean(JDBCDatabaseConnection ob) { + jdbcDefPane.populate(ob); + } + + @Override + protected JDBCDatabaseConnection updateSubDatabaseConnectionBean() { + return jdbcDefPane.update(); + } + + @Override + protected String title4PopupWindow() { + return "JDBC"; + } + } + + public static class JNDI extends DatabaseConnectionPane { + private static JNDIDefPane jndiDefPane = new JNDIDefPane(); + + @Override + protected JPanel mainPanel() { + return jndiDefPane; + } + + @Override + protected boolean isFineBI() { + return false; + } + + @Override + protected void populateSubDatabaseConnectionBean(JNDIDatabaseConnection ob) { + jndiDefPane.populate(ob); + } + + @Override + protected JNDIDatabaseConnection updateSubDatabaseConnectionBean() { + return jndiDefPane.update(); + } + + @Override + protected String title4PopupWindow() { + return "JNDI"; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java b/designer_base/src/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java new file mode 100644 index 0000000000..ea08d29fee --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java @@ -0,0 +1,122 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public abstract class ItemEditableComboBoxPanel extends JPanel { + /** + * + */ + private static final long serialVersionUID = 1L; + + protected static final Object EMPTY = new Object() { + public String toString() { + return ""; + } + }; + + protected UIComboBox itemComboBox; + protected UIButton editButton; + protected UIButton refreshButton; + + public ItemEditableComboBoxPanel() { + super(); + + initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); + + itemComboBox = new UIComboBox(); + itemComboBox.setEnabled(true); + this.add(itemComboBox, BorderLayout.CENTER); + + editButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/control-center2.png")); + refreshButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + JPanel jPanel = FRGUIPaneFactory.createNColumnGridInnerContainer_Pane(2, 4 ,4); + jPanel.add(editButton); + jPanel.add(refreshButton); + this.add(jPanel, BorderLayout.EAST); + Dimension buttonSize = new Dimension(26, 20); + editButton.setPreferredSize(buttonSize); + editButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + editItems(); + } + }); + refreshButton.setPreferredSize(buttonSize); + refreshButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + refreshItems(); + } + }); + } + + /** + * 给itemComboBox添加ActionListener + */ + public void addComboBoxActionListener(ActionListener l) { + itemComboBox.addActionListener(l); + } + + /* + * 刷新itemComboBox的内容 + */ + protected void refreshItems() { + // 记录原来选中的Item,重新加载后需要再次选中 + Object lastSelectedItem = itemComboBox.getSelectedItem(); + + DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); + model.removeAllElements(); + + // 先加EMPTY,再加items + model.addElement(EMPTY); + + java.util.Iterator itemIt = items(); + while(itemIt.hasNext()) { + model.addElement(itemIt.next()); + } + + // 再次选中之前选中的Item + int idx = model.getIndexOf(lastSelectedItem); + if(idx < 0) { + idx = 0; + } + itemComboBox.setSelectedIndex(idx); + } + + /* + * 得到其中的itemComboBox所选中的Item + */ + public String getSelectedItem() { + Object selected = itemComboBox.getSelectedItem(); + + return selected instanceof String ? (String)selected : null; + } + + /* + * 选中name项 + */ + public void setSelectedItem(String name) { + DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel()); + model.setSelectedItem(name); + } + + /* + * 刷新ComboBox.items + */ + protected abstract java.util.Iterator items(); + + /* + * 弹出对话框编辑Items + */ + protected abstract void editItems(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/JDBCDefPane.java b/designer_base/src/com/fr/design/data/datapane/connect/JDBCDefPane.java new file mode 100644 index 0000000000..5e6cd1292a --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/JDBCDefPane.java @@ -0,0 +1,376 @@ +package com.fr.design.data.datapane.connect; + +import com.fr.design.constants.UIConstants; +import com.fr.data.impl.JDBCDatabaseConnection; +import com.fr.data.pool.DBCPConnectionPoolAttr; +import com.fr.design.border.UITitledBorder; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ipasswordfield.UIPassWordField; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.editor.IntegerEditor; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +public class JDBCDefPane extends JPanel { + public static final String DRIVER_TYPE = "driver_type"; + public static final String USER_NAME = "user_name"; + public static final int TIME_MULTIPLE = 1000; + + private static Map jdbcMap = new HashMap(); + + static { + jdbcMap.put("Others", new DriverURLName[]{new DriverURLName("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:"), + new DriverURLName("org.hsqldb.jdbcDriver", "jdbc:hsqldb:file:[PATH_TO_DB_FILES]"), new DriverURLName("com.inet.tds.TdsDriver", "jdbc:inetdae7:localhost:1433/"), + new DriverURLName("COM.cloudscape.JDBCDriver", "jdbc:cloudscape:/cloudscape/"), + new DriverURLName("com.internetcds.jdbc.tds.Driver", "jdbc:freetds:sqlserver://localhost/")}); +// jdbcMap.put("Hadoop Hive",new DriverURLName[]{new DriverURLName("org.apache.hadoop.hive.jdbc.HiveDriver","jdbc:hive://localhost:10000/default")}); + jdbcMap.put("Oracle", new DriverURLName[]{new DriverURLName("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@localhost:1521:databaseName")}); + jdbcMap.put("DB2", new DriverURLName[]{new DriverURLName("com.ibm.db2.jcc.DB2Driver", "jdbc:db2://localhost:50000/")}); + jdbcMap.put("SQL Server", new DriverURLName[]{new DriverURLName("com.microsoft.sqlserver.jdbc.SQLServerDriver", "jdbc:sqlserver://localhost:1433;" + "databaseName=")}); + jdbcMap.put("MySQL", new DriverURLName[]{new DriverURLName("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/"), + new DriverURLName("org.gjt.mm.mysql.Driver", "jdbc:mysql://localhost/")}); + jdbcMap.put("Sybase", new DriverURLName[]{new DriverURLName("com.sybase.jdbc2.jdbc.SybDriver", "jdbc:sybase:Tds:localhost:5000/")}); + jdbcMap.put("Access", new DriverURLName[]{new DriverURLName("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=")}); + jdbcMap.put("Derby", new DriverURLName[]{new DriverURLName("org.apache.derby.jdbc.ClientDriver", "jdbc:derby://localhost:1527/")}); + jdbcMap.put("Postgre", new DriverURLName[]{new DriverURLName("org.postgresql.Driver", "jdbc:postgresql://localhost:5432/")}); + jdbcMap.put("SQLite", new DriverURLName[]{new DriverURLName("org.sqlite.JDBC", "jdbc:sqlite://${ENV_HOME}/../FRDemo.db")}); + } + + private UIButton dbtypeButton; + private UIComboBox dbtypeComboBox; + private UIComboBox driverComboBox; + private UITextField urlTextField; + private UITextField userNameTextField; + private JPasswordField passwordTextField; + // 请不要改动dbtype,只应该最后添加 + private final String[] dbtype = {"", "Oracle", "DB2", "SQL Server", "MySQL", "Sybase", "Access", "Derby", "Postgre","SQLite", "Others"}; + + // carl:DBCP的一些属性 + private IntegerEditor DBCP_INITIAL_SIZE = new IntegerEditor(); + private IntegerEditor DBCP_MAX_ACTIVE = new IntegerEditor(); + private IntegerEditor DBCP_MAX_IDLE = new IntegerEditor(); + private IntegerEditor DBCP_MIN_IDLE = new IntegerEditor(); + private IntegerEditor DBCP_MAX_WAIT = new IntegerEditor(); + private UITextField DBCP_VALIDATION_QUERY = new UITextField(); + + private UIComboBox DBCP_TESTONBORROW = new UIComboBox(new String[]{Inter.getLocText("No"), Inter.getLocText("Yes")}); + private UIComboBox DBCP_TESTONRETURN = new UIComboBox(new String[]{Inter.getLocText("No"), Inter.getLocText("Yes")}); + private UIComboBox DBCP_TESTWHILEIDLE = new UIComboBox(new String[]{Inter.getLocText("No"), Inter.getLocText("Yes")}); + + private IntegerEditor DBCP_TIMEBETWEENEVICTIONRUNSMILLS = new IntegerEditor(); + private IntegerEditor DBCP_NUMTESTSPEREVICTIONRUN = new IntegerEditor(); + private IntegerEditor DBCP_MINEVICTABLEIDLETIMEMILLIS = new IntegerEditor(); + + public JDBCDefPane() { + this.setBorder(UITitledBorder.createBorderWithTitle("JDBC" + ":")); + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + JPanel innerthis = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + innerthis.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + this.add(innerthis); + dbtypeComboBox = new UIComboBox(); + dbtypeComboBox.setName(DRIVER_TYPE); + for (int i = 0; i < dbtype.length; i++) { + dbtypeComboBox.addItem(dbtype[i]); + } + dbtypeComboBox.addActionListener(dbtypeActionListener); + dbtypeComboBox.setMaximumRowCount(10); + + driverComboBox = new UIComboBox(); + driverComboBox.setEditable(true); + driverComboBox.addActionListener(driverListener); + urlTextField = new UITextField(15); + userNameTextField = new UITextField(15); + userNameTextField.setName(USER_NAME); + passwordTextField = new UIPassWordField(15); + dbtypeButton = new UIButton("."); + dbtypeButton.setToolTipText(Inter.getLocText("Click-Get_Default_URL")); + dbtypeButton.addActionListener(dbtypeButtonActionListener); + + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + JPanel dbtypePane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + dbtypePane.add(new UILabel((Inter.getLocText("Database") + ":"))); + JPanel dbtypeComPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + Component[][] dbtypeComComponents = {{dbtypeComboBox}}; + double[] dbtypeRowSize = {p}; + double[] dbtypeColumnSize = {p}; + dbtypeComPane = TableLayoutHelper.createTableLayoutPane(dbtypeComComponents, dbtypeRowSize, dbtypeColumnSize); + + JPanel driverPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + driverPane.add(new UILabel(Inter.getLocText("Driver") + ":")); + + JPanel urlPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + urlPane.add(new UILabel("URL:")); + JPanel urlComPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + Component[][] urlComComponents = {{urlTextField, dbtypeButton}}; + double[] urlRowSize = {p}; + double[] urlColumnSize = {f, 21}; + urlComPane = TableLayoutHelper.createCommonTableLayoutPane(urlComComponents, urlRowSize, urlColumnSize, 4); + + JPanel userPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + userPane.add(new UILabel(Inter.getLocText("Username") + ":")); + JPanel userComPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + Component[][] userComComponents = {{userNameTextField, new UILabel(Inter.getLocText("Password") + ":"), passwordTextField}}; + double[] userRowSize = {p}; + double[] userColumnSize = {f, p, f}; + userComPane = TableLayoutHelper.createCommonTableLayoutPane(userComComponents, userRowSize, userColumnSize, 4); + + JPanel passwordPane = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + passwordPane.add(new UILabel(Inter.getLocText("Password") + ":")); + + Component[][] components = {{dbtypePane, dbtypeComPane}, {driverPane, driverComboBox}, {urlPane, urlComPane}, {userPane, userComPane},}; + + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, f, 22}; + JPanel centerPanel = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, 0, 6); + innerthis.add(centerPanel); + JPanel southPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + innerthis.add(southPanel); + southPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 4, 20)); + ActionLabel actionLabel = new ActionLabel(Inter.getLocText("ConnectionPool_Attr")); + southPanel.add(actionLabel, BorderLayout.EAST); + actionLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + JDialog wDialog = createJDialog(); + wDialog.setVisible(true); + } + }); + } + + public void populate(JDBCDatabaseConnection jdbcDatabase) { + if (jdbcDatabase == null) { + jdbcDatabase = new JDBCDatabaseConnection(); + } + if (ComparatorUtils.equals(jdbcDatabase.getDriver(), "sun.jdbc.odbc.JdbcOdbcDriver") + && jdbcDatabase.getURL().startsWith("jdbc:odbc:Driver={Microsoft")) { + this.dbtypeComboBox.setSelectedItem("Access"); + } else { + Iterator> jdbc = jdbcMap.entrySet().iterator(); + boolean out = false; + while (jdbc.hasNext()) { + Entry entry = jdbc.next(); + DriverURLName[] dus = entry.getValue(); + for (int i = 0, len = dus.length; i < len; i++) { + if (ComparatorUtils.equals(dus[i].getDriver(), jdbcDatabase.getDriver())) { + this.dbtypeComboBox.setSelectedItem(entry.getKey()); + out = true; + break; + } + } + if (out) { + break; + } + } + } + this.driverComboBox.setSelectedItem(jdbcDatabase.getDriver()); + this.urlTextField.setText(jdbcDatabase.getURL()); + this.userNameTextField.setText(jdbcDatabase.getUser()); + this.passwordTextField.setText(jdbcDatabase.getPassword()); + + DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr(); + if (dbcpAttr == null) { + dbcpAttr = new DBCPConnectionPoolAttr(); + jdbcDatabase.setDbcpAttr(dbcpAttr); + } + this.DBCP_INITIAL_SIZE.setValue(dbcpAttr.getInitialSize()); + this.DBCP_MAX_ACTIVE.setValue(dbcpAttr.getMaxActive()); + this.DBCP_MAX_IDLE.setValue(dbcpAttr.getMaxIdle()); + this.DBCP_MAX_WAIT.setValue(dbcpAttr.getMaxWait()); + this.DBCP_MIN_IDLE.setValue(dbcpAttr.getMinIdle()); + this.DBCP_VALIDATION_QUERY.setText(dbcpAttr.getValidationQuery()); + this.DBCP_TESTONBORROW.setSelectedIndex(dbcpAttr.isTestOnBorrow() ? 1 : 0); + this.DBCP_TESTONRETURN.setSelectedIndex(dbcpAttr.isTestOnReturn() ? 1 : 0); + this.DBCP_TESTWHILEIDLE.setSelectedIndex(dbcpAttr.isTestWhileIdle() ? 1 : 0); + this.DBCP_MINEVICTABLEIDLETIMEMILLIS.setValue(dbcpAttr.getMinEvictableIdleTimeMillis() / TIME_MULTIPLE); + this.DBCP_NUMTESTSPEREVICTIONRUN.setValue(dbcpAttr.getNumTestsPerEvictionRun()); + this.DBCP_TIMEBETWEENEVICTIONRUNSMILLS.setValue(dbcpAttr.getTimeBetweenEvictionRunsMillis()); + } + + public JDBCDatabaseConnection update() { + JDBCDatabaseConnection jdbcDatabase = new JDBCDatabaseConnection(); + Object driveItem = this.driverComboBox.getSelectedItem(); + jdbcDatabase.setDriver(driveItem == null ? null : driveItem.toString()); + jdbcDatabase.setURL(this.urlTextField.getText().trim()); + jdbcDatabase.setUser(this.userNameTextField.getText().trim()); + jdbcDatabase.setPassword(new String(this.passwordTextField.getPassword()).trim()); + + DBCPConnectionPoolAttr dbcpAttr = jdbcDatabase.getDbcpAttr(); + if (dbcpAttr == null) { + dbcpAttr = new DBCPConnectionPoolAttr(); + jdbcDatabase.setDbcpAttr(dbcpAttr); + } + dbcpAttr.setInitialSize(this.DBCP_INITIAL_SIZE.getValue().intValue()); + dbcpAttr.setMaxActive(this.DBCP_MAX_ACTIVE.getValue().intValue()); + dbcpAttr.setMaxIdle(this.DBCP_MAX_IDLE.getValue().intValue()); + dbcpAttr.setMaxWait(this.DBCP_MAX_WAIT.getValue().intValue()); + dbcpAttr.setMinIdle(this.DBCP_MIN_IDLE.getValue().intValue()); + dbcpAttr.setValidationQuery(this.DBCP_VALIDATION_QUERY.getText()); + dbcpAttr.setTestOnBorrow(this.DBCP_TESTONBORROW.getSelectedIndex() == 0 ? false : true); + dbcpAttr.setTestOnReturn(this.DBCP_TESTONRETURN.getSelectedIndex() == 0 ? false : true); + dbcpAttr.setTestWhileIdle(this.DBCP_TESTWHILEIDLE.getSelectedIndex() == 0 ? false : true); + dbcpAttr.setMinEvictableIdleTimeMillis(((Number) this.DBCP_MINEVICTABLEIDLETIMEMILLIS.getValue()).intValue() * TIME_MULTIPLE); + dbcpAttr.setNumTestsPerEvictionRun(((Number) this.DBCP_NUMTESTSPEREVICTIONRUN.getValue()).intValue()); + dbcpAttr.setTimeBetweenEvictionRunsMillis(((Number) this.DBCP_TIMEBETWEENEVICTIONRUNSMILLS.getValue()).intValue()); + + return jdbcDatabase; + } + + ActionListener dbtypeActionListener = new ActionListener() { + public void actionPerformed(ActionEvent evt) { + + urlTextField.setText(StringUtils.EMPTY); + driverComboBox.removeAllItems(); + if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), StringUtils.EMPTY)) { + driverComboBox.setSelectedItem(StringUtils.EMPTY); + return; + } + + DriverURLName[] dus = jdbcMap.get(dbtypeComboBox.getSelectedItem()); + for (int i = 0, len = dus.length; i < len; i++) { + driverComboBox.addItem(dus[i].getDriver()); + if (i == 0) { + driverComboBox.setSelectedItem(dus[i].getDriver()); + urlTextField.setText(dus[i].getURL()); + } + } + } + }; + + ActionListener driverListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (driverComboBox.getSelectedItem() == null ||ComparatorUtils.equals(driverComboBox.getSelectedItem(), StringUtils.EMPTY)) { + return; + } + Iterator> jdbc = jdbcMap.entrySet().iterator(); + while (jdbc.hasNext()) { + Entry entry = jdbc.next(); + DriverURLName[] dus = entry.getValue(); + for (int i = 0, len = dus.length; i < len; i++) { + if (ComparatorUtils.equals(dus[i].getDriver(), (driverComboBox.getSelectedItem()))) { + urlTextField.setText(dus[i].getURL()); + return; + } + } + } + } + + }; + + ActionListener dbtypeButtonActionListener = new ActionListener() { + public void actionPerformed(ActionEvent evt) { + if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), StringUtils.EMPTY)) { + return; + } + DriverURLName[] dus = jdbcMap.get(dbtypeComboBox.getSelectedItem()); + for (int i = 0, len = dus.length; i < len; i++) { + if (ComparatorUtils.equals(driverComboBox.getSelectedItem(), (dus[i].getDriver()))) { + urlTextField.setText(dus[i].getURL()); + if (ComparatorUtils.equals(dbtypeComboBox.getSelectedItem(), ("Access"))) { + // ben:这个能不能换种处理方案- - + JFileChooser filechooser = new JFileChooser(); + filechooser.setDialogTitle(Inter.getLocText("Open")); + filechooser.setMultiSelectionEnabled(false); + filechooser.addChoosableFileFilter(new ChooseFileFilter(new String[]{"accdb", "mdb"}, "Microsoft Office Access")); + int result = filechooser.showOpenDialog(DesignerContext.getDesignerFrame()); + File selectedfile = null; + + if (result == JFileChooser.APPROVE_OPTION) { + selectedfile = filechooser.getSelectedFile(); + if (selectedfile != null) { + String selectedName = selectedfile.getPath().substring(selectedfile.getPath().lastIndexOf('.') + 1); + if (selectedName.equalsIgnoreCase("mdb") || selectedName.equalsIgnoreCase("accdb")) { + urlTextField.setText(urlTextField.getText() + selectedfile.getPath()); + } + } + } + } + break; + } + } + } + }; + + private JDialog createJDialog() { + return new DBCPAttrPane().showWindow(SwingUtilities.getWindowAncestor(JDBCDefPane.this)); + } + + class DBCPAttrPane extends BasicPane { + public DBCPAttrPane() { + JPanel defaultPane = this; + + // JPanel northFlowPane + JPanel northFlowPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + defaultPane.add(northFlowPane, BorderLayout.NORTH); + + DBCP_VALIDATION_QUERY.setColumns(15); + // ContextPane + + double f = TableLayout.FILL; + // double p = TableLayout.PREFERRED; + double[] rowSize = {f, f, f, f, f, f, f, f, f, f, f, f}; + double[] columnSize = {f, f}; + Component[][] comps = { + {new UILabel(Inter.getLocText("DBCP_INITIAL_SIZE") + ":", SwingConstants.RIGHT), DBCP_INITIAL_SIZE}, + {new UILabel(Inter.getLocText("DBCP_MAX_ACTIVE") + ":", SwingConstants.RIGHT), DBCP_MAX_ACTIVE}, + {new UILabel(Inter.getLocText("DBCP_MAX_IDLE") + ":", SwingConstants.RIGHT), DBCP_MAX_IDLE}, + {new UILabel(Inter.getLocText("DBCP_MIN_IDLE") + ":", SwingConstants.RIGHT), DBCP_MIN_IDLE}, + {new UILabel(Inter.getLocText(new String[] {"DBCP_MAX_WAIT", "Milliseconds"},new String[] {"(", "):"}) , SwingConstants.RIGHT), DBCP_MAX_WAIT}, + {new UILabel(Inter.getLocText("DBCP_VALIDATION_QUERY") + ":", SwingConstants.RIGHT), DBCP_VALIDATION_QUERY}, + {new UILabel(Inter.getLocText("DBCP_TEST_ON_BORROW") + ":", SwingConstants.RIGHT), DBCP_TESTONBORROW}, + {new UILabel(Inter.getLocText("DBCP_TEST_ON_RETURN") + ":", SwingConstants.RIGHT), DBCP_TESTONRETURN}, + {new UILabel(Inter.getLocText("DBCP_TEST_WHILE_IDLE") + ":", SwingConstants.RIGHT), DBCP_TESTWHILEIDLE}, + {new UILabel(Inter.getLocText(new String[] {"DBCP_TIME_BETWEEN_EVICTIONRUNSMILLIS", "Milliseconds"}, new String[] {"(", "):"}), SwingConstants.RIGHT), + DBCP_TIMEBETWEENEVICTIONRUNSMILLS}, + {new UILabel(Inter.getLocText("DBCP_NUM_TEST_PER_EVCTION_RUN") + ":", SwingConstants.RIGHT), DBCP_NUMTESTSPEREVICTIONRUN}, + {new UILabel(Inter.getLocText(new String[] {"DBCP_MIN_EVICTABLE_IDLE_TIMEMILLIS", "Sche-Second"}, new String[] {"(", "):"}) , SwingConstants.RIGHT), + DBCP_MINEVICTABLEIDLETIMEMILLIS}}; + + JPanel contextPane = TableLayoutHelper.createGapTableLayoutPane(comps, rowSize, columnSize, 10, 4); + contextPane.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, UIConstants.LINE_COLOR)); + northFlowPane.add(contextPane); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("ConnectionPool_Attr"); + } + } + + private static class DriverURLName { + public DriverURLName(String driver, String url) { + this.driver = driver; + this.url = url; + } + + public String getDriver() { + return this.driver; + } + + public String getURL() { + return this.url; + } + + private String driver; + private String url; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/connect/JNDIDefPane.java b/designer_base/src/com/fr/design/data/datapane/connect/JNDIDefPane.java new file mode 100644 index 0000000000..f541f548cb --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/connect/JNDIDefPane.java @@ -0,0 +1,266 @@ +package com.fr.design.data.datapane.connect; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; + +import javax.naming.Context; +import javax.swing.BorderFactory; +import javax.swing.JDialog; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; + +import com.fr.data.impl.JNDIDatabaseConnection; +import com.fr.design.border.UITitledBorder; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.FRExplainLabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.dialog.BasicPane; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +public class JNDIDefPane extends JPanel { + private static Map jndiMap = new HashMap(); + + static { + jndiMap.put("weblogic.jndi.WLInitialContextFactory", "t3://localhost:7001"); + jndiMap.put("com.ibm.websphere.naming.WsnInitialContextFactory", "iiop://localhost:2809"); + jndiMap.put("org.jboss.naming.HttpNamingContextFactory", "http://jboss_server_address:8080/invoker/JNDIFactory"); + jndiMap.put("org.jnp.interfaces.NamingContextFactory", "localhost:1099"); + jndiMap.put("com.caucho.burlap.BurlapContextFactory", "http://localhost:8080/hello/burlap"); + } + + private UITextField jndiNameTextField; + + private UIComboBox JNDIFactoryComboBox; + private ContextTextField PROVIDER_URL_TF = new ContextTextField(Context.PROVIDER_URL); + private ContextTextField SECURITY_PRINCIPAL_TF = new ContextTextField(Context.SECURITY_PRINCIPAL); + private ContextTextField SECURITY_CREDENTIALS_TF = new ContextTextField(Context.SECURITY_CREDENTIALS); + + private ContextTextField OBJECT_FACTORIES_TF = new ContextTextField(Context.OBJECT_FACTORIES); + private ContextTextField STATE_FACTORIES_TF = new ContextTextField(Context.STATE_FACTORIES); + private ContextTextField URL_PKG_PREFIXES_TF = new ContextTextField(Context.URL_PKG_PREFIXES); + private ContextTextField DNS_URL_TF = new ContextTextField(Context.DNS_URL); + private ContextTextField AUTHORITATIVE_TF = new ContextTextField(Context.AUTHORITATIVE); + private ContextTextField BATCHSIZE_TF = new ContextTextField(Context.BATCHSIZE); + private ContextTextField REFERRAL_TF = new ContextTextField(Context.REFERRAL); + private ContextTextField SECURITY_PROTOCOL_TF = new ContextTextField(Context.SECURITY_PROTOCOL); + private ContextTextField SECURITY_AUTHENTICATION_TF = new ContextTextField(Context.SECURITY_AUTHENTICATION); + private ContextTextField LANGUAGE_TF = new ContextTextField(Context.LANGUAGE); + private ContextTextField APPLET_TF = new ContextTextField(Context.APPLET); + + private JDialog otherAttrDialog; + + public JNDIDefPane() { + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + this.setBorder(UITitledBorder.createBorderWithTitle("JNDI" + ":")); + JPanel innerthis = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + this.add(innerthis); + // NorthPane + JPanel nContentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + innerthis.add(nContentPane); + nContentPane.add(new UILabel(Inter.getLocText("Datasource-JNDI_Name") + ":")); + jndiNameTextField = new UITextField(20); + nContentPane.add(jndiNameTextField, BorderLayout.NORTH); + + // CenterPane + JPanel outcenterPane = FRGUIPaneFactory.createTitledBorderPane(Inter.getLocText("Datasource-Context")); + innerthis.add(outcenterPane); + JPanel centerPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_M_Pane(); + outcenterPane.add(centerPane); + + JNDIFactoryComboBox = new UIComboBox(new String[] { "", "weblogic.jndi.WLInitialContextFactory", "com.ibm.websphere.naming.WsnInitialContextFactory", + "org.jboss.naming.HttpNamingContextFactory", "org.jnp.interfaces.NamingContextFactory", "com.caucho.burlap.BurlapContextFactory", }); + JNDIFactoryComboBox.setEditable(true); + + JNDIFactoryComboBox.addActionListener(jndiListener); + JNDIFactoryComboBox.setPreferredSize(new Dimension(30, JNDIFactoryComboBox.getPreferredSize().height + 2)); + + // ContextPane + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double[] rowSize = { p, p, p, p }; + double[] columnSize = { f, f }; + Component[][] comps = { { new UILabel("INITIAL_CONTEXT_FACTORY:", SwingConstants.RIGHT), JNDIFactoryComboBox }, + { new UILabel("PROVIDER_URL:", SwingConstants.RIGHT), PROVIDER_URL_TF }, { new UILabel("SECURITY_PRINCIPAL:", SwingConstants.RIGHT), SECURITY_PRINCIPAL_TF }, + { new UILabel("SECURITY_CREDENTIALS:", SwingConstants.RIGHT), SECURITY_CREDENTIALS_TF } }; + centerPane.add(TableLayoutHelper.createCommonTableLayoutPane(comps, rowSize, columnSize, 2)); + + // ActionLabel + JPanel actionPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + centerPane.add(actionPane); + actionPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 6)); + + ActionLabel actionLabel = new ActionLabel(Inter.getLocText("Datasource-Other_Attributes")); + actionPane.add(actionLabel, BorderLayout.EAST); + actionLabel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + JDialog wDialog = createJDialog(); + wDialog.setVisible(true); + } + }); + + // South Description + UILabel explainLabe11l = new FRExplainLabel(Inter.getLocText("Datasource-JNDI_DES")); + innerthis.add(new JScrollPane(explainLabe11l)); + } + + public void populate(JNDIDatabaseConnection jndiDatabase) { + if (jndiDatabase == null) { + jndiDatabase = new JNDIDatabaseConnection(); + } + + // Properties. + Hashtable contextHashtable = jndiDatabase.getContextHashtable(); + Object INITIAL_CONTEXT_FACTORY = contextHashtable.get(Context.INITIAL_CONTEXT_FACTORY); + + this.JNDIFactoryComboBox.setSelectedItem(INITIAL_CONTEXT_FACTORY == null ? "" : INITIAL_CONTEXT_FACTORY); + this.jndiNameTextField.setText(jndiDatabase.getJNDIName() == null ? "" : jndiDatabase.getJNDIName()); + populateContextAttributes(contextHashtable, this.PROVIDER_URL_TF, Context.PROVIDER_URL); + populateContextAttributes(contextHashtable, this.SECURITY_PRINCIPAL_TF, Context.SECURITY_PRINCIPAL); + populateContextAttributes(contextHashtable, this.SECURITY_CREDENTIALS_TF, Context.SECURITY_CREDENTIALS); + + populateContextAttributes(contextHashtable, this.OBJECT_FACTORIES_TF, Context.OBJECT_FACTORIES); + populateContextAttributes(contextHashtable, this.STATE_FACTORIES_TF, Context.STATE_FACTORIES); + populateContextAttributes(contextHashtable, this.URL_PKG_PREFIXES_TF, Context.URL_PKG_PREFIXES); + + populateContextAttributes(contextHashtable, this.DNS_URL_TF, Context.DNS_URL); + populateContextAttributes(contextHashtable, this.AUTHORITATIVE_TF, Context.AUTHORITATIVE); + populateContextAttributes(contextHashtable, this.BATCHSIZE_TF, Context.BATCHSIZE); + populateContextAttributes(contextHashtable, this.REFERRAL_TF, Context.REFERRAL); + populateContextAttributes(contextHashtable, this.SECURITY_PROTOCOL_TF, Context.SECURITY_PROTOCOL); + populateContextAttributes(contextHashtable, this.SECURITY_AUTHENTICATION_TF, Context.SECURITY_AUTHENTICATION); + populateContextAttributes(contextHashtable, this.LANGUAGE_TF, Context.LANGUAGE); + populateContextAttributes(contextHashtable, this.APPLET_TF, Context.APPLET); + } + + private void populateContextAttributes(Hashtable properties, UITextField textField, String contextAttr) { + String PROVIDER_URL = properties.get(contextAttr); + if (PROVIDER_URL != null) { + textField.setText(PROVIDER_URL); + } + } + + public JNDIDatabaseConnection update() { + JNDIDatabaseConnection jndiDatabase = new JNDIDatabaseConnection(); + + jndiDatabase.setJNDIName(this.jndiNameTextField.getText()); + + Hashtable contextHashtable = jndiDatabase.getContextHashtable(); + + String factoryString = (String)this.JNDIFactoryComboBox.getEditor().getItem(); + if (factoryString != null && factoryString.trim().length() > 0) { + contextHashtable.put(Context.INITIAL_CONTEXT_FACTORY, factoryString); + } + updateContextAttributes(contextHashtable, this.PROVIDER_URL_TF, Context.PROVIDER_URL); + updateContextAttributes(contextHashtable, this.SECURITY_PRINCIPAL_TF, Context.SECURITY_PRINCIPAL); + updateContextAttributes(contextHashtable, this.SECURITY_CREDENTIALS_TF, Context.SECURITY_CREDENTIALS); + + updateContextAttributes(contextHashtable, this.OBJECT_FACTORIES_TF, Context.OBJECT_FACTORIES); + updateContextAttributes(contextHashtable, this.STATE_FACTORIES_TF, Context.STATE_FACTORIES); + updateContextAttributes(contextHashtable, this.URL_PKG_PREFIXES_TF, Context.URL_PKG_PREFIXES); + + updateContextAttributes(contextHashtable, this.DNS_URL_TF, Context.DNS_URL); + updateContextAttributes(contextHashtable, this.AUTHORITATIVE_TF, Context.AUTHORITATIVE); + updateContextAttributes(contextHashtable, this.BATCHSIZE_TF, Context.BATCHSIZE); + updateContextAttributes(contextHashtable, this.REFERRAL_TF, Context.REFERRAL); + updateContextAttributes(contextHashtable, this.SECURITY_PROTOCOL_TF, Context.SECURITY_PROTOCOL); + updateContextAttributes(contextHashtable, this.SECURITY_AUTHENTICATION_TF, Context.SECURITY_AUTHENTICATION); + updateContextAttributes(contextHashtable, this.LANGUAGE_TF, Context.LANGUAGE); + updateContextAttributes(contextHashtable, this.APPLET_TF, Context.APPLET); + + return jndiDatabase; + } + + private void updateContextAttributes(Hashtable contextHashtable, UITextField textField, String contextAttr) { + String tValue = textField.getText(); + if (tValue != null && tValue.trim().length() > 0) { + contextHashtable.put(contextAttr, tValue); + } + } + + ActionListener jndiListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + Object o = JNDIFactoryComboBox.getSelectedItem(); + if (o == null || ComparatorUtils.equals(o, StringUtils.EMPTY)) { + PROVIDER_URL_TF.setText(""); + return; + } + PROVIDER_URL_TF.setText(jndiMap.get(o)); + } + + }; + + private JDialog createJDialog() { + if (this.otherAttrDialog == null) { + this.otherAttrDialog = new OtherAttrPane().showWindow(SwingUtilities.getWindowAncestor(JNDIDefPane.this)); + } + + return this.otherAttrDialog; + } + + class OtherAttrPane extends BasicPane { + public OtherAttrPane() { + // JPanel northFlowPane + JPanel northFlowPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_L_Pane(); + this.add(northFlowPane, BorderLayout.NORTH); + + // ContextPane + double f = TableLayout.FILL; + double[] rowSize = { f, f, f, f, f, f, f, f, f, f, f }; + double[] columnSize = { f, f }; + Component[][] comps = { { new UILabel("OBJECT_FACTORIES:", SwingConstants.RIGHT), OBJECT_FACTORIES_TF }, + { new UILabel("STATE_FACTORIES:", SwingConstants.RIGHT), STATE_FACTORIES_TF }, { new UILabel("URL_PKG_PREFIXES:", SwingConstants.RIGHT), URL_PKG_PREFIXES_TF }, + { new UILabel("DNS_URL:", SwingConstants.RIGHT), DNS_URL_TF }, { new UILabel("AUTHORITATIVE:", SwingConstants.RIGHT), AUTHORITATIVE_TF }, + { new UILabel("BATCHSIZE:", SwingConstants.RIGHT), BATCHSIZE_TF }, { new UILabel("REFERRAL:", SwingConstants.RIGHT), REFERRAL_TF }, + { new UILabel("SECURITY_PROTOCOL:", SwingConstants.RIGHT), SECURITY_PROTOCOL_TF }, + { new UILabel("SECURITY_AUTHENTICATION:", SwingConstants.RIGHT), SECURITY_AUTHENTICATION_TF }, { new UILabel("LANGUAGE:", SwingConstants.RIGHT), LANGUAGE_TF }, + { new UILabel("APPLET:", SwingConstants.RIGHT), APPLET_TF } }; + northFlowPane.add(TableLayoutHelper.createCommonTableLayoutPane(comps, rowSize, columnSize, 2)); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Datasource-Other_Attributes"); + } + } + + // 主力Context属性 + class ContextTextField extends UITextField { + private String contextName; + + public ContextTextField(String contextName) { + this.setContextName(contextName); + this.setColumns(24); + } + + public String getContextName() { + return contextName; + } + + public void setContextName(String contextName) { + this.contextName = contextName; + } + + /* + * 更新Properties. + */ + public void applyProperties(Properties properties) { + properties.put(contextName, this.getText()); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/preview/LoadedEventListener.java b/designer_base/src/com/fr/design/data/datapane/preview/LoadedEventListener.java new file mode 100644 index 0000000000..ac91006cf0 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/preview/LoadedEventListener.java @@ -0,0 +1,18 @@ +/* + * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.data.datapane.preview; + +import java.util.EventListener; + +/** + * Created by IntelliJ IDEA. + * User : Richer + * Version: 6.5.5 + * Date : 11-7-7 + * Time : 下午5:32 + */ +public interface LoadedEventListener extends EventListener { + + public void fireLoaded(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/preview/PreviewLabel.java b/designer_base/src/com/fr/design/data/datapane/preview/PreviewLabel.java new file mode 100644 index 0000000000..ce82e0bad5 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/preview/PreviewLabel.java @@ -0,0 +1,37 @@ +package com.fr.design.data.datapane.preview; + +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.general.Inter; + + + + +public class PreviewLabel extends UIButton { + Previewable previewable; + + public PreviewLabel(Previewable previewable) { + super(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + this.setToolTipText(Inter.getLocText("Preview")); + this.setCursor(new Cursor(Cursor.HAND_CURSOR)); + this.previewable = previewable; + this.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + PreviewLabel.this.previewable.preview(); + } + }); + this.setPreferredSize(new Dimension(24, 20)); + } + + public static interface Previewable { + public void preview(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/preview/PreviewTableModel.java b/designer_base/src/com/fr/design/data/datapane/preview/PreviewTableModel.java new file mode 100644 index 0000000000..d7918609c1 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/preview/PreviewTableModel.java @@ -0,0 +1,212 @@ +package com.fr.design.data.datapane.preview; + +import javax.swing.table.AbstractTableModel; + +import com.fr.base.FRContext; +import com.fr.data.AbstractDataModel; +import com.fr.data.impl.EmbeddedTableData.EmbeddedTDDataModel; +import com.fr.data.impl.storeproc.ProcedureDataModel; +import com.fr.env.RemoteEnv; +import com.fr.general.Inter; +import com.fr.general.data.DataModel; +import com.fr.general.data.TableDataException; +import com.fr.cache.list.IntList; +import com.fr.stable.StringUtils; +import com.fr.design.utils.DesignUtils; + +/** + * 这个TableModel主要是预览数据的. 字段TableData必须转化为内置的 + */ +public class PreviewTableModel extends AbstractTableModel { + private DataModel dataModel; + private String erroMessage = null; + + public IntList dateIndexs = new IntList(4); + + public PreviewTableModel(int maxRowCount) { + // peter:默认必须显示错误的数据源. + this(new ErrorResultSet(), maxRowCount); + } + + public PreviewTableModel(DataModel sourceResultSet, int maxRowCount) { + if (sourceResultSet instanceof ProcedureDataModel) { + ProcedureDataModel rs = (ProcedureDataModel) sourceResultSet; + try { + this.dataModel = createRowDataModel(rs, maxRowCount); + } catch (TableDataException e) { + // TODO Auto-generated catch block + FRContext.getLogger().error(e.getMessage(), e); + } + } else { + this.dataModel = sourceResultSet; + } + } + + public static DataModel createRowDataModel(final ProcedureDataModel rs, int maxRowCount) throws TableDataException { + int rowCount = rs.getRowCount(); + if (maxRowCount == 0) { + maxRowCount = rowCount; + } else if (maxRowCount > rowCount) { + maxRowCount = rowCount; + } + final int finalRowCount = maxRowCount; + DataModel dm = new DataModel() { + + @Override + public void release() throws Exception { + rs.release(); + } + + @Override + public boolean hasRow(int rowIndex) throws TableDataException { + return rowIndex <= finalRowCount - 1 && rowIndex >= 0; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + throws TableDataException { + return rs.getValueAt(rowIndex, columnIndex); + } + + @Override + public int getRowCount() throws TableDataException { + return finalRowCount; + } + + @Override + public String getColumnName(int columnIndex) throws TableDataException { + return rs.getColumnName(columnIndex); + } + + @Override + public int getColumnCount() throws TableDataException { + return rs.getColumnCount(); + } + }; + return dm; + } + + public String getErrMessage() { + return this.erroMessage; + } + + public void setErrMessage(String err) { + this.erroMessage = err; + } + + public String getColumnName(int column) { + try { + return Integer.toString(column + 1) + ". " + dataModel.getColumnName(column) + checkType(column); + } catch (TableDataException e) { + FRContext.getLogger().error(e.getMessage(), e); + DesignUtils.errorMessage(e.getMessage()); + return Inter.getLocText("Error"); + } + } + + public int getRowCount() { + try { + return this.dataModel.getRowCount(); + } catch (TableDataException e) { + FRContext.getLogger().error(e.getMessage(), e); + return 0; + } + } + + public int getColumnCount() { + try { + if (dataModel == null) { + return 0; + } + return dataModel.getColumnCount(); + } catch (TableDataException e) { + FRContext.getLogger().error(e.getMessage(), e); + DesignUtils.errorMessage(e.getMessage()); + return 0; + } + } + + public Object getValueAt(int row, int column) { + try { + return dataModel.getValueAt(row, column); + } catch (TableDataException e) { + FRContext.getLogger().error(e.getMessage(), e); + DesignUtils.errorMessage(e.getMessage()); + return ""; + } + } + + /* + * peter:由于如果预览的TableData发生错误,界面有点象死机了一样,晕啊. + * 就是由于预览的JTable在不停的getRowCount来显示数据. + */ + private static class ErrorResultSet extends AbstractDataModel { + public ErrorResultSet() { + } + + public int getRowCount() { + return 0; + } + + public String getColumnName(int column) { + return Inter.getLocText("Error"); + } + + public int getColumnCount() { + return 1; + } + + public Object getValueAt(int row, int column) { + return ""; + } + + public void release() throws Exception { + } + } + + private String checkType(int column) { + if (dateIndexs.contain(column)) { + String s = Inter.getLocText("Date"); + return ("(" + s + ")"); + } + + String s = StringUtils.EMPTY; + Object o = null; + try { + for (int i = 0; i < dataModel.getRowCount(); i++) { + o = dataModel.getRowCount() <= 0 ? null : dataModel.getValueAt(i, column); + + if (o != null && StringUtils.isNotEmpty(o.toString())) { + break; + } + } + } catch (TableDataException e) { + return ("(?)"); + } + + if (o == null) { + s = "?"; + } else if (o instanceof String) { + s = Inter.getLocText("Parameter-String"); + if (FRContext.getCurrentEnv() instanceof RemoteEnv && dataModel instanceof EmbeddedTDDataModel) { + Class clzz = ((EmbeddedTDDataModel) dataModel).getColumnClass(column); + if (Number.class.isAssignableFrom(clzz)) { + s = Inter.getLocText("Number");//bigdecimal + } else if (java.sql.Date.class.isAssignableFrom(clzz)) { + s = Inter.getLocText("Date"); + } + } + } else if (o instanceof Integer) { + s = Inter.getLocText("Integer"); + } else if (o instanceof Double || o instanceof Float) { + s = Inter.getLocText("Double"); + } else if (o instanceof java.sql.Date || o instanceof java.util.Date) { + s = Inter.getLocText("Date"); + } else if (o instanceof Number) { + s = Inter.getLocText("Number");//bigdecimal + } else { + s = "?"; + } + return ("(" + s + ")"); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/preview/PreviewTablePane.java b/designer_base/src/com/fr/design/data/datapane/preview/PreviewTablePane.java new file mode 100644 index 0000000000..28e421b542 --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/preview/PreviewTablePane.java @@ -0,0 +1,482 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.data.datapane.preview; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.TableData; +import com.fr.data.impl.DBTableData; +import com.fr.data.impl.EmbeddedTableData; +import com.fr.data.impl.storeproc.ProcedureDataModel; +import com.fr.design.DesignerEnvManager; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.iprogressbar.AutoProgressBar; +import com.fr.design.gui.itable.SortableJTable; +import com.fr.design.gui.itable.TableSorter; +import com.fr.design.gui.itextfield.UINumberField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.function.TIME; +import com.fr.general.FRFont; +import com.fr.general.Inter; + +import javax.swing.*; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Date; +import java.util.concurrent.CancellationException; + +/** + * august: PreviewTablePane一共提供5个共有的静态方法,用来预览。 + */ +public class PreviewTablePane extends BasicPane { + private TableData tableData; + private ProcedureDataModel storeProcedureDataModel; + private static UINumberField maxPreviewNumberField; + private UINumberField currentRowsField; + private JTable preveiwTable; + private static AutoProgressBar progressBar; + private AutoProgressBar connectionBar; + private java.util.List listeners = new ArrayList(); + private BasicDialog dialog; + private SwingWorker worker; + + private UILabel refreshLabel; + private static PreviewTablePane THIS; + private EmbeddedTableData previewTableData; + + public static final PreviewTablePane getInstance() { + if (THIS == null) { + THIS = new PreviewTablePane(); + } + return THIS; + } + + private PreviewTablePane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + // elalke:预览行数 + JPanel previewNumberPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + this.add(previewNumberPanel, BorderLayout.NORTH); + + JPanel currentPreviewPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + previewNumberPanel.add(currentPreviewPanel); + currentPreviewPanel.add(new UILabel(Inter.getLocText("FR-Designer_Current_Preview_Rows") + ":")); + + currentRowsField = new UINumberField(); + currentPreviewPanel.add(currentRowsField); + currentRowsField.setEditable(false); + currentRowsField.setColumns(4); + currentRowsField.setInteger(true); + + JPanel maxPanel = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + previewNumberPanel.add(maxPanel); + maxPanel.add(new UILabel(Inter.getLocText("Datasource-Maximum_Number_of_Preview_Rows") + ":")); + + maxPreviewNumberField = new UINumberField(); + maxPanel.add(maxPreviewNumberField); + maxPreviewNumberField.setColumns(4); + maxPreviewNumberField.setInteger(true); + + DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager(); + maxPreviewNumberField.setValue(designerEnvManager.getMaxNumberOrPreviewRow()); + + maxPreviewNumberField.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager(); + designerEnvManager.setMaxNumberOrPreviewRow((int) ((UINumberField) evt.getSource()).getValue()); + } + }); + + Icon refreshImage = BaseUtils.readIcon("/com/fr/design/images/control/refresh.png"); + refreshLabel = new UILabel(refreshImage); + previewNumberPanel.add(refreshLabel); + refreshLabel.addMouseListener(new MouseAdapter() { + boolean mouseEntered = false; + boolean buttonPressed = false; + + public void mouseEntered(MouseEvent e) { // 当鼠标进入时候调用. + mouseEntered = true; + if (!buttonPressed) { + refreshLabel.setBackground(java.awt.Color.WHITE); + refreshLabel.setOpaque(true); + refreshLabel.setBorder(BorderFactory.createLineBorder(java.awt.Color.GRAY)); + } + } + + public void mouseExited(MouseEvent e) { + mouseEntered = false; + refreshLabel.setOpaque(false); + refreshLabel.setBorder(BorderFactory.createEmptyBorder()); + } + + public void mousePressed(MouseEvent e) { + buttonPressed = true; + refreshLabel.setBackground(java.awt.Color.lightGray); + } + + public void mouseReleased(MouseEvent e) { + buttonPressed = false; + if (mouseEntered) { + refreshLabel.setBackground(java.awt.Color.WHITE); + try { + populate(tableData); + if (storeProcedureDataModel != null) { + populateStoreDataSQL(); + } + } catch (Exception e1) { + } + } + } + }); + + preveiwTable = new SortableJTable(new TableSorter()); + preveiwTable.setRowSelectionAllowed(false); + preveiwTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + this.add(new JScrollPane(preveiwTable), BorderLayout.CENTER); + if (this.dialog == null) { + this.dialog = this.showWindow(DesignerContext.getDesignerFrame()); + } + progressBar = new AutoProgressBar(this, Inter.getLocText("FR-Designer_Loading_Data"), "", 0, 100) { + public void doMonitorCanceled() { + if (getWorker() != null) { + getWorker().cancel(true); + } + getDialog().setVisible(false); + } + }; + } + + public AutoProgressBar getProgressBar() { + return this.progressBar; + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Preview"); + } + + private void addLoadedListener(LoadedEventListener l) { + listeners.add(l); + } + + private void fireLoadedListener() { + for (LoadedEventListener l : listeners) { + l.fireLoaded(); + } + } + + /** + * sets current row count. + * + * @param currentRows + */ + private void setCurrentRows(int currentRows) { + this.currentRowsField.setValue(currentRows); + } + + private void resetPreviewTableColumnColor() { + this.listeners.clear(); + + } + + public BasicDialog getDialog() { + return this.dialog; + } + + public SwingWorker getWorker() { + return this.worker; + } + + // elake:为预览表的columnIndex列着c色. + private void setPreviewTableColumnColor(final int columnIndex, final Color c) { + addLoadedListener(new LoadedEventListener() { + @Override + public void fireLoaded() { + TableColumn column = preveiwTable.getColumnModel().getColumn(columnIndex); + DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JComponent comp = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + comp.setBackground(c); + comp.setBorder(BorderFactory.createRaisedBevelBorder()); + return comp; + } + }; + column.setCellRenderer(cellRenderer); + } + }); + + } + + /** + * 重置面板 + */ + public static void resetPreviewTable() { + getInstance().preveiwTable = new SortableJTable(new TableSorter()); + getInstance().preveiwTable.setRowSelectionAllowed(false); + getInstance().preveiwTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + getInstance().progressBar.close(); + getInstance().repaint(); + } + + private void setModel(TableModel tableModel) { + TableSorter tableSorter = (TableSorter) preveiwTable.getModel(); + + tableSorter.setTableModel(tableModel); + + preveiwTable.getParent().validate(); + preveiwTable.repaint(); + } + + + /** + * 直接预览数据集,没有实际值和显示值 + * + * @param tableData tableData + */ + public static void previewTableData(TableData tableData) { + previewTableData(tableData, -1, -1); + } + + /** + * 预览数据集,keyIndex为实际值、valueIndex为显示值 + * + * @param tableData tableData + * @param keyIndex + * @param valueIndex + */ + public static EmbeddedTableData previewTableData(TableData tableData, final int keyIndex, final int valueIndex) { + PreviewTablePane previewTablePane = new PreviewTablePane(); + previewTablePane.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("FR-Designer_Data"))); + try { + previewTablePane.populate(tableData); + previewTablePane.resetPreviewTableColumnColor(); + + if (keyIndex > -1) { + previewTablePane.setPreviewTableColumnColor(keyIndex, Color.getHSBColor(0, 204, 204)); + } + if (valueIndex > -1) { + previewTablePane.setPreviewTableColumnColor(valueIndex, Color.lightGray); + } + + } catch (Exception exp) { + previewTablePane.setModel(new PreviewTableModel((int) previewTablePane.maxPreviewNumberField.getValue())); + previewTablePane.showErrorMessage(exp); + } + if (!previewTablePane.dialog.isVisible()) { + previewTablePane.dialog.setVisible(true); + } + + return previewTablePane.previewTableData; + } + + private void showErrorMessage(Exception exp) { + String errMessage = exp.getLocalizedMessage(); + String columnErrMessage = errMessage.substring(0, errMessage.indexOf(">=")); + String tatolColumnErrMessage = errMessage.substring(errMessage.indexOf(">=") + 2); + try { + int choiceColumn = Integer.parseInt(columnErrMessage.trim()); + int tatalColumn = Integer.parseInt(tatolColumnErrMessage.trim()); + columnErrMessage = Inter.getLocText(new String[]{"Ser", String.valueOf(choiceColumn + 1), "Column_Does_Not_Exsit", ", ", "Total", String.valueOf(tatalColumn), "Column" + "!"}); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + return; + } + FRContext.getLogger().errorWithServerLevel(exp.getMessage(), exp); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), columnErrMessage, Inter.getLocText("FR-Designer_Error"), JOptionPane.ERROR_MESSAGE); + } + + private void populate(TableData tableData) throws Exception { + this.tableData = tableData; + + // p:直接预览. + if (tableData != null) { + previewTableDataSQL(); + } + } + + private void previewTableDataSQL() throws Exception { + connectionBar = new AutoProgressBar(this, Inter.getLocText("Utils-Now_create_connection"), "", 0, 100) { + public void doMonitorCanceled() { + getWorker().cancel(true); + getDialog().setVisible(false); + } + }; + setWorker(); + worker.execute(); + + } + + + private void setPreviewTableColumnValue(final Graphics g) { + for (int i = 0; i < preveiwTable.getColumnModel().getColumnCount(); i++) { + TableColumn column = preveiwTable.getColumnModel().getColumn(i); + DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JComponent comp = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + Font f = table.getFont(); + + //默认在系统不支持 无法显示时 如自造的字 ,字体设置为空. + Font defaultShowFont = FRFont.getInstance("", f.getStyle(), f.getSize()); + if (value instanceof String) { + String str = (String) value; + for (int j = 0; j < str.length(); j++) { + char c = str.charAt(j); + if (!f.canDisplay(c)) { + table.setFont(defaultShowFont); + } + } + } + return comp; + } + }; + column.setCellRenderer(cellRenderer); + } + } + + + private void setWorker() { + + worker = new SwingWorker() { + protected PreviewTableModel doInBackground() throws Exception { + connectionBar.start(); + if (tableData instanceof DBTableData) { + boolean status = FRContext.getCurrentEnv().testConnection(((DBTableData) tableData).getDatabase()); + if (!status) { + connectionBar.close(); + throw new Exception(Inter.getLocText("Datasource-Connection_failed")); + } + } + connectionBar.close(); + previewTableData = DesignTableDataManager.previewTableDataNeedInputParameters(tableData, (int) maxPreviewNumberField.getValue(), true); + // parameterInputDialog + // update之后的parameters,转成一个parameterMap,用于预览TableData + PreviewTableModel previewModel = new PreviewTableModel(previewTableData.createDataModel(null), (int) maxPreviewNumberField.getValue()); + for (int i = 0; i < previewTableData.getColumnCount(); i++) { + Class cls = previewTableData.getColumnClass(i); + if (cls == Date.class || cls == TIME.class || cls == Timestamp.class) { + previewModel.dateIndexs.add(i); + } + } + return previewModel; + } + + public void done() { + try { + PreviewTableModel model = get(); + setModel(model); + setCurrentRows(model.getRowCount()); + setPreviewTableColumnValue(getParent().getGraphics()); + fireLoadedListener(); + } catch (Exception e) { + if (!(e instanceof CancellationException)) { + FRContext.getLogger().error(e.getMessage(), e); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage()); + } + dialog.setVisible(false); + } finally { + progressBar.close(); + } + } + }; + } + + /** + * 直接预览存储过程的一个返回数据集,没有实际值和显示值 + * + * @param storeProcedureDataModel storeProcedureDataModel + */ + public static void previewStoreData(ProcedureDataModel storeProcedureDataModel) { + previewStoreData(storeProcedureDataModel, -1, -1); + } + + /** + * 预览存储过程的一个返回数据集,keyIndex为实际值、valueIndex为显示值 + * + * @param storeProcedureDataModel storeProcedureDataModel + * @param keyIndex 实际值 + * @param valueIndex 显示值 + */ + public static void previewStoreData(final ProcedureDataModel storeProcedureDataModel, final int keyIndex, final int valueIndex) { + final PreviewTablePane previewTablePane = new PreviewTablePane(); + previewTablePane.storeProcedureDataModel = storeProcedureDataModel; + previewTablePane.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("FR-Designer_Data"))); + + try { + previewTablePane.populateStoreDataSQL(); + previewTablePane.resetPreviewTableColumnColor(); + + if (keyIndex > -1) { + previewTablePane.setPreviewTableColumnColor(keyIndex, Color.getHSBColor(0, 204, 204)); + } + if (valueIndex > -1) { + previewTablePane.setPreviewTableColumnColor(valueIndex, Color.lightGray); + } + + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + previewTablePane.fireLoadedListener(); + previewTablePane.showWindow(DesignerContext.getDesignerFrame()).setVisible(true); + } + + /** + * 直接预览存储过程的所有返回数据集,没有实际值和显示值 + * + * @param storeProcedureDataModels storeProcedureDataModels + */ + public static void previewStoreDataWithAllDs(ProcedureDataModel[] storeProcedureDataModels) { + UITabbedPane tabPreviewpane = new UITabbedPane(); + int tableSize = storeProcedureDataModels.length; + for (int i = 0; i < tableSize; i++) { + PreviewTablePane previewTablePane = new PreviewTablePane(); + previewTablePane.storeProcedureDataModel = storeProcedureDataModels[i]; + previewTablePane.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("FR-Designer_Data"))); + try { + previewTablePane.populateStoreDataSQL(); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + tabPreviewpane.addTab(storeProcedureDataModels[i].getName(), previewTablePane); + } + + BasicPane prieviewPane = new BasicPane() { + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Preview"); + } + + }; + prieviewPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + prieviewPane.add(tabPreviewpane, BorderLayout.CENTER); + prieviewPane.showWindow(DesignerContext.getDesignerFrame()).setVisible(true); + } + + private void populateStoreDataSQL() throws Exception { + PreviewTableModel previewModel; + try { + previewModel = new PreviewTableModel(storeProcedureDataModel, (int) maxPreviewNumberField.getValue()); + } catch (Exception e) { + previewModel = new PreviewTableModel((int) maxPreviewNumberField.getValue()); + } + setModel(previewModel); + setCurrentRows(previewModel.getRowCount()); + fireLoadedListener(); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/datapane/sqlpane/SQLEditPane.java b/designer_base/src/com/fr/design/data/datapane/sqlpane/SQLEditPane.java new file mode 100644 index 0000000000..3d17636aaf --- /dev/null +++ b/designer_base/src/com/fr/design/data/datapane/sqlpane/SQLEditPane.java @@ -0,0 +1 @@ +package com.fr.design.data.datapane.sqlpane; import com.fr.base.FRContext; import com.fr.data.core.DataCoreUtils; import com.fr.data.core.db.TableProcedure; import com.fr.design.actions.UpdateAction; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; import com.fr.general.ComparatorUtils; import com.fr.general.Inter; import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.*; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.*; import java.awt.event.ActionEvent; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 13-5-2 * Time: 上午11:09 */ public class SQLEditPane extends RSyntaxTextArea { public static final boolean REQUEST_DROPTARGET = true; public static final boolean UNREQUEST_DROPTARGET = false; public SQLEditPane() { this(REQUEST_DROPTARGET); } public SQLEditPane(boolean requestDroptarget) { super(); setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); setAnimateBracketMatching(true); setAntiAliasingEnabled(true); setAutoIndentEnabled(true); setCodeFoldingEnabled(true); setUseSelectedTextColor(true); setCloseCurlyBraces(true); setBracketMatchingEnabled(true); setAntiAliasingEnabled(true); setCloseMarkupTags(true); setLineWrap(true); if (requestDroptarget) { new SQLPaneDropTarget(this); } } private static class SQLPaneDropTarget extends DropTargetAdapter { private TableProcedure sqlTable; public SQLPaneDropTarget(SQLEditPane sqlTextPane) { new DropTarget(sqlTextPane, this); } public void dragEnter(DropTargetDragEvent dtde) { dtde.acceptDrag(dtde.getDropAction()); } public void dragOver(DropTargetDragEvent dtde) { dtde.acceptDrag(dtde.getDropAction()); } public void drop(DropTargetDropEvent dtde) { Point p = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); SQLEditPane jTextPane = (SQLEditPane) dtc.getComponent(); try { Transferable tr = dtde.getTransferable(); DataFlavor[] flavors = tr.getTransferDataFlavors(); for (int i = 0; i < flavors.length; i++) { if (!tr.isDataFlavorSupported(flavors[i])) { continue; } dtde.acceptDrop(dtde.getDropAction()); Object userObj = tr.getTransferData(flavors[i]); if (userObj instanceof TableProcedure) { this.sqlTable = (TableProcedure) userObj; JPopupMenu popupMenu = new JPopupMenu(); popupMenu.add(new NameAction(jTextPane, sqlTable).createMenuItem()); if (ComparatorUtils.equals(sqlTable.getType(), TableProcedure.PROCEDURE)) { popupMenu.add(new CallAction(jTextPane, sqlTable).createMenuItem()); } else { popupMenu.add(new SelectAction(jTextPane, sqlTable).createMenuItem()); } GUICoreUtils.showPopupMenu(popupMenu, jTextPane, (int) p.getX() + 1, (int) p.getY() + 1); } dtde.dropComplete(true); } dtde.rejectDrop(); } catch (Exception e) { dtde.rejectDrop(); } } class NameAction extends UpdateAction { private SQLEditPane sqlTextPane; private TableProcedure sqlTable; public NameAction(SQLEditPane sqlTextPane, TableProcedure sqlTable) { this.sqlTextPane = sqlTextPane; this.sqlTable = sqlTable; this.setName(Inter.getLocText("Name")); this.setMnemonic('N'); this.setSmallIcon(null); } public void actionPerformed(ActionEvent evt) { if (sqlTable != null) { insertStringTo(sqlTextPane, sqlTable.toString()); } } } class SelectAction extends UpdateAction { private SQLEditPane sqlTextPane; private TableProcedure sqlTable; public SelectAction(SQLEditPane sqlTextPane, TableProcedure sqlTable) { this.sqlTextPane = sqlTextPane; this.sqlTable = sqlTable; this.setName("SELECT *"); this.setMnemonic('s'); this.setSmallIcon(null); } public void actionPerformed(ActionEvent evt) { //daniel: 添加参数 insertStringTo(sqlTextPane, DataCoreUtils.createSelectSQL(sqlTable.getSchema(), sqlTable.getName(), sqlTable.getDialect())); } } class CallAction extends UpdateAction { private SQLEditPane sqlTextPane; private TableProcedure sqlTable; public CallAction(SQLEditPane sqlTextPane, TableProcedure sqlTable) { this.sqlTextPane = sqlTextPane; this.sqlTable = sqlTable; this.setName("CALL PROCEDURE "); this.setMnemonic('s'); this.setSmallIcon(null); } public void actionPerformed(ActionEvent evt) { StringBuffer sBuf = new StringBuffer(); sBuf.append("{call "); if (sqlTable != null) { sBuf.append(sqlTable.toString()).append("()"); } sBuf.append('}'); insertStringTo(sqlTextPane, sBuf.toString()); } } private void insertStringTo(SQLEditPane sqlTextPane, String str) { Document document = sqlTextPane.getDocument(); try { document.insertString(sqlTextPane.getCaretPosition(), str, null); } catch (BadLocationException badLocationException) { FRContext.getLogger().error(badLocationException.getMessage(), badLocationException); } sqlTextPane.requestFocus(); } } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/Prepare4DataSourceChange.java b/designer_base/src/com/fr/design/data/tabledata/Prepare4DataSourceChange.java new file mode 100644 index 0000000000..3468b2f3d1 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/Prepare4DataSourceChange.java @@ -0,0 +1,15 @@ +package com.fr.design.data.tabledata; + +/** + * Created with IntelliJ IDEA. + * User: 小灰灰 + * Date: 13-8-5 + * Time: 上午11:23 + * To change this template use File | Settings | File Templates. + */ +public interface Prepare4DataSourceChange { + /** + *注册listener,相应数据集改变 + */ + public void registerDSChangeListener (); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/ResponseDataSourceChange.java b/designer_base/src/com/fr/design/data/tabledata/ResponseDataSourceChange.java new file mode 100644 index 0000000000..e1dde3dd21 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/ResponseDataSourceChange.java @@ -0,0 +1,25 @@ +package com.fr.design.data.tabledata; + +import java.util.Map; + +/** + * Created with IntelliJ IDEA. + * User: 小灰灰 + * Date: 13-8-5 + * Time: 上午11:24 + * To change this template use File | Settings | File Templates. + */ +public interface ResponseDataSourceChange { + + /** + * 响应数据集改变 + */ + public void fireDSChanged(); + + /** + * 响应数据集改变 + */ + public void fireDSChanged(Map map); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/StoreProcedureWorkerListener.java b/designer_base/src/com/fr/design/data/tabledata/StoreProcedureWorkerListener.java new file mode 100644 index 0000000000..ab9520a7ee --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/StoreProcedureWorkerListener.java @@ -0,0 +1,14 @@ +package com.fr.design.data.tabledata; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-12-5 + * Time: 上午10:09 + */ +public interface StoreProcedureWorkerListener { + + public void fireDoneAction(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/gui/CONTENT.txt b/designer_base/src/com/fr/design/data/tabledata/gui/CONTENT.txt new file mode 100644 index 0000000000..ff6cc55a10 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/gui/CONTENT.txt @@ -0,0 +1,14 @@ + ʹSAPݼȡǰҪһɳɹӵSAPӡ + ӺSAPݼȡ,ֲͬȡֶΡ + 1.Զ壺 + ʹԶȡֱӵABAP FunctionԻȡݡ + бУɸfunctionһһҷݼͨݼֵ + бУĿǰֻѡһΪݼĽʹá + 2.ͨòѯ + ʹüͨòѯֱӻȡSAPijһ͸ݡ + ע⣬ֵ֧ѯ + ɼ${abc}Ϊһ÷ͬݿݼ + 3.ͨòѯ(ECC 6ϰ汾) + ʹͨòѯԽжӲѯ + ע⣬˹ֻ֧SAP 6ϰ汾Ҫҷĵе˵SAPϵͳӦFunction + ɼ${abc}Ϊһ÷ͬݿݼ diff --git a/designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN1.txt b/designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN1.txt new file mode 100644 index 0000000000..9f90c96a51 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN1.txt @@ -0,0 +1,6 @@ + Where﷨ʽοOPEN SQL﷨ + : + Column1 = 'ABC' AND Column2 > 100 + AND Column3 LIKE 'DES%' + AND Column4 BETWEEN 1995 AND 2000 + AND Column5 IN (1,2,3,4,5); diff --git a/designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN2.txt b/designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN2.txt new file mode 100644 index 0000000000..4214f49721 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/gui/EXPLAN2.txt @@ -0,0 +1,17 @@ + ﷨ʽοOPEN SQL﷨ + 磺 + Select : + employees~pernr, adr~vorna, adr~nachn, orgnam~orgtx + From : + pa0003 AS employees + INNER JOIN pa0000 AS status ON employees~pernr = status~pernr + INNER JOIN pa0001 AS org ON employees~pernr = org~pernr + INNER JOIN pa0002 AS adr ON employees~pernr = adr~pernr + INNER JOIN t527x AS orgnam ON org~orgeh = orgnam~orgeh + INNER JOIN t002 AS lang ON orgnam~sprsl = lang~spras + Where : + status~stat2 >= '2' AND status~endda > sy-datum AND + org~endda > sy-datum AND + adr~endda > sy-datum AND + lang~laiso = 'EN' + ע~.where֧ͬ BETWEEN LIKE INš diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/AbstractTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/AbstractTableDataPane.java new file mode 100644 index 0000000000..894c68529f --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/AbstractTableDataPane.java @@ -0,0 +1,15 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.TableData; +import com.fr.design.data.tabledata.StoreProcedureWorkerListener; +import com.fr.design.beans.BasicBeanPane; + +public abstract class AbstractTableDataPane extends BasicBeanPane { + + public void addStoreProcedureWorkerListener(StoreProcedureWorkerListener listener) { + } + + public void removeStoreProcedureWorkerListener() { + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/AutoStoreProcedureTableModel.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/AutoStoreProcedureTableModel.java new file mode 100644 index 0000000000..86d96f5738 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/AutoStoreProcedureTableModel.java @@ -0,0 +1,156 @@ +package com.fr.design.data.tabledata.tabledatapane; +import com.fr.base.Formula; +import com.fr.base.StoreProcedureParameter; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.editor.editor.CursorEditor; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; +import java.awt.*; +import java.util.*; + + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-5-24 + * Time: 下午1:07 + * To change this template use File | Settings | File Templates. + */ +public class AutoStoreProcedureTableModel extends StoreProcedureTableModel { + + public AutoStoreProcedureTableModel() { + super(); + Class[] classes = new Class[]{ParameterTableModel.ParameterEditor.class, getColumnClass(1), getColumnClass(2), StoreProcedureParameterValueEditor.class}; + this.setColumnClass(classes); + this.setDefaultEditor(StoreProcedureParameterValueEditor.class, new StoreProcedureParameterValueEditor()); + this.setDefaultEditor(ParameterTableModel.ParameterEditor.class, new ParameterTableModel().new ParameterEditor()); + this.setDefaultRenderer(StoreProcedureParameterValueEditor.class, new ProcedureParameterValueRenderer()); + } + public boolean isCellEditable(int row, int col) { + if (ComparatorUtils.equals(getValueAt(row, col -1), "OUT")) { + return false; + } + if (col ==0 || col == 3) { + return true; + } + return false; + } + + public boolean shouldResponseDoubleClickAction () { + return false; + } + + private class StoreProcedureParameterValueEditor extends AbstractCellEditor implements TableCellEditor { + private ValueEditorPane editor; + + public StoreProcedureParameterValueEditor() { + + editor = ValueEditorPaneFactory.createStoreProcedValueEditorPane(); + editor.getMenu().addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + new java.util.Timer().schedule(new TimerTask() { + public void run() { + int selectedRow = table.getSelectedRow(); + if (selectedRow != -1) { + StoreProcedureParameter para = getList().get(selectedRow); + para.setType(getParameterType(getCellEditorValue())); + fireTableDataChanged(); + table.setRowSelectionInterval(selectedRow, selectedRow); + } + } + }, 100); + } + + public void popupMenuCanceled(PopupMenuEvent e) { + + } + }); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1) { + return; + } + StoreProcedureParameter para = getList().get(table.getSelectedRow()); + para.setValue(getCellEditorValue()); + para.setType(getParameterType(getCellEditorValue())); + fireTableDataChanged(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + editor.populate(value == null ? "" : value); + return editor; + } + + @Override + public Object getCellEditorValue() { + return editor.update(); + } + + } + + private int getParameterType (Object value) { + String type; + if(value instanceof CursorEditor) + type= Inter.getLocText("Cursor"); + else if(value instanceof String ){ + if(((String) value).length() > 0 && ((String) value).charAt(0) == '=') + type = Inter.getLocText("Formula"); + else + type = Inter.getLocText("Parameter-String"); + }else if(value instanceof Integer) + type = Inter.getLocText("Integer"); + else if(value instanceof Double) + type = Inter.getLocText("Double"); + else if(value instanceof Date) + type = Inter.getLocText("Date"); + else if(value instanceof Boolean) + type = Inter.getLocText("Parameter-Boolean"); + else if(value instanceof Formula) + type = Inter.getLocText("Formula"); + else + type = Inter.getLocText("Parameter-String"); + return StoreProcedureParameterPane.getInfo4Value(type); + + } + + private class ProcedureParameterValueRenderer extends DefaultTableCellRenderer { + private static final long serialVersionUID = 1L; + private ValueEditorPane editor; + + public ProcedureParameterValueRenderer() { + editor = ValueEditorPaneFactory.createStoreProcedValueEditorPane(); + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + editor.setCurrentEditor(0); + editor.populate(value); + return editor; + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassNameSelectPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassNameSelectPane.java new file mode 100644 index 0000000000..5b1ccd78e7 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassNameSelectPane.java @@ -0,0 +1,63 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.BorderLayout; + +import javax.swing.BorderFactory; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.tree.TreeSelectionModel; + +import com.fr.base.FRContext; +import com.fr.design.gui.itree.filetree.ClassFileTree; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; + +public class ClassNameSelectPane extends BasicPane { + private ClassFileTree classFileTree; + + public ClassNameSelectPane() { + this.setLayout(new BorderLayout(0, 4)); + + JPanel webDirectoryPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(webDirectoryPane, BorderLayout.NORTH); + webDirectoryPane.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0)); + webDirectoryPane.add(new UILabel( + Inter.getLocText("Function-Choose_Function_Class") + ":")); + + classFileTree = new ClassFileTree(); + classFileTree.refreshEnv(FRContext.getCurrentEnv()); + classFileTree.getSelectionModel().setSelectionMode( + TreeSelectionModel.SINGLE_TREE_SELECTION); + this.add(new JScrollPane(classFileTree), BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Function-Function_Class_Name"); + } + + /* + * 选中某ClassPath + */ + public void setClassPath(String classPath) { + + classFileTree.setSelectedClassPath(classPath + ".class"); + } + + /* + * 返回选中的ClassPath + */ + public String getClassPath() { + return classFileTree.getSelectedClassPath(); + } + + @Override + public void checkValid() throws Exception { + String classPath = classFileTree.getSelectedClassPath(); + if (classPath == null) { + throw new Exception(Inter.getLocText("Function-The_selected_file_cannot_be_null")); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassTableDataPane.java new file mode 100644 index 0000000000..fd127375d2 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ClassTableDataPane.java @@ -0,0 +1,115 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.data.impl.ClassTableData; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.JavaEditorPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.general.Inter; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +public class ClassTableDataPane extends AbstractTableDataPane { + private UITextField classNameTextField; + + public ClassTableDataPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + + // TableLayout + double p = TableLayout.PREFERRED; + + double[] rowSize = {p, p, p, p}; + double[] columnSize = {p, p}; + //Reportlet. + JPanel reportletNamePane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(); + classNameTextField = new UITextField(36); + reportletNamePane.add(classNameTextField); + + UIButton browserButton = new UIButton(Inter.getLocText("Select")); + browserButton.setPreferredSize(new Dimension( + browserButton.getPreferredSize().width, + classNameTextField.getPreferredSize().height)); + reportletNamePane.add(browserButton); + browserButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + final ClassNameSelectPane bPane = new ClassNameSelectPane(); + bPane.setClassPath(classNameTextField.getText()); + BasicDialog dlg= bPane.showWindow( + (Dialog) SwingUtilities.getWindowAncestor(ClassTableDataPane.this), + new DialogActionAdapter() { + public void doOk() { + classNameTextField.setText(bPane.getClassPath()); + } + }); + dlg.setVisible(true); + } + }); + UIButton editButton = new UIButton(Inter.getLocText("Edit")); + editButton.setPreferredSize(new Dimension( + editButton.getPreferredSize().width, + classNameTextField.getPreferredSize().height)); + reportletNamePane.add(editButton); + editButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final JavaEditorPane javaEditorPane = new JavaEditorPane(classNameTextField.getText(), JavaEditorPane.DEFAULT_TABLEDATA_STRING); + final BasicDialog dlg = javaEditorPane.showMediumWindow(SwingUtilities.getWindowAncestor(ClassTableDataPane.this), + new DialogActionAdapter() { + public void doOk() { + classNameTextField.setText(javaEditorPane.getClassText()); + } + }); + + javaEditorPane.addSaveActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dlg.doOK(); + } + }); + dlg.setVisible(true); + } + }); + + Component[][] components = { + {new UILabel(Inter.getLocText("DS-Class_Name") + ":"), reportletNamePane}, + {null, new UILabel(Inter.getLocText("Function-The_class_must_implement_the_interface") + "\"com.fr.data.Tabledata\"")}, + {null, new UILabel(Inter.getLocText("Example") + ":\"com.fr.data.impl.ArrayTableData\"")}, + {null,new UILabel(Inter.getLocText(new String[]{"Function-The_class_must_be_located_in","Function-J2EE_server"}, + new String[]{" ","\"",File.separator,ProjectConstants.WEBINF_NAME,File.separator,"classes\""}))} + }; + JPanel northPane = TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); + this.add(northPane, BorderLayout.NORTH); + // TODO alex_ENV +// northPane.add(flowTableLayoutHelper.createLabelFlowPane( +// " ", new UILabel(Inter.getLocText("Example") + ":" + +// BaseCoreUtils.pathJoin(new String[] {FRContext.getCurrentEnv().getPath(), "classes"})))); + + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("DS-Class_TableData"); + } + + @Override + public void populateBean(ClassTableData ob) { + this.classNameTextField.setText(ob.getClassName()); + } + + @Override + public ClassTableData updateBean() { + return new ClassTableData(this.classNameTextField.getText()); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/CustomDictModel.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/CustomDictModel.java new file mode 100644 index 0000000000..3c81cd90ea --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/CustomDictModel.java @@ -0,0 +1,130 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.AbstractCellEditor; +import javax.swing.JTable; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.table.TableCellEditor; + +import com.fr.design.gui.itableeditorpane.ActionStyle; +import com.fr.design.gui.itableeditorpane.UIArrayTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableModelAdapter; +import com.fr.design.gui.itextfield.UITextField; + +public class CustomDictModel extends UITableModelAdapter implements ActionStyle { + /** + * + */ + private static final long serialVersionUID = 1L; + private int[] array; + private ActionListener actionListener; + + public CustomDictModel(String[] s, int[] array, ActionListener actionListener) { + super(s); + this.array = array; + this.actionListener = actionListener; + this.setColumnClass(new Class[] { ParameterEditor.class, ParameterEditor.class }); + this.setDefaultEditor(ParameterEditor.class, new ParameterEditor()); + } + + public Object getValueAt(int row, int column) { + Object[] os = this.getList().get(row); + return os[column]; + } + + public void setValueAt(Object value, int row, int column) { + Object[] os = this.getList().get(row); + os[column] = value; + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + @Override + public void fireTableDataChanged() { + super.fireTableDataChanged(); + if (actionListener != null) { + actionListener.actionPerformed(null); + } + } + + @Override + public UITableEditAction[] createAction() { + List list = new ArrayList(); + UITableEditAction[] tableEditAction = new UITableEditAction[array.length]; + for (int i : array) { + switch (i) { + case UIArrayTableModel.ADDSTYLE: + list.add(new AddRow()); + break; + case UIArrayTableModel.ADDJSFILE: + break; + case UIArrayTableModel.ADDCSSFILE: + break; + case UIArrayTableModel.DELETESTYLE: + list.add(new DeleteAction()); + break; + case UIArrayTableModel.MOVEUPSTYLE: + list.add(new MoveUpAction()); + break; + case UIArrayTableModel.MOVEDOWNSTYLE: + list.add(new MoveDownAction()); + break; + + } + } + return list.toArray(tableEditAction); + } + + public class AddRow extends AddTableRowAction { + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + addRow(new Object[getColumnCount()]); + fireTableDataChanged(); + } + } + + class ParameterEditor extends AbstractCellEditor implements TableCellEditor { + + private static final long serialVersionUID = 1L; + private UITextField textField; + + public ParameterEditor() { + textField = new UITextField(); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (actionListener != null) { + actionListener.actionPerformed(null); + } + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + textField.setText((String) value); + return textField; + } + + @Override + public Object getCellEditorValue() { + return textField.getText(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java new file mode 100644 index 0000000000..5b1ed2febf --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java @@ -0,0 +1,344 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.Parameter; +import com.fr.base.ParameterHelper; +import com.fr.data.core.db.TableProcedure; +import com.fr.data.impl.DBTableData; +import com.fr.data.impl.NameDatabaseConnection; +import com.fr.design.actions.UpdateAction; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; +import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.data.datapane.sqlpane.SQLEditPane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.SeparatorDef; +import com.fr.design.menu.ToolBarDef; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.script.Calculator; +import com.fr.stable.ArrayUtils; +import com.fr.stable.ParameterProvider; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.ArrayList; +import java.util.List; + +public class DBTableDataPane extends AbstractTableDataPane { + private static final String PREVIEW_BUTTON = Inter.getLocText("Preview"); + private static final String REFRESH_BUTTON = Inter.getLocText("Refresh"); + private ConnectionTableProcedurePane connectionTableProcedurePane; + private UITableEditorPane editorPane; + + private SQLEditPane sqlTextPane; + private UICheckBox isShareCheckBox; + private MaxMemRowCountPanel maxPanel; + private String pageQuery = null; + + + public DBTableDataPane() { + this.setLayout(new BorderLayout(4, 4)); + + Box box = new Box(BoxLayout.Y_AXIS); + + sqlTextPane = new SQLEditPane(); + sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); + JPanel northPane = new JPanel(new BorderLayout(4, 4)); + JToolBar editToolBar = createToolBar(); + northPane.add(editToolBar, BorderLayout.CENTER); + northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 6, 0)); + + RTextScrollPane sqlTextScrollPane = new RTextScrollPane(sqlTextPane); + sqlTextScrollPane.setLineNumbersEnabled(true); + sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + sqlTextScrollPane.setPreferredSize(new Dimension(680, 600)); + + JPanel paraMeanPane = new JPanel(new BorderLayout()); + paraMeanPane.setPreferredSize(new Dimension(680, 90)); + UILabel paraMean = new UILabel(Inter.getLocText("Datasource-Param_DES")); + paraMeanPane.add(paraMean, BorderLayout.CENTER); + + ParameterTableModel model = new ParameterTableModel() { + @Override + public UITableEditAction[] createAction() { + return (UITableEditAction[]) ArrayUtils.add(super.createDBTableAction(), new RefreshAction()); + } + }; + editorPane = new UITableEditorPane(model); + + box.add(northPane); + box.add(sqlTextScrollPane); + box.add(paraMeanPane); + box.add(editorPane); + + JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4)); + sqlSplitPane.add(box, BorderLayout.CENTER); + + // 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table + connectionTableProcedurePane = new ConnectionTableProcedurePane(); + connectionTableProcedurePane.addDoubleClickListener(new DoubleClickSelectedNodeOnTreeListener() { + + @Override + public void actionPerformed(TableProcedure target) { + Document document = sqlTextPane.getDocument(); + try { + document.insertString(sqlTextPane.getCaretPosition(), target.toString(), null); + } catch (BadLocationException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + // 这里开始作色,本来可以给sqlTextPane添加DocumentListener来实现的, + // 后来发现insertString的时候,锁定了JTextPane,不能调用setXXX来作色,先这样了. +// sqlTextPane.syntaxTexts(); + sqlTextPane.requestFocus(); + } + }); + sqlTextPane.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + + } + + public void focusLost(FocusEvent e) { + if (isPreviewOrRefreshButton(e)) { + checkParameter(); + } + } + }); + + this.add(connectionTableProcedurePane, BorderLayout.WEST); + this.add(sqlSplitPane, BorderLayout.CENTER); + } + + private boolean isPreviewOrRefreshButton (FocusEvent e) { + if (e.getOppositeComponent() != null) { + String name = e.getOppositeComponent().getName(); + return ComparatorUtils.equals(name, PREVIEW_BUTTON) || ComparatorUtils.equals(name, REFRESH_BUTTON); + } + return false; + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("DS-Database_Query"); + } + + private void refresh() { + String[] paramTexts = new String[2]; + paramTexts[0] = sqlTextPane.getText(); + paramTexts[1] = pageQuery; + + List existParameterList = editorPane.update(); + Parameter[] ps = existParameterList == null ? new Parameter[0] : existParameterList.toArray(new Parameter[existParameterList.size()]); + + editorPane.populate(ParameterHelper.analyzeAndUnionSameParameters(paramTexts, ps)); + } + + private JToolBar createToolBar() { + // p:工具栏. + ToolBarDef toolBarDef = new ToolBarDef(); + toolBarDef.addShortCut(new PreviewAction()); + toolBarDef.addShortCut(SeparatorDef.DEFAULT); + toolBarDef.addShortCut(new EditPageQueryAction()); + isShareCheckBox = new UICheckBox(Inter.getLocText("Is_Share_DBTableData")); + maxPanel = new MaxMemRowCountPanel(); + maxPanel.setBorder(null); + UIToolbar editToolBar = ToolBarDef.createJToolBar(); + toolBarDef.updateToolBar(editToolBar); + editToolBar.add(isShareCheckBox); + editToolBar.add(maxPanel); + return editToolBar; + } + + private void checkParameter() { + String[] paramTexts = new String[2]; + paramTexts[0] = sqlTextPane.getText(); + paramTexts[1] = pageQuery; + + Parameter[] parameters = ParameterHelper.analyze4Parameters(paramTexts, false); + + if (parameters.length < 1 && editorPane.update().size() < 1) { + return; + } + boolean isIn = true; + List list = editorPane.update(); + List name = new ArrayList(); + for (int i = 0; i < list.size(); i++) { + name.add(list.get(i).getName()); + } + for (int i = 0; i < parameters.length; i++) { + if (!name.contains(parameters[i].getName())) { + isIn = false; + break; + } + } + if (list.size() == parameters.length && isIn) { + return; + } + // bug:34175 删了是否刷新对话框, 均直接刷新 + refresh(); + } + + @Override + public void populateBean(DBTableData dbtabledata) { + ParameterProvider[] parameters = null; + + Calculator c = Calculator.createCalculator(); + + parameters = dbtabledata.getParameters(c); + editorPane.populate(parameters); + + com.fr.data.impl.Connection db = null; + String query = null; + boolean isShare = false; + int maxMemeryRow = -1; + + db = dbtabledata.getDatabase(); + query = dbtabledata.getQuery(); + isShare = dbtabledata.isShare(); + maxMemeryRow = dbtabledata.getMaxMemRowCount(); + this.pageQuery = dbtabledata.getPageQuerySql(); + + this.connectionTableProcedurePane.setSelectedDatabaseConnection(db); + this.sqlTextPane.setText(query); + this.sqlTextPane.requestFocus(); + this.sqlTextPane.moveCaretPosition(this.sqlTextPane.getCaretPosition()); + + isShareCheckBox.setSelected(isShare); + maxPanel.setValue(maxMemeryRow); + } + + @Override + public DBTableData updateBean() { + String dbName = this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); + if (StringUtils.isBlank(dbName) || StringUtils.isBlank(this.sqlTextPane.getText())) { + try { + throw new Exception(Inter.getLocText("Connect_SQL_Cannot_Null") + "."); + } catch (Exception e) { + // JOptionPane.showMessageDialog(DBTableDataPane.this, + // Inter.getLocText("Connect_SQL_Cannot_Null") + "."); + } + } + + List parameterList = editorPane.update(); + Parameter[] parameters = parameterList.toArray(new Parameter[parameterList.size()]); + + DBTableData dbTableData = new DBTableData(); + dbTableData.setDatabase(new NameDatabaseConnection(dbName)); + + // p:必须先设置Parameters数组,因为setQuery里面会自动设置的 + + dbTableData.setParameters(parameters); + dbTableData.setQuery(this.sqlTextPane.getText()); + + dbTableData.setShare(isShareCheckBox.isSelected()); + dbTableData.setMaxMemRowCount(maxPanel.getValue()); + dbTableData.setPageQuerySql(this.pageQuery); + + return dbTableData; + } + + protected class RefreshAction extends UITableEditAction { + public RefreshAction() { + this.setName(REFRESH_BUTTON); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + } + + public void actionPerformed(ActionEvent e) { + refresh(); + } + + @Override + public void checkEnabled() { + } + } + + private class PreviewAction extends UpdateAction { + public PreviewAction() { + this.setName(PREVIEW_BUTTON); + this.setMnemonic('P'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + } + + public void actionPerformed(ActionEvent evt) { + checkParameter(); + PreviewTablePane.previewTableData(DBTableDataPane.this.updateBean()); + } + } + + private class EditPageQueryAction extends UpdateAction { + public EditPageQueryAction() { + this.setName(Inter.getLocText("LayerPageReport_PageQuery")); + this.setMnemonic('L'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/text.png")); + } + + public void actionPerformed(ActionEvent e) { + final PageQueryPane pane = new PageQueryPane(); + pane.populate(pageQuery); + BasicDialog dialog = pane.showWindow(DesignerContext.getDesignerFrame()); + dialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + pageQuery = pane.update(); + checkParameter(); + } + }); + dialog.setVisible(true); + } + } + + private class PageQueryPane extends BasicPane { + private SQLEditPane pageQueryPane; + + public PageQueryPane() { + this.initComponents(); + } + + public void initComponents() { + this.setLayout(new BorderLayout()); + pageQueryPane = new SQLEditPane(); + this.add(new JScrollPane(pageQueryPane)); + } + + public void populate(String text) { + if (StringUtils.isBlank(text)) { + return; + } + pageQueryPane.setText(text); + } + + public String update() { + String text = pageQueryPane.getText(); + if (StringUtils.isBlank(text)) { + return null; + } else { + return text; + } + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("LayerPageReport_Define_PageQuerySQL"); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/DecoratedTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/DecoratedTableDataPane.java new file mode 100644 index 0000000000..0f3f8631b4 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/DecoratedTableDataPane.java @@ -0,0 +1,96 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.FRContext; +import com.fr.data.impl.DecoratedTableData; +import com.fr.design.condition.DSColumnLiteConditionPane; +import com.fr.design.gui.ilist.CheckBoxList; +import com.fr.design.gui.ilist.CheckBoxList.CheckBoxListSelectionChangeListener; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; +import com.fr.general.data.DataModel; +import com.fr.general.data.TableDataException; +import com.fr.script.Calculator; + +import java.awt.*; + +public class DecoratedTableDataPane extends AbstractTableDataPane implements CheckBoxListSelectionChangeListener { + private CheckBoxList availableTableDataNameList; + private DSColumnLiteConditionPane conditionPane; + + public DecoratedTableDataPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + DatasourceManagerProvider mgr = DatasourceManager.getProviderInstance(); + java.util.Iterator serverTableDataNameIterator = mgr.getTableDataNameIterator(); + java.util.List tableDataNameList = new java.util.ArrayList(); + while (serverTableDataNameIterator.hasNext()) { + tableDataNameList.add((String)serverTableDataNameIterator.next()); + } + availableTableDataNameList = new CheckBoxList(tableDataNameList.toArray(new String[0]), CheckBoxList.SelectedState.NONE,Inter.getLocText("FR-Designer_Chart_Field_Name")); + this.add(availableTableDataNameList, BorderLayout.WEST); + availableTableDataNameList.addCheckBoxListSelectionChangeListener(this); + + conditionPane = new DSColumnLiteConditionPane(); + this.add(conditionPane, BorderLayout.CENTER); + } + + @Override + public void populateBean(DecoratedTableData ob) { + String[] relatedTableDataNames = ob.getRelatedTableDataNames(); + availableTableDataNameList.setItems(relatedTableDataNames); + + conditionPane.populateBean(ob.getCondition()); + } + + private DecoratedTableData updateBeanExcludeFilter() { + DecoratedTableData td = new DecoratedTableData(); + + java.util.List targetStringList = new java.util.ArrayList(); + Object[] selectedObz = availableTableDataNameList.getSelectedValues(); + for (Object ob : selectedObz) { + if (ob instanceof String) { + targetStringList.add((String)ob); + } + } + td.setRelatedTableDataNames(targetStringList.toArray(new String[0])); + + return td; + } + + @Override + public DecoratedTableData updateBean() { + DecoratedTableData td = updateBeanExcludeFilter(); + td.setCondition(conditionPane.updateBean()); + + return td; + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("DS-Relation_TableData"); + } + + /** + * 选中组件改变事件 + * + * @param taget 目标 + */ + public void selectionChanged(CheckBoxList target) { + DecoratedTableData updatedBean = updateBeanExcludeFilter(); + DataModel model = updatedBean.createDataModel(Calculator.createCalculator()); + java.util.List columnList = new java.util.ArrayList(); + try { + for (int i = 0, len = model.getColumnCount(); i < len; i++) { + columnList.add(model.getColumnName(i)); + } + } catch (TableDataException e) { + FRContext.getLogger().error(e.getMessage(), e); + return; + } + + this.conditionPane.populateColumns(columnList.toArray(new String[0])); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataDefinedPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataDefinedPane.java new file mode 100644 index 0000000000..ae8d763556 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableDataDefinedPane.java @@ -0,0 +1,321 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Date; + +import javax.swing.DefaultCellEditor; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableColumn; + +import com.fr.base.FRContext; +import com.fr.data.impl.EmbeddedTableData; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +public class EmbeddedTableDataDefinedPane extends BasicPane{ + + private EmbeddedTableData tableData; + private JTable dataJTable; + private UIButton add; + private UIButton del; + + private static String[] TYPE = { + Inter.getLocText("String"), + Inter.getLocText("Integer"), + Inter.getLocText("Double"), + Inter.getLocText("Date") + }; + + public EmbeddedTableDataDefinedPane() { + initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + dataJTable = new JTable(new EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel(new EmbeddedTableData())); + JScrollPane scrollPane = new JScrollPane(dataJTable); + this.add(scrollPane, BorderLayout.CENTER); + dataJTable.setRowSelectionAllowed(true); + dataJTable.setColumnSelectionAllowed(true); + + // 类型选择 + UIComboBox typeBox = new UIComboBox(TYPE); + dataJTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(typeBox)); + + // 单击编辑 + TableCellEditor tableCellEditor = dataJTable.getDefaultEditor(String.class); + if (tableCellEditor != null) { + (( DefaultCellEditor) tableCellEditor).setClickCountToStart(1); + } + + // 行号显示 + TableColumn tableColumn = dataJTable.getColumnModel().getColumn(0); + tableColumn.setCellRenderer(new CellRenderer()); + tableColumn.setMaxWidth(30); + + // 控制按钮 + add = new UIButton(Inter.getLocText("Add")); + del = new UIButton(Inter.getLocText("Delete")); + JPanel buttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); +// buttonPane.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + buttonPane.add(add); + buttonPane.add(del); + this.add(buttonPane, BorderLayout.NORTH); + + add.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + insertRow(); + checkEnabled(); + } + }); + del.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + removeRow(); + checkEnabled(); + } + }); + checkEnabled(); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText(new String[]{"Column", "Set"}); + } + + public void checkValid() throws Exception { + try { + dataJTable.getCellEditor().stopCellEditing(); + } + catch (Exception e) { + } + } + + public void insertRow(){ + EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel localDefaultModel = + (EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel) dataJTable.getModel(); + + try { + dataJTable.getCellEditor().stopCellEditing(); + } + catch (Exception e) { + } + + int indexedrow = dataJTable.getSelectedRow(); + if (indexedrow == - 1) { + indexedrow = dataJTable.getRowCount() - 1; + } + + localDefaultModel.addNewRowData(indexedrow); + localDefaultModel.fireTableDataChanged(); + dataJTable.requestFocusInWindow(); + dataJTable.setRowSelectionInterval(indexedrow + 1, indexedrow + 1); + dataJTable.editCellAt(indexedrow + 1, 1); + } + + protected void removeRow() { + EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel localDefaultModel = + (EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel) dataJTable.getModel(); + + int selectedRow = dataJTable.getSelectedRow(); + if (selectedRow == -1) { + selectedRow = dataJTable.getRowCount() - 1; + } + + try { + dataJTable.getCellEditor().stopCellEditing(); + } + catch (Exception e) { + } + + for (int i = 0; i < dataJTable.getSelectedRowCount(); i++){ + localDefaultModel.removeRow(selectedRow); + } + localDefaultModel.fireTableDataChanged(); + + int rowCount = localDefaultModel.getRowCount(); + if (rowCount > 0) { + if (selectedRow < rowCount) { + dataJTable.setRowSelectionInterval(selectedRow, selectedRow); + } + else { + dataJTable.setRowSelectionInterval(rowCount - 1, rowCount - 1); + } + } + } + + private void checkEnabled() { + this.dataJTable.setEnabled(true); + this.del.setEnabled(true); + this.add.setEnabled(true); + + if (dataJTable.getRowCount() <=0 ) { + this.del.setEnabled(false); + } + } + + public void populate(Object obj) { + if(obj == null || !(obj instanceof EmbeddedTableData)) { + return; + } + try { + this.tableData = (EmbeddedTableData)obj; + + EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel localDefaultModel = + (EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel) dataJTable.getModel(); + localDefaultModel.setEditableTableData((EmbeddedTableData)tableData.clone()); + localDefaultModel.fireTableDataChanged(); + checkEnabled(); + } catch (CloneNotSupportedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + + public EmbeddedTableData update() { + if(dataJTable.getCellEditor() != null){ + dataJTable.getCellEditor().stopCellEditing(); + } + EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel localDefaultModel = + (EmbeddedTableDataDefinedPane.EmbeddedTableDefinedModel) dataJTable.getModel(); + try { + tableData = (EmbeddedTableData)(localDefaultModel.getEditableTableData().clone()); + } catch (CloneNotSupportedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + return tableData; + } + + class CellRenderer extends DefaultTableCellRenderer { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (column == 0) { + setBackground(new Color(229, 229, 229)); + setHorizontalAlignment(CENTER); + } + return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } + } + + class EmbeddedTableDefinedModel extends AbstractTableModel { + private EmbeddedTableData embeddedTableData; + private String[] COLUMN_NAME = { + "", + Inter.getLocText("ColumnName"), + Inter.getLocText("Type") + }; + private int sum = 0; + + public EmbeddedTableDefinedModel(EmbeddedTableData editableTableData) { + this.embeddedTableData = editableTableData; + } + + public EmbeddedTableData getEditableTableData() { + return embeddedTableData; + } + + public void setEditableTableData(EmbeddedTableData editableTableData) { + this.embeddedTableData = editableTableData; + } + + public String getColumnName(int column) { + if (column < COLUMN_NAME.length) { + return COLUMN_NAME[column]; + } else { + return ""; + } + } + + public Class getColumnClass(int column) { + return String.class; + } + + public int getRowCount() { + return embeddedTableData.getColumnCount(); + } + + public int getColumnCount() { + return 3; + } + + public Object getValueAt(int row, int column) { + switch (column) { + case 0: + return Integer.toString(row + 1); + case 1: + return embeddedTableData.getColumnName(row); + case 2: + if (embeddedTableData.getColumnClass(row).equals(String.class)) { + return TYPE[0]; + } else if (embeddedTableData.getColumnClass(row).equals(Integer.class)) { + return TYPE[1]; + } else if (embeddedTableData.getColumnClass(row).equals(Double.class)) { + return TYPE[2]; + } else if (embeddedTableData.getColumnClass(row).equals(Date.class)) { + return TYPE[3]; + } + } + return null; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex !=0; + } + + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + break; + case 1: + embeddedTableData.setColumn(rowIndex, (String)aValue, embeddedTableData.getColumnClass(rowIndex)); + break; + case 2: + Class cls = null; + if (((String)aValue).equals(TYPE[0])){ + cls = String.class; + } else if (((String)aValue).equals(TYPE[1])){ + cls = Integer.class; + } else if (((String)aValue).equals(TYPE[2])){ + cls = Double.class; + } else if (((String)aValue).equals(TYPE[3])){ + cls = Date.class; + } + embeddedTableData.setColumn(rowIndex, embeddedTableData.getColumnName(rowIndex), cls); + break; + } + } + + public void addNewRowData(int index) { + int n= embeddedTableData.getColumnCount(); + sum++; + for(int i=0;i { + private JTable dataJTable ; + private JScrollPane scrollPane; + private UILabel coordinatelabel; + private UIButton insertRowButton; + private UIButton removeRowButton; + private UIButton columnSetButton; + + /** + * Constructor + * + */ + public EmbeddedTableDataPane() { + initComponents(); + } + + // additional methods + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + // prepare the data in this way as default if no arguments is passed in + dataJTable = new JTable(new EmbeddedTableModel(new EmbeddedTableData())); + scrollPane = new JScrollPane(dataJTable); + this.add(scrollPane, BorderLayout.CENTER); + + // 显示double,date类;渲染date类 + dataJTable.setDefaultRenderer(Double.class, new DoubleRenderer()); + dataJTable.setDefaultRenderer(Date.class, new DateRenderer()); + dataJTable.setDefaultEditor(Date.class, new DateEditor(new UIDatePicker(UIDatePicker.STYLE_CN_DATE1))); + tableStructureChanged(); + + // 单击即可编辑 + editbysingleclick(dataJTable, String.class); + editbysingleclick(dataJTable, Date.class); + editbysingleclick(dataJTable, Double.class); + editbysingleclick(dataJTable, Integer.class); + + // AUTO RESIZE + // dataJTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); + dataJTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + dataJTable.setRowSelectionAllowed(true); + dataJTable.setColumnSelectionAllowed(true); + + + // peter:控制Panel + JPanel northPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + this.add(northPane, BorderLayout.NORTH); + northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 3, 0)); + + // kel:在左上角加一个JLabel用来显示坐标,方便用户查看。 + coordinatelabel = new UILabel("0/0,0/0"); + coordinatelabel.setHorizontalAlignment(UILabel.CENTER); + northPane.add(coordinatelabel); + + dataJTable.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + // kel:加上一个鼠标点击的监控,鼠标点击时,返回选中的行坐标和列坐标。 + selectedChanged(); + } + }); + dataJTable.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + selectedChanged(); + } + }); + initOtherNorthPaneComponents(northPane); + + } + + private void initOtherNorthPaneComponents(JPanel northPane) { + // 表结构设置 + columnSetButton = new UIButton(Inter.getLocText(new String[]{"Table", "Design"})); + columnSetButton.setMnemonic('C'); + northPane.add(columnSetButton); + columnSetButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + + final EmbeddedTableModel localDefaultModel = (EmbeddedTableModel) dataJTable.getModel(); + final EmbeddedTableDataDefinedPane columnSetPane = new EmbeddedTableDataDefinedPane(); + columnSetPane.populate(((EmbeddedTableModel) dataJTable.getModel()).getEditableTableData()); + + DialogActionAdapter l = new DialogActionAdapter() { + public void doOk() { + localDefaultModel.setEditableTableData(columnSetPane.update()); + localDefaultModel.fireTableStructureChanged(); + localDefaultModel.fireTableDataChanged(); + tableStructureChanged(); + selectedChanged(); + } + }; + + BasicDialog dlg = columnSetPane.showWindow(DesignerContext.getDesignerFrame(), l); + dlg.setAlwaysOnTop(true); + dlg.setVisible(true); + } + }); + + // DataSourceEditor-Insert_Row + insertRowButton = new UIButton(Inter.getLocText("Utils-Insert_Row")); + insertRowButton.setMnemonic('I'); + northPane.add(insertRowButton); + insertRowButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + insertRow(); + } + }); + + // DataSourceEditor-Remove_Row + removeRowButton = new UIButton(Inter.getLocText("Utils-Delete_Row")); + removeRowButton.setMnemonic('R'); + northPane.add(removeRowButton); + removeRowButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + removeRow(); + } + }); + + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("DS-Embedded_TableData"); + } + + + + @Override + public void checkValid() throws Exception { + // alex:停止当前的编辑 + try { + dataJTable.getCellEditor().stopCellEditing(); + } catch (Exception e) { + } + } + + private void selectedChanged() { + int a = dataJTable.getSelectedRow() + 1, b = dataJTable.getSelectedColumn(), c = dataJTable.getRowCount(), d = dataJTable.getColumnCount() - 1; + if (b < 0) { + b = 0; + } + String coordinate = a + "/" + c + "," + b + "/" + d; + coordinatelabel.setText(coordinate); + } + + + @Override + public void populateBean(EmbeddedTableData ob) { + EmbeddedTableModel localDefaultModel = (EmbeddedTableModel) dataJTable.getModel(); + localDefaultModel.clear(); + // 读取tabeldata + for (int i = 0; i < ob.getColumnCount(); i++) { + String columnName = ob.getColumnName(i); + Class columnClass = ob.getColumnClass(i); + localDefaultModel.addColumn(columnName, columnClass); + } + for (int j = 0; j < ob.getRowCount(); j++) { + localDefaultModel.addNewRowData(j); + } + for (int i = 0; i < ob.getColumnCount(); i++) { + for (int j = 0; j < ob.getRowCount(); j++) { + localDefaultModel.setValueAt(ob.getValueAt(j, i), j, i + 1); + } + } + localDefaultModel.fireTableStructureChanged(); + localDefaultModel.fireTableDataChanged(); + tableStructureChanged(); + this.repaint(); + } + + @Override + public EmbeddedTableData updateBean() { + if (dataJTable.getCellEditor() != null) { + dataJTable.getCellEditor().stopCellEditing(); + } + EmbeddedTableModel localDefaultModel = (EmbeddedTableModel) dataJTable.getModel(); + try { + return (EmbeddedTableData) localDefaultModel.getEditableTableData().clone(); + } catch (CloneNotSupportedException e) { + FRContext.getLogger().error(e.getMessage(), e); + return new EmbeddedTableData(); + } + } + + private void tableStructureChanged() { + // 行号显示,每次dateJTable的表结构发生变化时都要调用 + TableColumn tableColumn = dataJTable.getColumnModel().getColumn(0); + tableColumn.setCellRenderer(new CellRenderer()); + tableColumn.setMaxWidth(30); + } + + private class DoubleRenderer extends DefaultTableCellRenderer { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + setHorizontalAlignment(RIGHT); + return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } + } + + private class DateRenderer extends DefaultTableCellRenderer { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + Date date2Format = DateUtils.object2Date(value, true); + return super.getTableCellRendererComponent(table, date2Format == null ? StringUtils.EMPTY : DateUtils.DATEFORMAT1.format(date2Format), isSelected, hasFocus, row, + column); + } + } + + private class DateEditor extends DefaultCellEditor { + public DateEditor(final UIDatePicker datepicker) { + super(datepicker); + } + + public Object getCellEditorValue() { + SimpleDateFormat simpledateformat = new SimpleDateFormat("yyyy-MM-dd"); + Date date = null; + try { + synchronized (this) { + date = simpledateformat.parse(((UIDatePicker) this.editorComponent).getSelectedItem().toString()); + } + } catch (Exception e) { + date = new Date(); + } + return date; + } + + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + Date date = DateUtils.object2Date(value, false); + return super.getTableCellEditorComponent(table, date, isSelected, row, column); + } + } + + private class CellRenderer extends DefaultTableCellRenderer { + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (column == 0) { + setBackground(new Color(229, 229, 229)); + setHorizontalAlignment(CENTER); + } + return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + } + } + + private void editbysingleclick(JTable table, Class cls) { + TableCellEditor tableCellEditor = table.getDefaultEditor(cls); + if (tableCellEditor != null) { + ((DefaultCellEditor) tableCellEditor).setClickCountToStart(1); + } + } + + + private void insertRow() { + EmbeddedTableModel localDefaultModel = (EmbeddedTableModel) dataJTable.getModel(); + + // alex:停止当前的编辑 + try { + dataJTable.getCellEditor().stopCellEditing(); + } catch (Exception e) { + } + + int indexedrow = dataJTable.getSelectedRow(); + int indexedcol = dataJTable.getSelectedColumn(); + if (indexedrow == -1) { + indexedrow = dataJTable.getRowCount(); + } + if (indexedcol == -1) { + indexedcol = 0; + } + + localDefaultModel.addNewRowData(indexedrow); + localDefaultModel.fireTableDataChanged(); + // kel:添加一个focus监控,在插入行时获得焦点。(未实现) + dataJTable.requestFocusInWindow(); + dataJTable.setRowSelectionInterval(indexedrow, indexedrow); + dataJTable.setColumnSelectionInterval(indexedcol, indexedcol); + dataJTable.editCellAt(indexedrow, indexedcol); + selectedChanged(); + } + + + private void removeRow() { + EmbeddedTableModel localDefaultModel = (EmbeddedTableModel) dataJTable.getModel(); + + // peter:开始删除行 + int selectedRow = dataJTable.getSelectedRow(); + + int selectedCol = dataJTable.getSelectedColumn(); + if (selectedRow == -1) { + selectedRow = dataJTable.getRowCount() - 1; + } + if (selectedCol == -1) { + selectedCol = 0; + } + + // alex:停止当前的编辑 + try { + dataJTable.getCellEditor().stopCellEditing(); + } catch (Exception e) { + } + + for (int i = 0; i < dataJTable.getSelectedRowCount(); i++) { + localDefaultModel.removeRow(selectedRow); + } + localDefaultModel.fireTableDataChanged(); + + // peter:调整Selection + int rowCount = localDefaultModel.getRowCount(); + if (rowCount > 0) { + if (selectedRow < rowCount) { + dataJTable.setRowSelectionInterval(selectedRow, selectedRow); + dataJTable.setColumnSelectionInterval(selectedCol, selectedCol); + dataJTable.editCellAt(selectedRow, selectedCol); + } else { + dataJTable.setRowSelectionInterval(rowCount - 1, rowCount - 1); + dataJTable.setColumnSelectionInterval(selectedCol, selectedCol); + dataJTable.editCellAt(rowCount - 1, selectedCol); + } + } + selectedChanged(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableModel.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableModel.java new file mode 100644 index 0000000000..82ab209e40 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/EmbeddedTableModel.java @@ -0,0 +1,103 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import javax.swing.table.AbstractTableModel; + +import com.fr.data.impl.EmbeddedTableData; + +public class EmbeddedTableModel extends AbstractTableModel { + private EmbeddedTableData embeddedTableData; + + public EmbeddedTableModel(EmbeddedTableData editableTableData) { + this.embeddedTableData = editableTableData; + } + + public EmbeddedTableData getEditableTableData() { + return embeddedTableData; + } + + public void setEditableTableData(EmbeddedTableData editableTableData) { + this.embeddedTableData = editableTableData; + } + + public String getColumnName(int column) { + if (column == 0) { + return ""; + } else { + return embeddedTableData.getColumnName(column - 1); + } + } + + public Class getColumnClass(int column) { + if (column == 0) { + return String.class; + } else { + return embeddedTableData.getColumnClass(column - 1); + } + } + + public int getRowCount() { + return embeddedTableData.getRowCount(); + } + + public int getColumnCount() { + if (embeddedTableData.getColumnCount() == 0) { + return 1; + } else { + return embeddedTableData.getColumnCount() + 1; + } + } + + public Object getValueAt(int row, int column) { + if (column == 0) { + return Integer.toString(row + 1); + } else { + return embeddedTableData.getValueAt(row, column - 1); + } + } + + /** + * Returns false. This is the default implementation for all cells. + * + * @param rowIndex the row being queried + * @param columnIndex the column being queried + */ + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex != 0; + } + + /** + * This empty implementation is provided so users don't have to implement + * this method if their data model is not editable. + * + * @param aValue value to assign to cell + * @param rowIndex row of cell + * @param columnIndex column of cell + */ + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (columnIndex != 0) { + this.embeddedTableData.setValueAt(aValue, rowIndex, columnIndex - 1); + } + } + + /** + * Add column. + * + * @param columnName column name + * @param columnClass column class + */ + public void addColumn(String columnName, Class columnClass) { + embeddedTableData.addColumn(columnName, columnClass); + } + + public void addNewRowData(int index) { + embeddedTableData.addNewRow(index); + } + + public void removeRow(int rowIndex) { + embeddedTableData.removeRow(rowIndex); + } + + public void clear() { + embeddedTableData.clear(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java new file mode 100644 index 0000000000..0a05e1893c --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataPane.java @@ -0,0 +1,997 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.Parameter; +import com.fr.base.ParameterHelper; +import com.fr.base.Utils; +import com.fr.data.core.datasource.FileDataSource; +import com.fr.data.core.datasource.URLDataSource; +import com.fr.data.core.define.XMLColumnNameType; +import com.fr.data.impl.ExcelTableData; +import com.fr.data.impl.FileTableData; +import com.fr.data.impl.TextTableData; +import com.fr.data.impl.XMLTableData; +import com.fr.design.actions.UpdateAction; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.ToolBarDef; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.general.data.DataSource; +import com.fr.stable.ArrayUtils; +import com.fr.stable.EncodeConstants; +import com.fr.stable.ParameterProvider; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLReadable; +import com.fr.stable.xml.XMLableReader; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +public class FileTableDataPane extends AbstractTableDataPane { + private static final int TEXT = 0; + private static final int EXCEL = 1; + private static final int XML = 2; + private static final double B = 20; + private static final int EIGHT = 8; + private static final String ROOTTAG = "XML"; + private static final String STARTTAG = ""; + private static final String ENDTAG = ""; + + private UIComboBox fileTypeComboBox; + private UITextField localText; + private UITextField urlText; + private UIRadioButton localFileRadioButton; + private UIRadioButton urlFileRadioButton; + private UITableEditorPane editorPane; + private UILabel tips; + private UIComboBox xmlKyePoint;// xml关键节点 + private UIComboBox encodingComboBox;// xml编码 + private FileTableData fileTableData; + private UIButton chooseFile; + private UIButton testConnection; + private XMLNodeTree xmlNodeTree; + private Parameter[] params; + private JPanel filePath; + private XMLNodeTreePane nodeTreePane; + + private UICheckBox needColumnNameCheckBox;// 第一行是否作为标题 + private UIRadioButton tableDismemberRadioButton;// 制表符 + private UIRadioButton spaceDismenberRadioButton;// 空格符,也是默认的分隔符 + private UIRadioButton commaDismenberRadioButton;// 逗号 + private UIRadioButton otherDismenberRadioButton;// 其他 + private UITextField otherDismenberTextField;// 其他分隔符编辑 + private UICheckBox igoreOneMoreDelimiterCheckBox;// 连续分隔符是否作为单一 + private UIComboBox charsetComboBox; + private UILabel encodeLabel; + private UILabel dismenberLabel; + private UILabel keyPointLaber; + private ExpandMutableTreeNode selectedNode = null; + private ExpandMutableTreeNode finalSelectedNode = null; + + + private ArrayList xmlColumnsList = new ArrayList(); + private static final int SETPANELWIDTH = 337; + private static final int WIDTH = 317; + private static final int HEIGHT = 453; + private static final int GAP = 23; + + + public FileTableDataPane(){ + this(SETPANELWIDTH,WIDTH,HEIGHT,GAP); + } + + public FileTableDataPane(int setPanelWidth,int width,int height,int gap) { + this.setLayout(new BorderLayout(gap,0)); + JPanel northPanel = new JPanel(new BorderLayout()); + JPanel type = new JPanel(); + type.add(new UILabel(Inter.getLocText("Utils-File_type") + ":")); + String[] item = {"TXT", "Excel", "XML"}; + fileTypeComboBox = new UIComboBox(item); + fileTypeComboBox.setPreferredSize(new Dimension(100, 20)); + type.add(fileTypeComboBox); + northPanel.add(type, BorderLayout.WEST); + + // 最上面的pane,文件选择 + JPanel centerPanel = new JPanel(); + centerPanel.setPreferredSize(new Dimension(522, 200)); + centerPanel.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("FR-Designer-File_address"))); + addToCenterPanel(centerPanel); + + // 下面的pane,参数面板 + ParameterTableModel model = new ParameterTableModel() { + @Override + public UITableEditAction[] createAction() { + return (UITableEditAction[]) ArrayUtils.add(null, new RefreshAction()); + } + }; + editorPane = new UITableEditorPane(model); + editorPane.setPreferredSize(new Dimension(355, 130)); + centerPanel.add(editorPane, BorderLayout.SOUTH); + + JPanel southPanel = new JPanel(new BorderLayout()); + JPanel setPanel = new JPanel(); + southPanel.add(setPanel, BorderLayout.CENTER); + setPanel.setPreferredSize(new Dimension(setPanelWidth, 460)); + setPanel.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("FR-Designer_Set"))); + JPanel controlPane = textSetPanel(width,height); + setPanel.add(controlPane, BorderLayout.NORTH); + fileTypeComboBox.addActionListener(getFileTypeListener(setPanel,width,height)); + + this.add(northPanel, BorderLayout.NORTH); + this.add(centerPanel, BorderLayout.CENTER); + this.add(southPanel, BorderLayout.EAST); + } + + private void addToCenterPanel(JPanel centerPanel){ + localFileRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer-Local_file") + ":", true); + urlFileRadioButton = new UIRadioButton("URL:", false); + ButtonGroup bg = new ButtonGroup(); + bg.add(localFileRadioButton); + bg.add(urlFileRadioButton); + localFileRadioButton.addActionListener(radioActionListener); + urlFileRadioButton.addActionListener(radioActionListener); + urlFileRadioButton.setForeground(new Color(143, 142, 139)); + localFileRadioButton.setForeground(Color.black); + localText = new UITextField(); + localText.setPreferredSize(new Dimension(195, 20)); + urlText = new UITextField(); + urlText.setPreferredSize(new Dimension(195, 20)); + urlText.setEditable(false); + chooseFile = new UIButton(Inter.getLocText("FR-Designer_Selection")); + chooseFile.addActionListener(chooseFileListener); + + testConnection = new UIButton(Inter.getLocText("Datasource-Test_Connection")); + testConnection.setEnabled(false); + testConnection.addActionListener(testConnectionListener);// 测试连接按钮 + + JPanel textPanel = new JPanel(new GridLayout(2, 1, 15, 15)); + JPanel textFieldPanel = new JPanel(new GridLayout(2, 1, 15, 15)); + JPanel buttonPanel = new JPanel(new GridLayout(2, 1, 15, 15)); + textPanel.add(localFileRadioButton); + textPanel.add(urlFileRadioButton); + textFieldPanel.add(localText); + textFieldPanel.add(urlText); + buttonPanel.add(chooseFile); + buttonPanel.add(testConnection); + filePath = FRGUIPaneFactory.createBorderLayout_S_Pane(); + filePath.add(textPanel, BorderLayout.WEST); + filePath.add(textFieldPanel, BorderLayout.CENTER); + filePath.add(buttonPanel, BorderLayout.EAST); + centerPanel.add(filePath, BorderLayout.NORTH); + + // 中间的pane,提示信息 + String tipContent = Inter.getLocText("FR-Designer-Type_Parameter") + "reportlets/excel/FineReport${abc}." + "txt" + "
" + + "http://192.168.100.120:8080/XXServer/Report/excel${abc}.jsp
" + "  "; + tips = new UILabel(tipContent); + centerPanel.add(tips, BorderLayout.CENTER); + } + + private ActionListener testConnectionListener = new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + String uri = urlText.getText(); + if (!checkURL(uri)) { + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(FileTableDataPane.this), Inter.getLocText("FR-Designer_Add_JS_warning")); + return; + } + params = getEditorPaneParameter(); + URLDataSource url = new URLDataSource(urlText.getText().trim(), params); + InputStream in = null; + try { + in = url.getSourceStream(params); + } catch (Throwable e) { + FRContext.getLogger().error(e.getMessage(), e); + } + if (in == null) { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Datasource-Connection_failed")); + } else { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Datasource-Connection_successfully")); + try { + in.close(); + } catch (IOException e) { + in = null; + } + } + } + }; + + private void previewPanel(JPanel jPanel){ + JPanel previewPanel = new JPanel(new BorderLayout()); + UIButton preview = new UIButton(Inter.getLocText("FR-Designer_Preview")); + preview.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + preview(); + } + }); + previewPanel.add(preview, BorderLayout.EAST); + jPanel.add(previewPanel, BorderLayout.SOUTH); + } + + private JPanel xmlSetPanel(int width,int height) { + // xml设置pane + JPanel controlPane = new JPanel(); + JPanel northPane = new JPanel(new BorderLayout(8,8)); + JPanel northTopPane = new JPanel(new BorderLayout(8,8)); + JPanel southPane = new JPanel(new BorderLayout(8,8)); + JPanel southTopPane = new JPanel(new BorderLayout(8,8)); + JPanel westPane = new JPanel(new BorderLayout()); + controlPane.setLayout(new BorderLayout(8,8)); + controlPane.setPreferredSize(new Dimension(width, height)); + JPanel comboboxPanel = new JPanel(new BorderLayout(8,8)); + encodeLabel = new UILabel(Inter.getLocText("FR-Designer-Encoding_Type") + ":"); + encodingComboBox = new UIComboBox(EncodeConstants.ALL_ENCODING_ARRAY); + encodingComboBox.setSelectedIndex(4); + encodingComboBox.setPreferredSize(new Dimension(90, 20)); + + JPanel treeContainerPane = new JPanel(); + treeContainerPane.setLayout(new BorderLayout(8,8)); + nodeTreePane = new XMLNodeTreePane(); + treeContainerPane.add(nodeTreePane,BorderLayout.CENTER); + + + comboboxPanel.add(encodeLabel, BorderLayout.WEST); + comboboxPanel.add(encodingComboBox, BorderLayout.CENTER); + + northPane.add(comboboxPanel,BorderLayout.EAST); + northTopPane.add(northPane,BorderLayout.WEST); + southTopPane.add(southPane,BorderLayout.WEST); + southTopPane.add(treeContainerPane,BorderLayout.CENTER); + controlPane.add(northTopPane, BorderLayout.NORTH); + controlPane.add(southTopPane,BorderLayout.CENTER); + previewPanel(controlPane); + return controlPane; + } + + private JPanel excelSetPanel(int width,int height) { + // excel设置pane + int checkBoxWidth = width - EIGHT; + JPanel controlPane = new JPanel(); + JPanel northPane = new JPanel(new BorderLayout(8,8)); + controlPane.setLayout(new BorderLayout()); + controlPane.setPreferredSize(new Dimension(width,height)); + needColumnNameCheckBox = new UICheckBox(Inter.getLocText("FR-Designer-FirstRow_IS_ColumnName"), false); + needColumnNameCheckBox.setPreferredSize(new Dimension(checkBoxWidth, 20)); + northPane.add(needColumnNameCheckBox, BorderLayout.EAST); + controlPane.add(northPane, BorderLayout.NORTH); + previewPanel(controlPane); + return controlPane; + } + + private String getFilePathFromUrlOrLocal() { + if (StringUtils.isNotEmpty(localText.getText()) && localFileRadioButton.isSelected()) { + return localText.getText().trim(); + } else if (StringUtils.isNotEmpty(urlText.getText()) && urlFileRadioButton.isSelected()) { + return urlText.getText().trim(); + } + return ""; + } + + /** + * 检查链接是否可用 + * + * @throws Exception + */ + public void checkValid() throws Exception { + if (urlFileRadioButton.isSelected()) { + String url = urlText.getText().trim(); + if (!checkURL(url)) { + throw new Exception(Inter.getLocText("FR-Designer_Add_JS_warning")); + } + } + + } + + private boolean checkURL(String uri){ + return (uri.matches("https*://.+|\\$\\{.+\\}.*")); + } + + private JPanel textSetPanel(int width,int height) { + // text设置pane + JPanel controlPane = new JPanel(); + controlPane.setLayout(new BorderLayout()); + controlPane.setPreferredSize(new Dimension(width,height)); + JPanel northPane = new JPanel(new BorderLayout(8,8)); + addToNorthPane(northPane); + controlPane.add(northPane,BorderLayout.WEST); + previewPanel(controlPane); + return controlPane; + } + + private void addToNorthPane(JPanel northPane){ + double f = TableLayout.FILL; + double p = TableLayout.PREFERRED; + double columnSize[] = {f, p, p}; + double rowSize[] = {B, B, B, B, B, B, B}; + needColumnNameCheckBox = new UICheckBox(Inter.getLocText("FR-Designer-FirstRow_IS_ColumnName"), true); + dismenberLabel = new UILabel(Inter.getLocText("FR-Designer_Dismenber") + ":"); + tableDismemberRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_TableDismember"), false); + tableDismemberRadioButton.setToolTipText(Inter.getLocText("FR-Designer_TableDismember")); + spaceDismenberRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_Space"), true); + spaceDismenberRadioButton.setToolTipText(Inter.getLocText("FR-Designer_Space")); + commaDismenberRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_CommaDismenber"), false); + commaDismenberRadioButton.setToolTipText(Inter.getLocText("FR-Designer_CommaDismenber")); + otherDismenberRadioButton = new UIRadioButton(Inter.getLocText("FR-Designer_Other") + ":", false); + otherDismenberRadioButton.setToolTipText(Inter.getLocText("FR-Designer_Other")); + otherDismenberTextField = new UITextField(8); + otherDismenberTextField.setEditable(false); + otherDismenberRadioButton.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent arg0) { + if (otherDismenberRadioButton.isSelected()) { + otherDismenberTextField.setEditable(true); + } else { + otherDismenberTextField.setEditable(false); + } + } + }); + ButtonGroup bg2 = new ButtonGroup(); + bg2.add(tableDismemberRadioButton); + bg2.add(spaceDismenberRadioButton); + bg2.add(commaDismenberRadioButton); + bg2.add(otherDismenberRadioButton); + igoreOneMoreDelimiterCheckBox = new UICheckBox(Inter.getLocText("FR-Designer-Series_Dismenber_As_Single"), true); + encodeLabel = new UILabel(Inter.getLocText("FR-Designer-Encoding_Type") + ":"); + charsetComboBox = new UIComboBox(EncodeConstants.ALL_ENCODING_ARRAY); + Component[][] comps = { + {encodeLabel,charsetComboBox,null}, + {needColumnNameCheckBox,null,null}, + {dismenberLabel,tableDismemberRadioButton,null}, + {null,spaceDismenberRadioButton,null}, + {null,commaDismenberRadioButton,null}, + {null,otherDismenberRadioButton,otherDismenberTextField}, + {igoreOneMoreDelimiterCheckBox,null,null} + }; + northPane.add(TableLayoutHelper.createTableLayoutPane(comps, rowSize, columnSize),BorderLayout.EAST); + } + + private ActionListener radioActionListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (localFileRadioButton.isSelected()) { + localRadioSelectAction(); + urlFileRadioButton.setForeground(new Color(143, 142, 139)); + localFileRadioButton.setForeground(Color.black); + } else if (urlFileRadioButton.isSelected()) { + urlRadioSelectAction(); + localFileRadioButton.setForeground(new Color(143, 142, 139)); + urlFileRadioButton.setForeground(Color.black); + } + } + }; + + private void localRadioSelectAction() { + localFileRadioButton.setSelected(true); + localText.setEditable(true); + chooseFile.setEnabled(true); + urlText.setEditable(false); + urlText.setText(""); + testConnection.setEnabled(false); + } + + private void urlRadioSelectAction() { + urlFileRadioButton.setSelected(true); + urlText.setEditable(true); + testConnection.setEnabled(true); + localText.setEditable(false); + localText.setText(""); + chooseFile.setEnabled(false); + } + + private ActionListener chooseFileListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + FILEChooserPane fileChooser = FILEChooserPane.getInstance(true, false, new ChooseFileFilter(getFileSuffix())); + if (fileChooser.showOpenDialog(DesignerContext.getDesignerFrame()) == FILEChooserPane.OK_OPTION) { + final FILE file = fileChooser.getSelectedFILE(); + if (file == null) {// 选择的文件不能是 null + return; + } + localText.setText(file.getPath()); + } + + fileChooser.removeFILEFilter(new ChooseFileFilter(getFileSuffix())); + if (fileTypeComboBox.getSelectedIndex() == XML) { + xmlNodeTree.waitRefresh(); + xmlNodeTree.refreshData(); + } + } + }; + + private String[] getFileSuffix() { + List suffixList = new ArrayList(); + String suffix = fileTypeComboBox.getSelectedItem().toString().toLowerCase(); + if (suffix.equalsIgnoreCase("excel")) { + suffixList.add("xls"); + suffixList.add("xlsx"); + } else { + suffixList.add(suffix); + } + return suffixList.toArray(new String[suffixList.size()]); + } + + private ActionListener getFileTypeListener(final JPanel setPanel, final int width, final int height) { + ActionListener fileTypeListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + setPanel.removeAll(); + localText.setText(""); + urlText.setText(""); + if (fileTypeComboBox.getSelectedIndex() == XML) { + setPanel.add(xmlSetPanel(width,height), BorderLayout.NORTH); + } else if (fileTypeComboBox.getSelectedIndex() == EXCEL) { + setPanel.add(excelSetPanel(width,height), BorderLayout.NORTH); + } else { + setPanel.add(textSetPanel(width,height), BorderLayout.NORTH); + } + String tipContent = Inter.getLocText("FR-Designer-Type_Parameter") + "reportlets/excel/FineReport${abc}." + getFileSuffix() + "
" + + "http://192.168.100.120:8080/XXServer/Report/excel${abc}.jsp
" + "  "; + tips.setText(tipContent); + } + }; + + return fileTypeListener; + } + + private class RefreshAction extends UITableEditAction { + public RefreshAction() { + this.setName(Inter.getLocText("FR-Designer_Refresh")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + } + + public void actionPerformed(ActionEvent e) { + String[] paramTexts = new String[1]; + paramTexts[0] = getFilePathFromUrlOrLocal(); + + List existParameterList = editorPane.update(); + Parameter[] ps = existParameterList == null ? new Parameter[0] : existParameterList.toArray(new Parameter[existParameterList.size()]); + + editorPane.populate(ParameterHelper.analyzeAndUnionParameters(paramTexts, ps, false)); + } + + @Override + public void checkEnabled() { + } + } + + @Override + public void populateBean(FileTableData ob) { + fileTableData = ob; + + if (ob instanceof ExcelTableData) { + fileTypeComboBox.setSelectedIndex(EXCEL); + populate2EXCEL((ExcelTableData) ob); + } else if (ob instanceof XMLTableData) { + fileTypeComboBox.setSelectedIndex(XML); + populate2XML((XMLTableData) ob); + } else if (ob instanceof TextTableData) { + fileTypeComboBox.setSelectedIndex(TEXT); + populate2TEXT((TextTableData) ob); + } + } + + private void populate2EXCEL(ExcelTableData etd) { + setTextField(etd); + editorPane.populate(etd.getParams()); + needColumnNameCheckBox.setSelected(etd.needColumnName()); + } + + //wikky:为了使树能够正常展开,合法的xml文件把path中添加的XML节点去掉,而不合法的xml需要把根节点值还原为添加的ROOTTAG值。 + private void populate2XML(XMLTableData xtd) { + setTextField(xtd); + editorPane.populate(xtd.getParams()); + encodingComboBox.setSelectedItem(xtd.getCharSet()); + if (!ComparatorUtils.equals(xtd,new XMLTableData())) { + xmlNodeTree.initData(); + String[] path = xtd.getXPath(); + String[] paths; + if (path != null && path.length > 0) { + DefaultTreeModel treeModel = (DefaultTreeModel)xmlNodeTree.getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + if (treeModel != null) { + if(!ComparatorUtils.equals(treeModel.getRoot().toString(),"")){ + paths = new String[path.length - 1]; + for(int i = 1;i< path.length;i++){ + paths[i -1] = path[i]; + } + }else{ + paths = path; + root.setUserObject(ROOTTAG); + } + if (treeModel.getRoot() instanceof ExpandMutableTreeNode) { + selectNode((ExpandMutableTreeNode)treeModel.getRoot(), 0, paths); + if (selectedNode != null) { + TreePath treepath = new TreePath(treeModel.getPathToRoot(selectedNode)); + xmlNodeTree.setSelectionPath(treepath); + xmlNodeTree.expandPath(treepath); + } + } + //防止某种操作导致添加的tag作为root出现。 + if(ComparatorUtils.equals(root.toString(),ROOTTAG)){ + root.setUserObject(StringUtils.EMPTY); + } + } + } + } + } + + private void populate2TEXT(TextTableData ttd) { + setTextField(ttd); + String delimiter = ttd.getDelimiter(); + if (delimiter == null) { + return; + } + if (ComparatorUtils.equals(delimiter, "\t")) { + tableDismemberRadioButton.setSelected(true); + } else if (ComparatorUtils.equals(delimiter, ",")) { + commaDismenberRadioButton.setSelected(true); + } else if (ComparatorUtils.equals(delimiter, " ")) { + spaceDismenberRadioButton.setSelected(true); + } else { + otherDismenberRadioButton.setSelected(true); + otherDismenberTextField.setEditable(true); + otherDismenberTextField.setText(ttd.getDelimiter()); + } + editorPane.populate(ttd.getParams()); + needColumnNameCheckBox.setSelected(ttd.needColumnName()); + igoreOneMoreDelimiterCheckBox.setSelected(ttd.isIgnoreOneMoreDelimiter()); + charsetComboBox.setSelectedItem(ttd.getCharset()); + } + + private void setTextField(FileTableData ob) { + if (ob.getFilePath() != null) { + if (ob.getFilePath().indexOf("http") != -1) { + urlRadioSelectAction(); + urlText.setText(ob.getFilePath()); + } else { + localRadioSelectAction(); + localText.setText(ob.getFilePath()); + } + } + } + + @Override + public FileTableData updateBean() { + String filePath = getFilePathFromUrlOrLocal(); + if (StringUtils.isNotBlank(filePath)) { + this.params = getEditorPaneParameter().length == 0 ? null : getEditorPaneParameter(); + if (fileTypeComboBox.getSelectedIndex() == EXCEL) { + return update2EXCEL(filePath); + } else if (fileTypeComboBox.getSelectedIndex() == TEXT) { + return update2TEXT(filePath); + } else if (fileTypeComboBox.getSelectedIndex() == XML) { + return update2XML(filePath); + + } + } + return new FileTableData(); + } + + private TextTableData update2TEXT(String filePath) { + TextTableData ttd = new TextTableData(); + ttd.setFilePath(filePath); + ttd.setParams(this.params); + ttd.setDelimiter(this.showDelimiter()); + ttd.setIgnoreOneMoreDelimiter(igoreOneMoreDelimiterCheckBox.isSelected()); + ttd.setNeedColumnName(needColumnNameCheckBox.isSelected()); + ttd.setCharset((String)charsetComboBox.getSelectedItem()); + fileTableData = ttd; + return ttd; + } + + private ExcelTableData update2EXCEL(String filePath) { + ExcelTableData etd = new ExcelTableData(); + etd.setFilePath(filePath); + etd.setParams(this.params); + etd.setNeedColumnName(needColumnNameCheckBox.isSelected()); + fileTableData = etd; + return etd; + } + + private XMLTableData update2XML(String filePath) { + XMLTableData xtd = new XMLTableData(); + xtd.setFilePath(filePath); + xtd.setParams(this.params); + if (localFileRadioButton.isSelected()) { + xtd.setDataSource(new FileDataSource(filePath, this.params)); + } else { + xtd.setDataSource(new URLDataSource(filePath, this.params)); + } + xtd.setCharSet((String) encodingComboBox.getSelectedItem()); + finalSelectedNode = selectedNode; + if (selectedNode instanceof ExpandMutableTreeNode) { + xmlColumnsList.clear(); + ExpandMutableTreeNode treeNode; + boolean flag = true; + for(int i = 0;i < selectedNode.getChildCount();i++){ + treeNode = (ExpandMutableTreeNode) selectedNode.getChildAt(i); + if(treeNode.isLeaf()){ + xmlColumnsList.add(treeNode.toString()); + }else{ + if(flag){ + flag = false; + finalSelectedNode = treeNode; + leafNode(treeNode); + } + } + } + } + String[] paths = getPaths(); + xtd.setXPath(paths); + XMLColumnNameType[] nameTypes = new XMLColumnNameType[xmlColumnsList.size()]; + for (int i = 0; i < nameTypes.length; i++) { + nameTypes[i] = new XMLColumnNameType(xmlColumnsList.get(i), 0); + } + xtd.setColumns(nameTypes); + fileTableData = xtd; + return xtd; + } + + //wikky:构建树时为了美观把添加的根节点值赋为空显示,现在还得该回去使得预览时能够顺利取到数据。 + private String[] getPaths(){ + TreePath treePath = GUICoreUtils.getTreePath(finalSelectedNode); + String path = StringUtils.EMPTY; + if (treePath != null) { + Object[] paths = treePath.getPath(); + for (int i = 0; i < paths.length; i++) { + path+="/" + paths[i]; + } + } + if (path.startsWith("/")) { + path = path.substring(1); + } + String[] paths = path.split("/"); + if(ComparatorUtils.equals(paths[0],StringUtils.EMPTY)){ + paths[0] = ROOTTAG; + } + return paths; + } + + private void leafNode(ExpandMutableTreeNode treeNode){ + boolean flag = true; + ExpandMutableTreeNode firstNode; + for(int i = 0;i < treeNode.getChildCount();i++){ + firstNode = (ExpandMutableTreeNode) treeNode.getChildAt(i); + if(firstNode.isLeaf()){ + xmlColumnsList.add(firstNode.toString()); + }else{ + if(flag){ + flag = false; + finalSelectedNode = treeNode; + leafNode(firstNode); + } + } + } + } + + private void selectNode(ExpandMutableTreeNode node, int layer, String[] paths) { + if (selectedNode != null || node == null){ + return; + } + if (layer < paths.length && paths[layer] != null && ComparatorUtils.equals(paths[layer],node.getUserObject())) { + if (layer == paths.length -1) { + selectedNode = node; + return; + } + for (int i = 0; i < node.getChildCount(); i++) { + selectNode((ExpandMutableTreeNode)node.getChildAt(i), layer + 1, paths); + } + } + } + + private Parameter[] getEditorPaneParameter() { + String[] paramTexts = new String[1]; + paramTexts[0] = getFilePathFromUrlOrLocal(); + + List existParameterList = editorPane.update(); + Parameter[] ps = existParameterList == null ? new Parameter[0] : existParameterList.toArray(new Parameter[existParameterList.size()]); + + return ParameterHelper.analyzeAndUnionParameters(paramTexts, ps, false); + } + + private String showDelimiter() { + if (tableDismemberRadioButton.isSelected()) { + return "\t"; + } else if (commaDismenberRadioButton.isSelected()) { + return ","; + } else if (spaceDismenberRadioButton.isSelected()) { + return " "; + } else { + String other = otherDismenberTextField.getText(); + if (StringUtils.isEmpty(other)) { + other = " "; + } + return other; + } + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText(new String[]{"File", "DS-TableData"}); + } + + private void preview() { + if (this.fileTableData == null) { + return; + } + PreviewTablePane.previewTableData(this.updateBean()); + } + + private class XMLNodeTreePane extends BasicPane { + private RefreshParameterAction refreshAction; + + public XMLNodeTreePane() { + this.initComponents(); + } + + protected void initComponents() { + JPanel toolbarPanel = new JPanel(new BorderLayout()); + this.setLayout(new BorderLayout()); + xmlNodeTree = new XMLNodeTree(); + this.add(new JScrollPane(xmlNodeTree)); + + keyPointLaber = new UILabel(Inter.getLocText("FR-Designer_KeyPoint") + ":"); + refreshAction = new RefreshParameterAction(); + ToolBarDef toolbarDef = new ToolBarDef(); + toolbarDef.addShortCut(refreshAction); + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolbarDef.updateToolBar(toolBar); + toolbarPanel.add(keyPointLaber,BorderLayout.WEST); + toolbarPanel.add(toolBar,BorderLayout.EAST); + this.add(toolbarPanel, BorderLayout.NORTH); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + private class RefreshParameterAction extends UpdateAction { + public RefreshParameterAction() { + this.setName(Inter.getLocText("FR-Designer_Refresh")); + this.setMnemonic('r'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + } + + public void actionPerformed(ActionEvent e) { + xmlNodeTree.waitRefresh(); + xmlNodeTree.refreshData(); + } + } + } + + private class XMLNodeTree extends JTree { + private DefaultTreeModel treeModel; + + private DefaultTreeModel waitTreeModel = null; + + public XMLNodeTree() { + this.initComponents(); + this.setModel(null); + } + + protected void initComponents() { + this.putClientProperty("JTree.lineStyle", "Angled"); + this.setShowsRootHandles(true); + this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + this.addMouseListener(treeMouseListener); + + + this.setEditable(false); + } + + private MouseListener treeMouseListener = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (XMLNodeTree.this.getModel() != treeModel){ + return; + } + int selRow = XMLNodeTree.this.getRowForLocation(e.getX(), e.getY()); + if (selRow == -1) {//没有选中某个树节点,就直接返回啦 + return; + } + TreePath selPath = XMLNodeTree.this.getPathForLocation(e.getX(), e.getY()); + if (selPath == null || selPath.getLastPathComponent() == null) { + return;//没有选中某个树节点,就直接返回啦 + } + Object selObject = selPath.getLastPathComponent(); + if (selObject instanceof ExpandMutableTreeNode ) { + ExpandMutableTreeNode expandMutableTreeNode = (ExpandMutableTreeNode) selObject; + if (!expandMutableTreeNode.isLeaf()) { + selectedNode = expandMutableTreeNode; + } else { + selectedNode = (ExpandMutableTreeNode)expandMutableTreeNode.getParent(); + } + } + } + }; + + public void waitRefresh() { + // 换个root,等待用户点击root节点后,展开刷新 + if (waitTreeModel == null) { + ExpandMutableTreeNode rootTreeNode = new ExpandMutableTreeNode(); + rootTreeNode.setExpanded(false); + rootTreeNode.setAllowsChildren(false); + + waitTreeModel = new DefaultTreeModel(rootTreeNode); + } + + this.setModel(waitTreeModel); + } + + public DefaultTreeModel getTreeModel() { + return treeModel; + } + + //防止界面卡死。 + public void refreshData() { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + XMLNodeTree.this.initData(); + } + }); + thread.start(); + } + + //wikky:为满足706设计时对不合法的xml文件(有多个根节点)的处理,把拿到的InputStream强制在最外层添加作为唯一根节点而将文件转换为合法的xml。 + private void initData() { + params = getEditorPaneParameter(); // 生成tree结构放哪儿呢?放这里感觉不对撒 + treeModel = null; + selectedNode = null; + xmlColumnsList.clear(); + DataSource dataSource = null; + if (localFileRadioButton.isSelected()) { + String localTextString = StringUtils.trimToNull(localText.getText()); + if(StringUtils.isEmpty(localTextString)){ + FRContext.getLogger().info("The file path is empty."); + loadedTreeModel(); + return; + } + dataSource = new FileDataSource(localTextString, params); + } else { + String urlTextString = StringUtils.trimToNull(urlText.getText()); + if (StringUtils.isEmpty(urlTextString)){ + FRContext.getLogger().info("The url path is empty."); + loadedTreeModel(); + return; + } + dataSource = new URLDataSource(urlTextString, params); + } + try { + InputStream in,input; + if ((in = dataSource.getSourceStream(params)) != null) { + String xmlString = Utils.inputStream2String(in, (String) encodingComboBox.getSelectedItem()); + String stringXml = addTag(xmlString); + input = new ByteArrayInputStream(stringXml.getBytes((String) encodingComboBox.getSelectedItem())); + InputStreamReader reader = new InputStreamReader(input, (String) encodingComboBox.getSelectedItem()); + XMLableReader xmlReader = XMLableReader.createXMLableReader(reader); + if (xmlReader != null) { + xmlReader.readXMLObject(new XMLLayerReader(0)); + } else { + FRContext.getLogger().info("The file is wrong or bad, can not create the XMLReader."); + loadedTreeModel(); + } + reader.close(); + } + } catch (Throwable e) { + FRContext.getLogger().error(e.getMessage(), e); + loadedTreeModel(); + } + if(treeModel.getChildCount(treeModel.getRoot()) == 1){ + treeModel = new DefaultTreeModel((ExpandMutableTreeNode) treeModel.getChild(treeModel.getRoot(),0)); + }else{ + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + root.setUserObject(StringUtils.EMPTY); + } + this.setModel(treeModel); + } + + private void loadedTreeModel(){ + ExpandMutableTreeNode rootTreeNode = new ExpandMutableTreeNode(Inter.getLocText("FR-Designer_loadedTreeModel")); + rootTreeNode.setExpanded(false); + rootTreeNode.setAllowsChildren(false); + DefaultTreeModel loadedTreeModel = new DefaultTreeModel(rootTreeNode); + XMLNodeTree.this.setModel(loadedTreeModel); + } + + private String addTag(String string){ + String stringWithTag; + int beginIndex = 0; + int firstIndex = string.indexOf(">"); + int endIndex = string.length(); + String firstPart = string.substring(beginIndex,firstIndex + 1); + String secondPart = STARTTAG; + String thirdPart = string.substring(firstIndex + 1,endIndex); + String lastPart = ENDTAG; + stringWithTag = firstPart + secondPart + thirdPart + lastPart; + return stringWithTag; + } + + private class XMLLayerReader implements XMLReadable { + private int layer = -1; + private ExpandMutableTreeNode parentNode; + private ExpandMutableTreeNode currentNode; + + public XMLLayerReader(int layer) { + this.parentNode = null; + this.layer = layer; + } + + public XMLLayerReader(ExpandMutableTreeNode parentNode, int layer) { + this.parentNode = parentNode; + this.layer = layer; + } + + public void readXML(XMLableReader reader) { + String nodeName; + if (this.layer < 0) { + return; + } + if (reader.isAttr()) { + nodeName = reader.getTagName(); + if (nodeName == null) { + return; + } + currentNode = new ExpandMutableTreeNode(nodeName); + if (layer == 0) { + treeModel = new DefaultTreeModel(currentNode); + } else { + boolean conflict = false; + for (int i = 0; i < parentNode.getChildCount(); i++) { + ExpandMutableTreeNode node = (ExpandMutableTreeNode) parentNode.getChildAt(i); + if (node != null && nodeName.equals(node.getUserObject())) { + conflict = true; + currentNode = node; + } + } + if (!conflict) { + parentNode.add(currentNode); + } + } + } + + if (reader.isChildNode()) { + if (currentNode == null) { + return; + } + reader.readXMLObject(new XMLLayerReader(currentNode, layer + 1)); + } + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallHeightPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallHeightPane.java new file mode 100644 index 0000000000..0294edfdb7 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallHeightPane.java @@ -0,0 +1,19 @@ +package com.fr.design.data.tabledata.tabledatapane; + +/** + * Created with IntelliJ IDEA. + * User: wikky + * Date: 14-2-12 + * Time: 下午2:23 + * To change this template use File | Settings | File Templates. + */ +public class FileTableDataSmallHeightPane extends FileTableDataPane{ + //wikky:文件数据集在模板数据集下面的界面参数。 + private static final int SETPANELWIDTH = 265; + private static final int WIDTH = 245; + private static final int HEIGHT = 475; + private static final int GAP = 13; + public FileTableDataSmallHeightPane(){ + super(SETPANELWIDTH,WIDTH,HEIGHT,GAP); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallPane.java new file mode 100644 index 0000000000..d5b14fd562 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FileTableDataSmallPane.java @@ -0,0 +1,19 @@ +package com.fr.design.data.tabledata.tabledatapane; + +/** + * Created with IntelliJ IDEA. + * User: wikky + * Date: 14-1-21 + * Time: 下午12:30 + * To change this template use File | Settings | File Templates. + */ +public class FileTableDataSmallPane extends FileTableDataPane{ + //wikky:文件数据集在服务器数据集下面的界面参数。 + private static final int SETPANELWIDTH = 265; + private static final int WIDTH = 245; + private static final int HEIGHT = 436; + private static final int GAP = 13; + public FileTableDataSmallPane(){ + super(SETPANELWIDTH,WIDTH,HEIGHT,GAP); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FormatExplanationPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FormatExplanationPane.java new file mode 100644 index 0000000000..aaff93c515 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/FormatExplanationPane.java @@ -0,0 +1 @@ +package com.fr.design.data.tabledata.tabledatapane; import com.fr.design.data.datapane.sqlpane.SQLEditPane; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; import com.fr.design.dialog.BasicPane; import java.awt.*; /** * Created with IntelliJ IDEA. * User: Administrator * Date: 13-6-7 * Time: 下午4:31 * To change this template use File | Settings | File Templates. */ public class FormatExplanationPane extends BasicPane { private String title; public FormatExplanationPane(String title, String content, float fontSize) { this.title = title; this.setLayout(new BorderLayout()); SQLEditPane explanation = new SQLEditPane(); explanation.setText(content); explanation.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE); explanation.setEditable(false); explanation.setFont(explanation.getFont().deriveFont(fontSize)); add(new UIScrollPane(explanation)); } protected String title4PopupWindow() { return title; } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalMultiTDTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalMultiTDTableDataPane.java new file mode 100644 index 0000000000..d126c57fdf --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalMultiTDTableDataPane.java @@ -0,0 +1,22 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.design.data.DesignTableDataManager; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-4-20 + * Time: 上午10:10 + * To change this template use File | Settings | File Templates. + */ +public class GlobalMultiTDTableDataPane extends MultiTDTableDataPane { + + public GlobalMultiTDTableDataPane(String string){ + + super(string); + } + protected void setResMap() { + resMap = DesignTableDataManager.getGlobalDataSet(); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalTreeTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalTreeTableDataPane.java new file mode 100644 index 0000000000..8faade23fc --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/GlobalTreeTableDataPane.java @@ -0,0 +1,19 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.design.data.datapane.GlobalTreeTableDataDictPane; + + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-4-20 + * Time: 上午11:30 + * To change this template use File | Settings | File Templates. + */ +public class GlobalTreeTableDataPane extends TreeTableDataPane { + public GlobalTreeTableDataPane(String treeName){ + this.treeTableDataDictPane = new GlobalTreeTableDataDictPane(treeName); + initComponent(); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java new file mode 100644 index 0000000000..75daac2e7b --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/MaxMemRowCountPanel.java @@ -0,0 +1,97 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; + +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.general.Inter; + +public class MaxMemRowCountPanel extends UIToolbar { + private static final int ALL_IN_MEMORY = 0; + private static final int MAX_IN_MEMORY = 1; + + private UISpinner numberSpinner; + private UIComboBox switchCache; + + private boolean showAll; // alex:不知道怎么通过界面判断当前的状态,只好加一个boolean量了 + + private ActionListener switchStateL = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int index = switchCache.getSelectedIndex(); + switch (index) { + case 0: + showAllPanel(); + break; + + case 1: + showMaxPanel(); + break; + + default: + showAllPanel(); + break; + } + } + }; + + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.width = 340; + return dim; + }; + + public MaxMemRowCountPanel() { + this.setFloatable(false); + this.setRollover(true); + this.setBackground(UIConstants.NORMAL_BACKGROUND); + String[] cacheList = { Inter.getLocText("Save_All_Records_In_Memory"), Inter.getLocText("Max-Mem-Row-Count") }; + switchCache = new UIComboBox(cacheList); + switchCache.addActionListener(switchStateL); + numberSpinner = new UISpinner(0, Integer.MAX_VALUE, 1); + } + + private void showAllPanel() { + showAll = true; + this.removeAll(); + this.add(switchCache); + switchCache.setSelectedIndex(ALL_IN_MEMORY); + this.validate(); + this.repaint(); + } + + private void showMaxPanel() { + showAll = false; + this.removeAll(); + this.add(switchCache); + switchCache.setSelectedIndex(MAX_IN_MEMORY); + this.add(new UILabel(" ")); + this.add(numberSpinner); + this.add(new UILabel(" " + Inter.getLocText("Row"))); + this.validate(); + this.repaint(); + } + + public void setValue(int value) { + if (value >= 0) { + showMaxPanel(); + numberSpinner.setValue(Integer.valueOf(value)); + } else { + showAllPanel(); + } + } + + public int getValue() { + if (showAll) { + return -1; + } else { + return ((Number) numberSpinner.getValue()).intValue(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java new file mode 100644 index 0000000000..8fbb7af568 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/MultiTDTableDataPane.java @@ -0,0 +1,405 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.*; +import com.fr.data.impl.ConditionTableData; +import com.fr.data.impl.MultiTDTableData; +import com.fr.data.impl.UnionTableData; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.FormulaFactory; +import com.fr.design.formula.UIFormula; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.script.Calculator; +import com.fr.stable.ParameterProvider; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.Icon; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; + +public class MultiTDTableDataPane extends AbstractTableDataPane { + + private static final int MAX_LENTH_OF_DATASET = 143; //关联数据集面板最大显示的数据集长度,超出这个长度显示数据集名称+“...” + private static final int MIN_BAR_NUMBER = 10; + private static final int SUB_LENGTH = 4; + private JPanel centerPanel; + private UITableEditorPane editorPane; + // key = name ; value = formula + private HashMap choosenTableData = new HashMap(); + protected java.util.Map resMap; + + public MultiTDTableDataPane() { + this(StringUtils.EMPTY); + + } + + public MultiTDTableDataPane(String multiName) { + this.setLayout(new BorderLayout()); + this.add(initNorthPane(multiName), BorderLayout.CENTER); + this.add(initSouthPanel(), BorderLayout.SOUTH); + + } + + private JPanel initNorthPane(String multiName) { + JPanel jpanel = new JPanel(); + jpanel.setLayout(new BorderLayout()); + + JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + UILabel chooseTableData = new UILabel(Inter.getLocText(new String[]{"Select_Data_Set", "Merge"})); + UIButton previewButton = new UIButton(); + previewButton.setIcon(BaseUtils.readIcon("/com/fr/web/images/preview.png")); + previewButton.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + previewButton.addActionListener(getPreviewActionListener()); + northPanel.add(chooseTableData); + northPanel.add(previewButton); + + centerPanel = new JPanel(); + JScrollPane js = new JScrollPane(centerPanel); + js.getVerticalScrollBar().setUnitIncrement(20);// 鼠标滚动大小 + js.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + js.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + initAllBarPane(multiName); + + jpanel.add(northPanel, BorderLayout.NORTH); + jpanel.add(js, BorderLayout.CENTER); + + return jpanel; + } + + private void initAllBarPane(String multiName) { + UILabel headLabel = new UILabel(Inter.getLocText("Multi_nam_formula")); + setResMap(); + int len = resMap.size(); + // 10个正好不会出现滚动条 + centerPanel.setLayout(new GridLayout(len < MIN_BAR_NUMBER ? MIN_BAR_NUMBER : len + 1, 1)); + centerPanel.add(headLabel); + + Iterator> entryIt = resMap.entrySet().iterator(); + while (entryIt.hasNext()) { + TableDataWrapper tableDataWrappe = entryIt.next().getValue(); + String tmp = tableDataWrappe.getTableDataName(); + UILabel uiLabel = new UILabel(tmp); + while (uiLabel.getPreferredSize().width > MAX_LENTH_OF_DATASET) { + tmp = tmp.substring(0, tmp.length() - SUB_LENGTH); + tmp = tmp + "..."; + uiLabel = new UILabel(tmp); + } + if (!ComparatorUtils.equals(tableDataWrappe.getTableDataName(), multiName)) { + centerPanel.add(new BarPanel(tmp, tableDataWrappe.getIcon())); + } + } + + } + + protected void setResMap() { + resMap = DesignTableDataManager.getAllEditingDataSet(DesignTableDataManager.getEditingTableDataSource()); + } + + private ActionListener getPreviewActionListener() { + return new ActionListener() { + + public void actionPerformed(ActionEvent e) { + MultiTDTableData td = MultiTDTableDataPane.this.updateBean(); + td.setTableDataSource(DesignTableDataManager.getEditingTableDataSource()); + new TemplateTableDataWrapper(td).previewData(); + } + }; + } + + private JPanel initSouthPanel() { + JPanel jpanel = new JPanel(); + jpanel.setPreferredSize(new Dimension(-1, 150)); + jpanel.setLayout(new BorderLayout()); + + editorPane = new UITableEditorPane(new ParameterTableModel() { + @Override + public UITableEditAction[] createAction() { + return new UITableEditAction[]{new RefreshAction()}; + } + }, " " + Inter.getLocText(new String[]{"DS-TableData", "DEFAULT", "Parameter"})); + + jpanel.add(editorPane, BorderLayout.CENTER); + + return jpanel; + } + + private class RefreshAction extends UITableEditAction { + public RefreshAction() { + this.setName(Inter.getLocText("Refresh")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + } + + public void actionPerformed(ActionEvent e) { + refresh(); + } + + @Override + public void checkEnabled() { + } + } + + private void refresh() { + int size = choosenTableData.size(); + String[] paramTexts = new String[size]; + Object[] object = choosenTableData.values().toArray(); + for (int i = 0; i < size; i++) { + paramTexts[i] = (String) object[i]; + } + List existParameterList = new ArrayList(); + Iterator> dataItera = choosenTableData.entrySet().iterator(); + List parameterName = new ArrayList(); + while (dataItera.hasNext()) { + Entry entry = dataItera.next(); + TableData td = resMap.get(entry.getKey()).getTableData(); + ParameterProvider[] currentparameters = td.getParameters(Calculator.createCalculator()); + for (int i=0; i> it = choosenTableData.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + td.addTableData(entry.getKey(), entry.getValue()); + } + + List paramList = editorPane.update(); + if (paramList != null) { + td.setDefineParameters(paramList.toArray(new Parameter[paramList.size()])); + } + + return td; + } + + class BarPanel extends JPanel { + + private static final int BAR_HEIGHT = 33; + + private String name; + private Icon icon; + private UICheckBox chekbox; + private UITextField formulaContentTextField; + private UIButton formulaButton; + private DocumentListener documentListener = new DocumentListener() { + + public void changedUpdate(DocumentEvent e) { + updateFormula(formulaContentTextField.getText()); + } + + public void insertUpdate(DocumentEvent e) { + updateFormula(formulaContentTextField.getText()); + } + + public void removeUpdate(DocumentEvent e) { + updateFormula(formulaContentTextField.getText()); + } + }; + + public BarPanel(String name, Icon icon) { + this.name = name; + this.icon = icon; + initUI(); + } + + private void initUI() { + this.setLayout(new FlowLayout(FlowLayout.LEFT)); + + JPanel leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + leftPanel.setPreferredSize(new Dimension(190, BAR_HEIGHT)); + chekbox = new UICheckBox(); + UILabel tabledataName = new UILabel(name); + UILabel iconLabel = new UILabel(icon); + chekbox.addActionListener(tableDataCheckboxListener); + iconLabel.addMouseListener(chooseTableDataListener); + tabledataName.addMouseListener(chooseTableDataListener); + leftPanel.add(chekbox); + leftPanel.add(iconLabel); + leftPanel.add(tabledataName); + + JPanel rightPanel = new JPanel(); + formulaContentTextField = new UITextField(BAR_HEIGHT); + formulaContentTextField.setEnabled(false); + formulaContentTextField.getDocument().addDocumentListener(documentListener); + formulaButton = new UIButton("..."); + formulaButton.setEnabled(false); + formulaButton.setPreferredSize(new Dimension(25, 23)); + formulaButton.addActionListener(getFormulaActionListener()); + rightPanel.add(new UILabel(Inter.getLocText("Conditions_formula") + " =")); + rightPanel.add(formulaContentTextField); + rightPanel.add(formulaButton); + + this.setPreferredSize(new Dimension(-1, BAR_HEIGHT)); + this.add(leftPanel, BorderLayout.WEST); + this.add(rightPanel, BorderLayout.CENTER); + } + + public void populate() { + Iterator> it = choosenTableData.entrySet().iterator(); + chekbox.setSelected(false); + formulaContentTextField.setEnabled(false); + formulaButton.setEnabled(false); + formulaContentTextField.getDocument().removeDocumentListener(documentListener); + formulaContentTextField.setText(""); + while (it.hasNext()) { + Entry entry = it.next(); + if (ComparatorUtils.equals(name, entry.getKey())) { + chekbox.setSelected(true); + formulaContentTextField.setEnabled(true); + formulaButton.setEnabled(true); + formulaContentTextField.setText(entry.getValue()); + } + } + formulaContentTextField.getDocument().addDocumentListener(documentListener); + } + + private MouseAdapter chooseTableDataListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + String formula = formulaContentTextField.getText(); + if (chekbox.isSelected()) { + chekbox.setSelected(false); + formulaContentTextField.setEnabled(false); + formulaButton.setEnabled(false); + if (choosenTableData.containsKey(name)) { + choosenTableData.remove(name); + } + } else { + formulaButton.setEnabled(true); + formulaContentTextField.setEnabled(true); + chekbox.setSelected(true); + choosenTableData.put(name, formula); + } + } + }; + + private ActionListener tableDataCheckboxListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String formula = formulaContentTextField.getText(); + if (chekbox.isSelected()) { + formulaButton.setEnabled(true); + formulaContentTextField.setEnabled(true); + choosenTableData.put(name, formula); + } else { + formulaButton.setEnabled(false); + formulaContentTextField.setEnabled(false); + if (choosenTableData.containsKey(name)) { + choosenTableData.remove(name); + } + } + + } + }; + + private void updateFormula(String newFormula) { + if (!chekbox.isSelected() && StringUtils.isNotEmpty(newFormula)) { + chekbox.setSelected(true); + } + choosenTableData.put(name, newFormula); + } + + private ActionListener getFormulaActionListener() { + return new ActionListener() { + public void actionPerformed(ActionEvent e) { + final UIFormula formulaPane = FormulaFactory.createFormulaPane(); + formulaPane.populate(new Formula(formulaContentTextField.getText())); + formulaPane.showLargeWindow(SwingUtilities.getWindowAncestor(MultiTDTableDataPane.this), new DialogActionAdapter() { + public void doOk() { + Formula formula = formulaPane.update(); + if (formula == null) { + formulaContentTextField.setText(""); + } else { + formulaContentTextField.setText(formula.getContent().substring(1)); + } + MultiTDTableDataPane.this.refresh(); + } + }).setVisible(true); + } + }; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/OneListTableModel.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/OneListTableModel.java new file mode 100644 index 0000000000..952367dcb4 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/OneListTableModel.java @@ -0,0 +1,111 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.Component; +import java.awt.event.ActionEvent; + +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableModelAdapter; +import com.fr.design.mainframe.DesignerContext; +import com.fr.file.FILE; +import com.fr.file.FILEChooserPane; +import com.fr.file.filter.ChooseFileFilter; +import com.fr.general.Inter; +import com.fr.stable.CoreConstants; + +//august:按理说,这个只有一列 就不该用jtable。不过这样总比之前用ArrayTableModel好 +public abstract class OneListTableModel extends UITableModelAdapter { + + protected Component component = null; ////指定确认对话框的父窗口,bug40340 + public OneListTableModel(String columnName) { + this(new String[] { columnName }); + } + + public OneListTableModel(String columnName, Component component) { + this(new String[] { columnName }); + this.component = component; + } + + // 外面的就不要用这个方法了 + protected OneListTableModel(String[] columnNames) { + super(columnNames); + } + @Override + public int getColumnCount() { + return 1; + } + @Override + public UITableEditAction[] createAction() { + return new UITableEditAction[] { getAddAction(),new DeleteAction(), new MoveUpAction(), new MoveDownAction() }; + } + + public abstract UITableEditAction getAddAction(); + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + T os = this.getList().get(rowIndex); + return os; + } + @SuppressWarnings("unchecked") + public void setValueAt(Object value, int row, int column) { + this.getList().set(row, (T) value); + fireTableCellUpdated(row, column); + } + @Override + public boolean isCellEditable(int row, int col) { + return true; + } + + public class AddJsAction extends AddTableRowAction{ + public AddJsAction() { + super(); + } + + @SuppressWarnings("unchecked") + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + FILEChooserPane fileChooser = FILEChooserPane.getInstance(false, false, true, new ChooseFileFilter("js", "javascript" + Inter.getLocText("File"))); + if(fileChooser.showOpenDialog(DesignerContext.getDesignerFrame()) == FILEChooserPane.OK_OPTION) { + final FILE file = fileChooser.getSelectedFILE(); + if(file == null) { + return ; + } + String fileName = file.getName(); + String fileType = fileName.substring(fileName.lastIndexOf(CoreConstants.DOT) + 1); + if(!"js".equalsIgnoreCase(fileType)) { + return ; + } + String temp = file.getPath().substring(1); + addRow((T) temp); + fireTableDataChanged(); + } + } + } + public class AddCssAction extends AddTableRowAction{ + public AddCssAction() { + super(); + } + + @SuppressWarnings("unchecked") + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + FILEChooserPane fileChooser = FILEChooserPane.getInstance(false, false, true, new ChooseFileFilter("css", "css" + Inter.getLocText("File"))); + if(fileChooser.showOpenDialog(DesignerContext.getDesignerFrame()) == FILEChooserPane.OK_OPTION) { + final FILE file = fileChooser.getSelectedFILE(); + if(file == null) { + return ; + } + String fileName = file.getName(); + String fileType = fileName.substring(fileName.lastIndexOf(CoreConstants.DOT) + 1); + if(!"css".equalsIgnoreCase(fileType)) { + return ; + } + String temp = file.getPath().substring(1); + addRow((T) temp); + fireTableDataChanged(); + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java new file mode 100644 index 0000000000..19cb45fcad --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureDataPane.java @@ -0,0 +1,381 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JToolBar; +import javax.swing.SwingWorker; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.StoreProcedureParameter; +import com.fr.data.core.db.TableProcedure; +import com.fr.data.impl.Connection; +import com.fr.data.impl.NameDatabaseConnection; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.actions.UpdateAction; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane; +import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleClickSelectedNodeOnTreeListener; +import com.fr.design.data.datapane.sqlpane.SQLEditPane; +import com.fr.design.data.tabledata.ResponseDataSourceChange; +import com.fr.design.data.tabledata.StoreProcedureWorkerListener; +import com.fr.design.data.tabledata.wrapper.StoreProcedureDataWrapper; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.menu.SeparatorDef; +import com.fr.design.menu.ToolBarDef; +import com.fr.file.DatasourceManager; +import com.fr.general.Inter; +import com.fr.script.Calculator; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; + +public class ProcedureDataPane extends AbstractTableDataPane implements ResponseDataSourceChange { + private static final String[] DRIVERS = { + "oracle.jdbc.driver.OracleDriver", + "com.microsoft.sqlserver.jdbc.SQLServerDriver", + "com.ibm.db2.jcc.DB2Driver", + "com.mysql.jdbc.Driver", + "org.gjt.mm.mysql.Driver" + }; // 需要隐藏面板的数据库的驱动 + private static final String PREVIEW_BUTTON = Inter.getLocText("FR-Designer_Preview"); + private ConnectionTableProcedurePane connectionTableProcedurePane; + private JPanel cardpane; + private CardLayout cardLayout; + private String editorPaneType; + private int paneIndex; + private UITableEditorPane editorPane; + private UITableEditorPane inAutoeditorPane; + private UITableEditorPane autoEditorPane; + private StoreProcedure storeprocedure; + // 存储过程的内容 + private SQLEditPane storeProcedureContext; + // 存储过程的警告提示 + private UILabel warningLabel; + // 存储过程显示的名字 + private UILabel queryText; + private UICheckBox isShareCheckBox; + private MaxMemRowCountPanel maxPanel; + private SwingWorker populateWorker; + private StoreProcedureWorkerListener storeProcedureWorkerListener; + private SwingWorker updateWorker; + + public ProcedureDataPane() { + super(); + queryText = new UILabel(StringUtils.EMPTY); + Box box = new Box(BoxLayout.Y_AXIS); + JPanel northpane = new JPanel(new BorderLayout(4, 4)); + northpane.add(creatToolBar(), BorderLayout.CENTER); + northpane.setBorder(BorderFactory.createEmptyBorder(0, 0, 6, 0)); + + storeProcedureContext = new SQLEditPane(SQLEditPane.UNREQUEST_DROPTARGET); + storeProcedureContext.setEditable(false); + UIScrollPane storeProcedureContextPane = new UIScrollPane(storeProcedureContext); + storeProcedureContextPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + storeProcedureContextPane.setPreferredSize(new Dimension(680, 600)); + + JPanel namePane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + namePane.add(new UILabel(Inter.getLocText("FR-Designer_Datasource-Stored_Procedure") + ":")); + namePane.add(queryText); + inAutoeditorPane = new UITableEditorPane(new StoreProcedureTableModel()); + autoEditorPane = new UITableEditorPane(new AutoStoreProcedureTableModel()); + autoEditorPane.getbuttonPane().setVisible(false); + + cardLayout = new CardLayout(); + cardpane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardpane.setLayout(this.cardLayout); + cardpane.add(inAutoeditorPane, "inAutoeditorPane"); + cardpane.add(autoEditorPane, "autoEditorPane"); + + box.add(northpane); + box.add(storeProcedureContextPane); + box.add(namePane); + box.add(cardpane); + warningLabel = new UILabel(""); + JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4)); + sqlSplitPane.add(box, BorderLayout.CENTER); + + // 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table + initconnectionTableProcedurePane(); + this.setLayout(new BorderLayout(4, 4)); + this.add(connectionTableProcedurePane, BorderLayout.WEST); + this.add(sqlSplitPane, BorderLayout.CENTER); + } + + private void initconnectionTableProcedurePane() { + connectionTableProcedurePane = new ConnectionTableProcedurePane() { + @Override + protected JPanel createCheckBoxgroupPane() { + return null; + } + }; + connectionTableProcedurePane.addDoubleClickListener(new DoubleClickSelectedNodeOnTreeListener() { + + @Override + public void actionPerformed(TableProcedure target) { + editorPane.stopEditing(); + queryText.setText(target.toString()); + refresh(); + } + + }); + connectionTableProcedurePane.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + editorPaneType = isAutoParameterDatabase() ? "autoEditorPane" : "inAutoeditorPane"; + paneIndex = isAutoParameterDatabase() ? 1 : 0; + editorPane = (UITableEditorPane) cardpane.getComponent(paneIndex); + cardLayout.show(cardpane, editorPaneType); + } + }); + + } + + private JToolBar creatToolBar() { + ToolBarDef toolBarDef = new ToolBarDef(); + toolBarDef.addShortCut(new PreviewAction()); + toolBarDef.addShortCut(new RefreshAction()); + toolBarDef.addShortCut(SeparatorDef.DEFAULT); + isShareCheckBox = new UICheckBox(Inter.getLocText("FR-Designer_Is_Share_DBTableData")); + maxPanel = new MaxMemRowCountPanel(); + maxPanel.setBorder(null); + UIToolbar toolbar = ToolBarDef.createJToolBar(); + toolBarDef.updateToolBar(toolbar); + toolbar.add(isShareCheckBox); + toolbar.add(maxPanel); + return toolbar; + } + + private boolean isAutoParameterDatabase() { + Connection connection = DatasourceManager.getProviderInstance().getConnection(connectionTableProcedurePane.getSelectedDatabaseConnnectonName()); + return connection == null ? false : ArrayUtils.contains(DRIVERS, connection.getDriver()); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Datasource-Stored_Procedure"); + } + + @Override + public void populateBean(StoreProcedure e) { + storeprocedure = e; + this.queryText.setText(e.getQuery()); + this.connectionTableProcedurePane.setSelectedDatabaseConnection(e.getDatabaseConnection()); + isShareCheckBox.setSelected(e.isShare()); + maxPanel.setValue(e.getMaxMemRowCount()); + + // refresh storeProcedureContext + if (populateWorker != null) { + populateWorker.cancel(true); + } + populateWorker = new SwingWorker() { + + protected Void doInBackground() throws Exception { + try { + storeProcedureContext.setText(StringUtils.EMPTY); + String connectionname = connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); + String procedureText = FRContext.getCurrentEnv().getProcedureText(connectionname, storeprocedure.getQuery()); + storeProcedureContext.setText(procedureText); + warningLabel.setText(StringUtils.EMPTY); + } catch (Exception ex) { + if (ex instanceof SQLException) { + warningLabel.setText(Inter.getLocText(new String[]{"Database", "Datasource-Connection_failed"})); + } else { + warningLabel.setText(ex.getMessage()); + } + } + return null; + } + + public void done() { + editorPane.populate(storeprocedure.getParameters()); + } + }; + + populateWorker.execute(); + + } + + /** + * 增加存储过程监听器 + * + * @param listener 监听器 + */ + public void addStoreProcedureWorkerListener(StoreProcedureWorkerListener listener) { + + this.storeProcedureWorkerListener = listener; + + } + + /** + * 去除存储过程监听器 + */ + public void removeStoreProcedureWorkerListener() { + this.storeProcedureWorkerListener = null; + + } + + private StoreProcedure updateBeanWithOutExecute() { + String dbName = connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); + + if (StringUtils.isBlank(dbName)) { + try { + throw new Exception(Inter.getLocText("FR-Designer_Connect_SQL_Cannot_Null") + "."); + } catch (Exception e) { + JOptionPane.showMessageDialog(ProcedureDataPane.this, Inter.getLocText("FR-Designer_Connect_SQL_Cannot_Null") + "."); + } + } + + StoreProcedure sp = new StoreProcedure(); + sp.setDatabaseConnection(new NameDatabaseConnection(dbName)); + List parametersList = editorPane.update(); + sp.setParameters(parametersList.toArray(new StoreProcedureParameter[parametersList.size()])); + + sp.setQuery(this.queryText.getText()); + sp.setShare(isShareCheckBox.isSelected()); + sp.setMaxMemRowCount(maxPanel.getValue()); + + return sp; + } + + @Override + public StoreProcedure updateBean() { + + final StoreProcedure sp = updateBeanWithOutExecute(); + if (updateWorker != null) { + updateWorker.cancel(true); + } + updateWorker = new SwingWorker() { + + protected Void doInBackground() throws Exception { + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + sp.setCalculating(true); + sp.creatDataModel(Calculator.createCalculator()); + return null; + } + + public void done() { + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + sp.setCalculating(false); + doAfterProcudureDone(); + fireDSChanged(); + } + }; + + updateWorker.execute(); + return sp; + } + + private void doAfterProcudureDone() { + if (storeProcedureWorkerListener != null) { + storeProcedureWorkerListener.fireDoneAction(); + } + } + + // 刷新参数,从数据库取值 + private void refresh() { + String text = this.queryText.getText(); + if (text == null) { + text = StringUtils.EMPTY; + } + text = text.trim(); + String[] tableName = text.split("\\."); + String connectionname = this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName(); + try { + String procedureText = FRContext.getCurrentEnv().getProcedureText(this.connectionTableProcedurePane.getSelectedDatabaseConnnectonName(), text); + + // 获取参数默认值,例如:NAME in varchar2 default 'SCOTT',默认值为SCOTT + String parameterDefaultValue = ""; + if (StringUtils.isNotEmpty(procedureText)) { + int index_begin = procedureText.indexOf("BEGIN"); + + //from sam: 默认值只会在begin之前声明, 不然会把所有的存储过程里带'xx'的都作为默认值 + String defaulValueStr = index_begin == -1 ? procedureText : procedureText.substring(0, index_begin); + String[] strs = defaulValueStr.split("\'"); + parameterDefaultValue = strs.length > 1 ? strs[1] : parameterDefaultValue; + } + + StoreProcedureParameter[] newparameters; + newparameters = FRContext.getCurrentEnv().getStoreProcedureDeclarationParameters(connectionname, tableName[tableName.length - 1], parameterDefaultValue); + + + editorPane.populate(newparameters); + storeProcedureContext.setText(procedureText); + warningLabel.setText(""); + } catch (SQLException sql) { + warningLabel.setText(Inter.getLocText(new String[]{"Database", "Datasource-Connection_failed"})); + storeProcedureContext.setText(""); + editorPane.populate(new StoreProcedureParameter[0]); + } catch (Exception e) { + warningLabel.setText(e.getMessage()); + storeProcedureContext.setText(""); + editorPane.populate(new StoreProcedureParameter[0]); + } + return; + } + + /** + * 响应数据集改变 + */ + public void fireDSChanged() { + fireDSChanged(new HashMap()); + } + + /** + * 响应数据集改变 + * + * @param map 改变的map + */ + public void fireDSChanged(Map map) { + DesignTableDataManager.fireDSChanged(map); + } + + private class PreviewAction extends UpdateAction { + public PreviewAction() { + this.setName(PREVIEW_BUTTON); + this.setMnemonic('P'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + } + + public void actionPerformed(ActionEvent evt) { + StoreProcedure sp = updateBeanWithOutExecute(); + StoreProcedureDataWrapper storeProcedureDataWrappe = new StoreProcedureDataWrapper(sp, StringUtils.EMPTY, queryText.getText()); + storeProcedureDataWrappe.previewData(StoreProcedureDataWrapper.PREVIEW_ALL); + } + } + + protected class RefreshAction extends UITableEditAction { + public RefreshAction() { + this.setName(Inter.getLocText("FR-Designer_Refresh")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png")); + } + + public void actionPerformed(ActionEvent e) { + refresh(); + } + + @Override + public void checkEnabled() { + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureListPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureListPane.java new file mode 100644 index 0000000000..5f56516280 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureListPane.java @@ -0,0 +1,148 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.data.TableDataSource; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.gui.controlpane.JControlPane; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.general.NameObject; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; +import com.fr.stable.core.PropertyChangeAdapter; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ProcedureListPane extends JControlPane { + public ProcedureListPane() { + super(); + this.addEditingListner(new PropertyChangeAdapter() { + @Override + public void propertyChange() { + TableDataSource source = DesignTableDataManager.getEditingTableDataSource(); + if (source == null) { + return; + } + String[] allDSNames = DesignTableDataManager.getAllDSNames(source); + String tempName = getEditingName(); + if(StringUtils.isEmpty(tempName)) { + nameableList.stopEditing(); + //JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ProcedureListPane.this), Inter.getLocText("NOT_NULL_Des") + "," + Inter.getLocText("Please_Rename") + "!"); + setWarnigText(nameableList.getSelectedIndex()); + return; + } + for(int i = 0; i < allDSNames.length; i++) { + String dsname = allDSNames[i]; + if (ComparatorUtils.equals(dsname, tempName)) { +// JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(ProcedureListPane.this), Inter.getLocText(new String[]{"already_exists", "TableData"}) +// + tempName + "," + Inter.getLocText("Please_Rename") + "!"); + setWarnigText(nameableList.getSelectedIndex()); + break; + } + } + } + }); + } + + /** + * 创建不重复的名称 + * + * @param prefix 前缀 + * + * @return 不重复的名称 + */ + public String createUnrepeatedName(String prefix) { + TableDataSource source = DesignTableDataManager.getEditingTableDataSource(); + if (source == null) { + return super.createUnrepeatedName(prefix); + } + String[] allDsNames = DesignTableDataManager.getAllDSNames(source); + DefaultListModel model = this.getModel(); + Nameable[] all = new Nameable[model.getSize()]; + for (int i = 0; i < model.size(); i++) { + all[i] = ((ListModelElement) model.get(i)).wrapper; + } + // richer:生成的名字从1开始. kunsnat: 添加属性从0开始. + int count = all.length + 1; + while (true) { + String name_test = prefix + count; + boolean repeated = false; + for (int i = 0, len = model.size(); i < len; i++) { + Nameable nameable = all[i]; + if (ComparatorUtils.equals(nameable.getName(), name_test)) { + repeated = true; + break; + } + } + for (String dsname : allDsNames) { + if (ComparatorUtils.equals(dsname, name_test)) { + repeated = true; + break; + } + } + + if (!repeated) { + return name_test; + } + + count++; + } + } + + /** + * 创建对象组件 + * + * @return 面板组件 + */ + public NameableCreator[] createNameableCreators() { + return new NameableCreator[] { new NameObjectCreator("Proc", "/com/fr/design/images/data/store_procedure.png", StoreProcedure.class, + ProcedureDataPane.class) }; + } + + @Override + protected String title4PopupWindow() { + return "procedure"; + } + + /** + * Populate. + * + * @param datasourceManager + * the new datasourceManager. + */ + public void populate(DatasourceManagerProvider datasourceManager) { + Iterator nameIt = datasourceManager.getProcedureNameIterator(); + + List nameObjectList = new ArrayList(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + nameObjectList.add(new NameObject(name, datasourceManager.getProcedure(name))); + } + this.populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); + + } + + /** + * Update. + */ + public void update(DatasourceManagerProvider datasourceManager) { + // Nameable[]居然不能强转成NameObject[],一定要这么写... + Nameable[] res = this.update(); + NameObject[] res_array = new NameObject[res.length]; + java.util.Arrays.asList(res).toArray(res_array); + + datasourceManager.clearAllProcedure(); + + for (int i = 0; i < res_array.length; i++) { + NameObject nameObject = res_array[i]; + datasourceManager.putProcedure(nameObject.getName(), (StoreProcedure) nameObject.getObject()); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureManagerPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureManagerPane.java new file mode 100644 index 0000000000..7274117b51 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/ProcedureManagerPane.java @@ -0,0 +1,51 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.FRContext; +import com.fr.design.gui.frpane.LoadingBasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import java.awt.*; +import java.io.File; + +public class ProcedureManagerPane extends LoadingBasicPane { + private UITextField connectionTextField; + private ProcedureListPane procedureListPane; + + protected void initComponents(JPanel container) { + container.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel connectionPathPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + container.add(connectionPathPane, BorderLayout.NORTH); + + connectionPathPane.setBorder(BorderFactory.createEmptyBorder(6, 2, 2, 2)); + + connectionPathPane.add(new UILabel(Inter.getLocText("FR-Designer_Save_Path") + ":"), BorderLayout.WEST); + this.connectionTextField = new UITextField(); + connectionPathPane.add(connectionTextField, BorderLayout.CENTER); + this.connectionTextField.setEditable(false); + procedureListPane = new ProcedureListPane(); + container.add(procedureListPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Datasource-Stored_Procedure"); + } + + public void populate(DatasourceManagerProvider datasourceManager) { + this.connectionTextField.setText(FRContext.getCurrentEnv().getPath() + File.separator + ProjectConstants.RESOURCES_NAME + + File.separator + datasourceManager.fileName()); + this.procedureListPane.populate(datasourceManager); + } + + public void update(DatasourceManagerProvider datasourceManager) { + this.procedureListPane.update(datasourceManager); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureParameterPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureParameterPane.java new file mode 100644 index 0000000000..148ff16f95 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureParameterPane.java @@ -0,0 +1,178 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.Date; +import java.util.HashMap; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.base.Formula; +import com.fr.general.NameObject; +import com.fr.base.StoreProcedureParameter; +import com.fr.data.impl.storeproc.StoreProcedureConstants; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.editor.editor.CursorEditor; +import com.fr.general.Inter; + + +public class StoreProcedureParameterPane extends BasicPane { + + private static String[] schemaName = new String[]{ + "IN", "OUT", "INOUT" + }; + + private static NameObject[] nameAndValue = new NameObject[]{ + new NameObject(Inter.getLocText("Cursor"), StoreProcedureConstants.CURSOR), + new NameObject(Inter.getLocText("Parameter-String"), StoreProcedureConstants.VARCHAR), + new NameObject(Inter.getLocText("Integer"), StoreProcedureConstants.INTEGER), + new NameObject(Inter.getLocText("Double"), StoreProcedureConstants.DECIMAL), + new NameObject(Inter.getLocText("Date"), StoreProcedureConstants.DATE), + new NameObject(Inter.getLocText("Parameter-Boolean"), StoreProcedureConstants.BOOLEAN), + new NameObject(Inter.getLocText("Formula"), StoreProcedureConstants.FORMULA), + new NameObject("IN",StoreProcedureConstants.IN), + new NameObject("OUT",StoreProcedureConstants.OUT), + new NameObject("INOUT",StoreProcedureConstants.INOUT) + }; + + private static HashMap infoMap = new HashMap(); + static { + for(int i = 0; i < nameAndValue.length; i ++){ + infoMap.put(nameAndValue[i].getName(), (Integer) nameAndValue[i].getObject()); + } + } + + private UITextField nameField; + private UIComboBox schemaCombo; + private ValueEditorPane valueEditPane; + private JPanel valuePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + public StoreProcedureParameterPane(){ + valueEditPane = ValueEditorPaneFactory.createStoreProcedValueEditorPane(); + this.initComponents(); + } + + public void checkValid() throws Exception{ + StoreProcedureParameter spp=this.update(); + if(spp.getSchema()!= StoreProcedureConstants.OUT && spp.getType() == StoreProcedureConstants.CURSOR){ + throw new Exception(Inter.getLocText("IN_and_INOUT_type_not_as_cursor")); + } + } + + private void initComponents(){ + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + schemaCombo = new UIComboBox(); + initUIComboBox(schemaCombo, schemaName); + JPanel namePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + namePane.add(new UILabel(" " + Inter.getLocText("Name") + ":"), BorderLayout.WEST); + nameField = new UITextField(10); + namePane.add(nameField, BorderLayout.CENTER); + namePane.add(new UILabel(" "), BorderLayout.EAST); + valuePane.add(new UILabel(" " + Inter.getLocText("CellWrite-InsertRow_DEFAULT") + ":"), BorderLayout.WEST); + valuePane.add(valueEditPane, BorderLayout.CENTER); + valuePane.add(new UILabel(" "), BorderLayout.EAST); + Component[][] components = {{null}, + {namePane}, + {addPane("Model", 1, schemaCombo)}, + {valuePane}, + {null} + }; + double p = TableLayout.PREFERRED; + double[] rowSize = {p, p, p, p, p, p}; + double[] columnSize = {p}; + JPanel centerPane = TableLayoutHelper.createGapTableLayoutPane( + components, rowSize, columnSize, 20, 10); + this.add(centerPane, BorderLayout.CENTER); + + } + + private JPanel addPane(String s, int i, UIComboBox combo){ + JPanel pane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + pane.add(new UILabel(" " + Inter.getLocText(s) + ":"), BorderLayout.WEST); + combo.setSelectedIndex(i); + pane.add(combo, BorderLayout.CENTER); + pane.add(new UILabel(" "), BorderLayout.EAST); + + return pane; + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Parameter"); + } + + public void populate(StoreProcedureParameter stpParameter) { + if(stpParameter == null) + return; + this.nameField.setText(stpParameter.getName()); + String schema = getInfo4Name(stpParameter.getSchema()); + this.schemaCombo.setSelectedItem(schema); + this.valueEditPane.populate(stpParameter.getValue()); + + } + + public StoreProcedureParameter update(){ + StoreProcedureParameter p = new StoreProcedureParameter(); + p.setName(nameField.getText()); + Object value = valueEditPane.update(); + String type = ""; + if(value instanceof CursorEditor) + type=Inter.getLocText("Cursor"); + else if(value instanceof String ){ + if(((String) value).length() > 0 && ((String) value).charAt(0) == '=') + type = Inter.getLocText("Formula"); + else + type = Inter.getLocText("Parameter-String"); + }else if(value instanceof Integer) + type = Inter.getLocText("Integer"); + else if(value instanceof Double) + type = Inter.getLocText("Double"); + else if(value instanceof Date) + type = Inter.getLocText("Date"); + else if(value instanceof Boolean) + type = Inter.getLocText("Parameter-Boolean"); + else if(value instanceof Formula) + type = Inter.getLocText("Formula"); + else + type = Inter.getLocText("Parameter-String"); + int typeVl = getInfo4Value(type); + p.setType(typeVl); + String schema = (String)schemaCombo.getSelectedItem(); + int schemaVl = getInfo4Value(schema); + p.setSchema(schemaVl); + p.setValue(value); + + return p; + } + + private void initUIComboBox(UIComboBox combo, String[] p){ + for(int i = 0; i < p.length; i ++) + combo.addItem(p[i]); + } + + public static int getInfo4Value(String name){ + return infoMap.get(name); + } + + public static String getInfo4Name(int value){ + java.util.Set set = infoMap.keySet(); + for(String s : set){ + if(infoMap.get(s) == value) + return s; + } + return null; + } + /** + * + */ + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureTableModel.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureTableModel.java new file mode 100644 index 0000000000..2505bf6519 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/StoreProcedureTableModel.java @@ -0,0 +1,139 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; + +import javax.swing.BorderFactory; + +import com.fr.base.StoreProcedureParameter; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableModelAdapter; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.general.Inter; + +public class StoreProcedureTableModel extends UITableModelAdapter { + + public StoreProcedureTableModel() { + super(new String[] { Inter.getLocText("Parameter"), Inter.getLocText("Type"), Inter.getLocText("Model"), Inter.getLocText("Value") }); + if (shouldResponseDoubleClickAction()) { + table.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() < 2) { + return; + } + final int selectedRow = table.getSelectedRow(); + final List sppList = getList(); + if (selectedRow < 0 || selectedRow >= sppList.size()) { + return; + } + StoreProcedureParameter spp = sppList.get(selectedRow); + + final StoreProcedureParameterPane pane = new StoreProcedureParameterPane(); + pane.populate(spp); + pane.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("Parameter"))); + BasicDialog stpEditDialog = pane.showWindow(DesignerContext.getDesignerFrame()); + stpEditDialog.addDialogActionListener(new DialogActionAdapter() { + + @Override + public void doOk() { + StoreProcedureParameter spp = pane.update(); + setSelectedValue(spp); + fireTableDataChanged(); + } + }); + stpEditDialog.setVisible(true); + } + }); + } + + } + + public Object getValueAt(int row, int col) { + StoreProcedureParameter stp = getList().get(row); + + if (col == 0) { + return stp.getName(); + } else if (col == 1) { + return StoreProcedureParameterPane.getInfo4Name(stp.getType()); + } else if (col == 2) { + return StoreProcedureParameterPane.getInfo4Name(stp.getSchema()); + } else if (col == 3) { + return stp.getValue(); + } + + return null; + } + + public boolean isCellEditable(int row, int col) { + return false; + } + + public boolean shouldResponseDoubleClickAction () { + return true; + } + @Override + public UITableEditAction[] createAction() { + return new UITableEditAction[] { new AddStoreProcedureAction(), new EditStoreProcedureAction(), new DeleteAction(), new MoveUpAction(), + new MoveDownAction() }; + } + + private class AddStoreProcedureAction extends AddTableRowAction { + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + StoreProcedureParameter para = new StoreProcedureParameter(); + final StoreProcedureParameterPane pane = new StoreProcedureParameterPane(); + pane.populate(para); + pane.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("Parameter"))); + BasicDialog stpEditDialog = pane.showWindow(DesignerContext.getDesignerFrame()); + stpEditDialog.addDialogActionListener(new DialogActionAdapter() { + + @Override + public void doOk() { + StoreProcedureParameter spp = pane.update(); + addRow(spp); + fireTableDataChanged(); + } + }); + stpEditDialog.setVisible(true); + } + } + + private class EditStoreProcedureAction extends EditAction { + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + StoreProcedureParameter para = getSelectedValue(); + final StoreProcedureParameterPane pane = new StoreProcedureParameterPane(); + pane.populate(para); + pane.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("Parameter"))); + BasicDialog stpEditDialog = pane.showWindow(DesignerContext.getDesignerFrame()); + stpEditDialog.addDialogActionListener(new DialogActionAdapter() { + + @Override + public void doOk() { + StoreProcedureParameter spp = pane.update(); + setSelectedValue(spp); + fireTableDataChanged(); + } + }); + stpEditDialog.setVisible(true); + } + + @Override + public void checkEnabled() { + if (table.getSelectedRow() < 0) { + this.setEnabled(false); + } else { + this.setEnabled(true); + } + } + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/TableDataManagerPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/TableDataManagerPane.java new file mode 100644 index 0000000000..55f975e385 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/TableDataManagerPane.java @@ -0,0 +1,92 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.base.FRContext; +import com.fr.design.data.datapane.TableDataListPane; +import com.fr.design.gui.frpane.LoadingBasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.Inter; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.util.Map; + +public class TableDataManagerPane extends LoadingBasicPane { + + private UITextField tableDataTextField; + private TableDataListPane tableDataListPane; + + @Override + protected void initComponents(JPanel container) { + this.initTableDataManagerPane(container); + } + + private void initTableDataManagerPane(JPanel container) { + container.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel tableDataPathPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + container.add(tableDataPathPane, BorderLayout.NORTH); + + + tableDataPathPane.add(new UILabel(Inter.getLocText("FR-Designer_Save_Path") + ":"), BorderLayout.WEST); + this.tableDataTextField = new UITextField(); + tableDataPathPane.add(tableDataTextField, BorderLayout.CENTER); + this.tableDataTextField.setEditable(false); + tableDataListPane = new TableDataListPane(){ + protected void rename(String oldName,String newName){ + super.rename(oldName,newName); + renameConnection(oldName, newName); + } + }; + container.add(tableDataListPane, BorderLayout.CENTER); + } + + + /** + * 名字是否允许 + * @return 是则返回true + */ + public boolean isNamePermitted(){ + return tableDataListPane.isNamePermitted(); + } + + /** + * 检查 + * @throws Exception 异常 + */ + public void checkValid() throws Exception { + tableDataListPane.checkValid(); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("DS-Server_TableData"); + } + + public void populate(DatasourceManagerProvider datasourceManager) { + this.tableDataTextField.setText(FRContext.getCurrentEnv().getPath() + File.separator + ProjectConstants.RESOURCES_NAME + + File.separator + datasourceManager.fileName()); + this.tableDataListPane.populate(datasourceManager); + } + + public void update(DatasourceManagerProvider datasourceManager) { + this.tableDataListPane.update(datasourceManager); + } + + public Map getDsChangedNameMap () { + return this.tableDataListPane.getDsNameChangedMap(); + } + + /** + * 设置选中项 + * + * @param index 选中项的序列号 + */ + public void setSelectedIndex(int index) { + this.tableDataListPane.setSelectedIndex(index); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/tabledatapane/TreeTableDataPane.java b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/TreeTableDataPane.java new file mode 100644 index 0000000000..a09d2f92ec --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/tabledatapane/TreeTableDataPane.java @@ -0,0 +1,45 @@ +package com.fr.design.data.tabledata.tabledatapane; + +import com.fr.design.data.datapane.TreeTableDataDictPane; +import com.fr.data.impl.RecursionTableData; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; + +import java.awt.*; + +public class TreeTableDataPane extends AbstractTableDataPane{ + + protected TreeTableDataDictPane treeTableDataDictPane; + + public TreeTableDataPane() { + this.treeTableDataDictPane = new TreeTableDataDictPane(); + initComponent(); + } + + public TreeTableDataPane(String treeName) { + this.treeTableDataDictPane = new TreeTableDataDictPane(treeName); + initComponent(); + } + + protected void initComponent() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(treeTableDataDictPane, BorderLayout.CENTER); + } + + @Override + public void populateBean(RecursionTableData ob) { + treeTableDataDictPane.populate(ob); + } + + @Override + public RecursionTableData updateBean() { + // TODO Auto-generated method stub + return treeTableDataDictPane.update(); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText(new String[]{"Tree", "DS-TableData"}); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/AbstractTableDataWrapper.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/AbstractTableDataWrapper.java new file mode 100644 index 0000000000..90e2adfab7 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/AbstractTableDataWrapper.java @@ -0,0 +1,138 @@ +package com.fr.design.data.tabledata.wrapper; + +import com.fr.base.TableData; +import com.fr.data.TableDataSource; +import com.fr.data.impl.EmbeddedTableData; +import com.fr.design.DesignModelAdapter; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.utils.DesignUtils; +import com.fr.general.ComparatorUtils; +import com.fr.stable.ArrayUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public abstract class AbstractTableDataWrapper implements TableDataWrapper { + protected TableData tabledata; + private String name; + private List columnNameList; + public AbstractTableDataWrapper(TableData tabledata) { + this(tabledata,null); + } + + public AbstractTableDataWrapper(TableData tabledata,String name) { + this.tabledata = tabledata; + this.name = name; + } + + public TableData getTableData() { + return tabledata; + } + + /** + * 获取数据集的所有列名list + * + * @return 数据集的所有列名list + * + * + * @date 2014-11-24-下午3:51:41 + * + */ + public List calculateColumnNameList() { + if(columnNameList != null){ + return columnNameList; + } + + DesignModelAdapter adapter = DesignModelAdapter.getCurrentModelAdapter(); + TableDataSource tds = adapter == null ? null : adapter.getBook(); + String[] colNames = tabledata.getColumnNames(tds); + if(ArrayUtils.isNotEmpty(colNames)){ + columnNameList = new ArrayList(); + columnNameList.addAll(Arrays.asList(colNames)); + return columnNameList; + } + + EmbeddedTableData embeddedTableData = null; + try { + embeddedTableData = DesignTableDataManager.previewTableDataNotNeedInputParameters(tabledata, TableData.RESULT_NOT_NEED, false); + } catch (Exception e) { + if (e.getMessage()!=null) { + DesignUtils.errorMessage(e.getMessage()); + } + } + columnNameList = DesignTableDataManager.getColumnNamesByTableData(embeddedTableData); + return columnNameList; + } + + /** + * 生成子节点 + * + * @return 生成子节点 + * + * + * @date 2014-11-24-下午3:51:17 + * + */ + public ExpandMutableTreeNode[] load() { + List namelist = calculateColumnNameList(); + ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[namelist.size()]; + for (int i = 0; i < res.length; i++) { + res[i] = new ExpandMutableTreeNode(namelist.get(i)); + } + + return res; + } + + /** + * 预览数据集 + * + * + * @date 2014-11-24-下午3:50:20 + * + */ + public void previewData() { + PreviewTablePane.previewTableData(tabledata); + } + + /** + * 预览数据集,带有显示值和实际值的标记结果 + * + * @param keyIndex 实际值 + * @param valueIndex 显示值 + * + * + * @date 2014-11-24-下午3:50:20 + * + */ + public void previewData(final int keyIndex,final int valueIndex){ + PreviewTablePane.previewTableData(tabledata, keyIndex, valueIndex); + } + @Override + public String getTableDataName(){ + return name; + } + + /** + * 获取数据集的面板 + * + * @return 数据集面板 + * + * + * @date 2014-11-24-下午3:50:00 + * + */ + public AbstractTableDataPane creatTableDataPane() { + return TableDataFactory.creatTableDataPane(tabledata, name); + } + + public boolean equals (Object obj) { + return obj instanceof AbstractTableDataWrapper + && ComparatorUtils.equals(this.name, ((AbstractTableDataWrapper) obj).getTableDataName()) + && ComparatorUtils.equals(this.tabledata, ((AbstractTableDataWrapper) obj).getTableData()); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/ServerTableDataWrapper.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/ServerTableDataWrapper.java new file mode 100644 index 0000000000..22b7e0950f --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/ServerTableDataWrapper.java @@ -0,0 +1,57 @@ +package com.fr.design.data.tabledata.wrapper; + +import com.fr.base.BaseUtils; +import com.fr.base.TableData; +import com.fr.data.impl.ClassTableData; +import com.fr.data.impl.DBTableData; +import com.fr.data.impl.EmbeddedTableData; +import com.fr.data.impl.RecursionTableData; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.icon.WarningIcon; +import com.fr.stable.StringUtils; + +import javax.swing.*; + +public final class ServerTableDataWrapper extends AbstractTableDataWrapper { + public ServerTableDataWrapper(TableData tabledata) { + super(tabledata); + } + + public ServerTableDataWrapper(TableData tabledata, String name) { + super(tabledata, name); + } + + @Override + public Icon getIcon() { + if (tabledata instanceof DBTableData) { + if (StringUtils.isBlank(((DBTableData) tabledata).getQuery())) + return new WarningIcon(BaseUtils.readImage("/com/fr/design/images/data/dock/serverdatabase.png")); + else + return BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png"); + } else if (tabledata instanceof ClassTableData) { + return BaseUtils.readIcon("/com/fr/design/images/data/dock/serverclasstabledata.png"); + } else if (tabledata instanceof EmbeddedTableData) { + return BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatatable.png"); + }else if(tabledata instanceof RecursionTableData){ + return BaseUtils.readIcon("/com/fr/design/images/data/tree.png"); + } else if (tabledata instanceof StoreProcedure) { + return BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png"); + } + return BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png"); + } + + /** + * 是否异常 + * @return + */ + @Override + public boolean isUnusual() { + //目前只判断DBTableData的异常 + if (tabledata instanceof DBTableData && StringUtils.isBlank(((DBTableData) tabledata).getQuery())) { + return true; + } + return false; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java new file mode 100644 index 0000000000..d2ca99bb76 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureDataWrapper.java @@ -0,0 +1,311 @@ +package com.fr.design.data.tabledata.wrapper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CancellationException; + +import javax.swing.Icon; +import javax.swing.JOptionPane; +import javax.swing.SwingWorker; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.TableData; +import com.fr.data.impl.storeproc.ProcedureDataModel; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.iprogressbar.AutoProgressBar; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +/** + * StoreProcedureDataWrappe :存储过程的一个返回数据集,不是它本身。
+ * Oracle数据库肯定有它。SQL SERVER就不一定有了,大部分情况下都没有. + *

+ * StoreProcedureNameWrappe :存储过程本身的返回数据集,是它本身。
+ * Oracle数据库有它,但其实没必要,它就是Oracle所有返回数据集的第一个。SQL SERVER肯定有这个东西。 + * StoreProcedureNameWrappe + * 实际就是:以前我们在新建数据集时,从左边的列表中拖动一个存储过程到右边的SQL面板, + * 得到的SQL语句执行后返回的数据集。又因为结果可能得到多个数据集,所以默认用第一个 + * + * @author zhou + * @since 2012-4-12上午10:29:15 + */ +public final class StoreProcedureDataWrapper implements TableDataWrapper { + public static final int PREVIEW_ALL = 0; + public static final int PREVIEW_ONE = 1; + public static AutoProgressBar loadingBar; + + private ProcedureDataModel procedureDataModel; + private String dsName; + private String storeprocedureName; + private StoreProcedure storeProcedure; + private List columnNameList; + private AutoProgressBar connectionBar; + private ProcedureDataModel[] dataModels; + private SwingWorker worker; + private BasicDialog dialog; + private int previewModel; + + public StoreProcedureDataWrapper(StoreProcedure storeProcedure, String storeprocedureName, String dsName) { + this(storeProcedure, storeprocedureName, dsName, true); + } + + + /** + * @param dsName 存储过程一个返回数据集的名字 + * @param storeProcedure 存储过程 + * @param storeprocedureName 存储过程的名字(某些情况下可以为空) + */ + public StoreProcedureDataWrapper(StoreProcedure storeProcedure, String storeprocedureName, String dsName, boolean needLoad) { + this.dsName = dsName; + this.storeProcedure = storeProcedure; + this.storeProcedure.setCalculating(false); + this.storeprocedureName = storeprocedureName; + if (needLoad) { + setWorker(); + } + dialog = PreviewTablePane.getInstance().getDialog(); + dialog.addDialogActionListener(new DialogActionAdapter() { + public void doOk() { + getWorker().cancel(true); + } + + public void doCancel() { + getWorker().cancel(true); + } + }); + loadingBar = new AutoProgressBar(dialog, Inter.getLocText("FR-Designer_Loading_Data"), "", 0, 100) { + public void doMonitorCanceled() { + getDialog().setVisible(false); + getWorker().cancel(true); + } + }; + } + + /** + * 数据集执行结果返回的所有字段 + * + * @return 数据集执行结果返回的所有字段 + * + * + * @date 2014-12-3-下午7:43:17 + * + */ + public List calculateColumnNameList() { + if (columnNameList != null) { + return columnNameList; + } + if (!createStore(false)) { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Engine_No-tableData")); + return new ArrayList(); + } + columnNameList = Arrays.asList(procedureDataModel.getColumnName()); + return columnNameList; + } + + /** + * 生成子节点 + * + * @return 节点数组 + * + * + * @date 2014-12-3-下午7:06:47 + * + */ + public ExpandMutableTreeNode[] load() { + List namelist; + if (storeProcedure.isCalculating()) { + namelist = Arrays.asList(new String[0]); + } else { + namelist = calculateColumnNameList(); + } + ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[namelist.size()]; + for (int i = 0; i < res.length; i++) { + res[i] = new ExpandMutableTreeNode(namelist.get(i)); + } + + return res; + } + + private boolean createStore(boolean needLoadingBar) { + try { + dataModels = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar); + if (dataModels == null || dataModels.length == 0) { + return false; + } + for (int i = 0; i < dataModels.length; i++) { + if (ComparatorUtils.equals(this.dsName, storeprocedureName + "_" + dataModels[i].getName())) { + procedureDataModel = dataModels[i]; + break; + } + } + return true; + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + return false; + } + + @Override + public Icon getIcon() { + return BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png"); + } + + /** + * 预览数据 + * + * @param previewModel 预览模式, 全部还是一个 + * + * + * @date 2014-12-3-下午7:05:50 + * + */ + public void previewData(final int previewModel) { + this.previewModel = previewModel; + new SwingWorker() { + + protected Object doInBackground() throws Exception { + loadingBar.close(); + PreviewTablePane.resetPreviewTable(); + dialog.setVisible(true); + return null; + } + }.execute(); + connectionBar = new AutoProgressBar(dialog, Inter.getLocText("Utils-Now_create_connection"), "", 0, 100) { + public void doMonitorCanceled() { + connectionBar.close(); + worker.cancel(true); + } + }; + worker.execute(); + } + + private void setWorker() { + worker = new SwingWorker() { + protected Void doInBackground() throws Exception { + connectionBar.start(); + boolean status = FRContext.getCurrentEnv().testConnection(((StoreProcedure) getTableData()).getDatabaseConnection()); + if (!status) { + connectionBar.close(); + // bug 61345 预览失败时,关闭窗口 + dialog.setVisible(false); + throw new Exception(Inter.getLocText("Datasource-Connection_failed")); + } + connectionBar.close(); + storeProcedure.resetDataModelList(); + createStore(true); + return null; + } + + public void done() { + try { + get(); + loadingBar.close(); + dialog.setVisible(false); + switch (previewModel) { + case StoreProcedureDataWrapper.PREVIEW_ALL: + PreviewTablePane.previewStoreDataWithAllDs(dataModels); + break; + case StoreProcedureDataWrapper.PREVIEW_ONE: + previewData(); + break; + } + } catch (Exception e) { + if (!(e instanceof CancellationException)) { + FRContext.getLogger().error(e.getMessage(), e); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage()); + } + loadingBar.close(); + } + } + }; + } + + private BasicDialog getDialog() { + return this.dialog; + } + + private SwingWorker getWorker() { + return this.worker; + } + + // august:这个只是预览返回的一个数据集 + + /** + * 预览返回的一个数据集 + * + * + * @date 2014-12-3-下午7:42:53 + * + */ + public void previewData() { + previewData(-1, -1); + } + + // august:这个只是预览返回的一个数据集 + + /** + * 预览返回的一个数据集,带有显示值和实际值的标记结果 + * + * @param keyIndex 实际值 + * @param valueIndex 显示值 + * + * + * @date 2014-12-3-下午7:42:27 + * + */ + public void previewData(final int keyIndex, final int valueIndex) { + PreviewTablePane.previewStoreData(procedureDataModel, keyIndex, valueIndex); + } + + + /** + * 预览返回的所有数据集,只有在编辑存储过程时才用到 + */ + public void previewAllTable() { + if (procedureDataModel == null) { + if (!createStore(true)) { + return; + } + } + PreviewTablePane.previewStoreDataWithAllDs(dataModels); + } + + @Override + public String getTableDataName() { + return dsName; + } + + public TableData getTableData() { + return storeProcedure; + } + + public String getStoreprocedureName() { + return storeprocedureName; + } + + /** + * 是否异常 + * + * @return 是否异常 + */ + public boolean isUnusual() { + return false; + } + + public boolean equals(Object obj) { + return obj instanceof StoreProcedureDataWrapper + && ComparatorUtils.equals(this.dsName, ((StoreProcedureDataWrapper) obj).getTableDataName()) + && ComparatorUtils.equals(this.storeProcedure, ((StoreProcedureDataWrapper) obj).getTableData()) + && ComparatorUtils.equals(this.storeprocedureName, ((StoreProcedureDataWrapper) obj).getStoreprocedureName()); + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureNameWrapper.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureNameWrapper.java new file mode 100644 index 0000000000..7c77d85fe0 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/StoreProcedureNameWrapper.java @@ -0,0 +1,153 @@ +package com.fr.design.data.tabledata.wrapper; + +import com.fr.base.BaseUtils; +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.base.TableData; +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.impl.storeproc.ProcedureDataModel; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.data.datapane.preview.PreviewTablePane; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.env.RemoteEnv; + +import javax.swing.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * StoreProcedureDataWrappe :存储过程的一个返回数据集,不是它本身。
+ * Oracle数据库肯定有它。SQL SERVER就不一定有了,大部分情况下都没有. + *

+ * StoreProcedureNameWrappe :存储过程本身的返回数据集,是它本身。
+ * Oracle数据库有它,但其实没必要,它就是Oracle所有返回数据集的第一个。SQL SERVER肯定有这个东西。 + * StoreProcedureNameWrappe + * 实际就是:以前我们在新建数据集时,从左边的列表中拖动一个存储过程到右边的SQL面板, + * 得到的SQL语句执行后返回的数据集。又因为结果可能得到多个数据集,所以默认用第一个 + * + * @author zhou + * @since 2012-4-12上午10:29:15 + */ +public final class StoreProcedureNameWrapper implements TableDataWrapper { + private ProcedureDataModel procedureDataModel; + private String name; + private StoreProcedure storeProcedure; + private List columnNameList; + + /** + * @param name 存储过程本身名字 + * @param storeProcedure 存储过程 + */ + public StoreProcedureNameWrapper(String name, StoreProcedure storeProcedure) { + this.name = name; + this.storeProcedure = storeProcedure; + } + + /** + * 生成子节点 + * + * @return 子节点 + */ + public ExpandMutableTreeNode[] load() { + List namelist = calculateColumnNameList(); + ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[namelist.size()]; + for (int i = 0; i < res.length; i++) { + res[i] = new ExpandMutableTreeNode(namelist.get(i)); + } + + return res; + } + + @Override + public String getTableDataName() { + return name; + } + + public TableData getTableData() { + return storeProcedure; + } + + @Override + public Icon getIcon() { + return BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png"); + } + + private void createStore(boolean needLoadingBar) { + try { + procedureDataModel = DesignTableDataManager.createLazyDataModel(storeProcedure, needLoadingBar)[0]; + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage()); + } + } + + /** + * 数据集执行结果返回的所有字段 + *

+ * TODO:要不要加上Exception呢?个人感觉很有必要 + * + * @return 字段 + */ + public List calculateColumnNameList() { + if (columnNameList != null) { + return columnNameList; + } + columnNameList = new ArrayList(); + Env env = FRContext.getCurrentEnv(); + if (env instanceof RemoteEnv) { + try { + createStore(false); + columnNameList = Arrays.asList(procedureDataModel.getColumnName()); + } catch (Exception e) { + FRContext.getLogger().errorWithServerLevel(e.getMessage(), e); + } + + } else { + if (procedureDataModel == null) { + createStore(false); + } + if (procedureDataModel != null) { + columnNameList = Arrays.asList(procedureDataModel.getColumnName()); + } + } + return columnNameList; + } + + /** + * 预览数据集 + */ + public void previewData() { + if (procedureDataModel == null) { + createStore(true); + } + PreviewTablePane.previewStoreData(procedureDataModel); + + } + + /** + * 预览数据集,带有显示值和实际值的标记结果 + * + * @param keyIndex 显示值Index + * @param valueIndex 实际值index + */ + public void previewData(int keyIndex, int valueIndex) { + if (procedureDataModel == null) { + createStore(true); + } + PreviewTablePane.previewStoreData(procedureDataModel, keyIndex, valueIndex); + } + + /** + * 是否异常 + * + * @return 异常返回true + */ + public boolean isUnusual() { + return false; + } + + public StoreProcedure getStoreProcedure() { + return storeProcedure; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataFactory.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataFactory.java new file mode 100644 index 0000000000..f3d2991c5e --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataFactory.java @@ -0,0 +1,189 @@ +package com.fr.design.data.tabledata.wrapper; + +import com.fr.base.FRContext; +import com.fr.base.TableData; +import com.fr.data.TableDataSource; +import com.fr.data.impl.*; +import com.fr.data.impl.storeproc.StoreProcedure; +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.data.datapane.TableDataNameObjectCreator; +import com.fr.design.data.tabledata.tabledatapane.*; +import com.fr.design.fun.TableDataCreatorProvider; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * 根据TableData取对应的一些属性 + * + * @author zhou + * @since 2012-3-28下午10:03:52 + */ +public abstract class TableDataFactory { + /** + * 有顺序的,用来排序用 + */ + private static Map map = new java.util.LinkedHashMap(); + + /** + * 同一类型的只能加一次,就加最上层的类,因为要排序。如果将所有的 FileTableData都加进来,那么FileTableData的排序就不正确了 + */ + static { + map.put(DBTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/database.png", DBTableData.class, DBTableDataPane.class)); + map.put(ClassTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/source/classTableData.png", ClassTableData.class, ClassTableDataPane.class)); + map.put(EmbeddedTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/dataTable.png", EmbeddedTableData.class, EmbeddedTableDataPane.class)); + map.put(DecoratedTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/multi.png", DecoratedTableData.class, DecoratedTableDataPane.class)); + map.put(StoreProcedure.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/store_procedure.png", StoreProcedure.class, ProcedureDataPane.class)); + map.put(MultiTDTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/multi.png", MultiTDTableData.class, MultiTDTableDataPane.class)); + map.put(FileTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/file.png", FileTableData.class, FileTableDataPane.class)); + map.put(RecursionTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/tree.png", RecursionTableData.class, TreeTableDataPane.class)); + map.put(MultiFieldTableData.class.getName(), new TableDataNameObjectCreator(null, "/com/fr/design/images/data/database.png", MultiFieldTableData.class, null)); + } + + /** + * 注册组件 + * + * @param clazz 数据集类 + * @param creator 组件 + */ + public static void register(Class clazz, TableDataNameObjectCreator creator) { + map.put(clazz.getName(), creator); + } + + private static TableDataNameObjectCreator getTableDataNameObjectCreator(TableData tabledata) { + TableDataCreatorProvider creatorProvider = ExtraDesignClassManager.getInstance().getTableDataCreatorProvider(); + if (creatorProvider != null) { + map.putAll(creatorProvider.registerMap()); + } + TableDataNameObjectCreator tableDataNameObjectCreator = map.get(tabledata.getClass().getName()); + if (tableDataNameObjectCreator == null) { + tableDataNameObjectCreator = map.get(tabledata.getClass().getSuperclass().getName()); + if (tableDataNameObjectCreator == null) { + tableDataNameObjectCreator = map.get(tabledata.getClass().getSuperclass().getSuperclass().getName());// 最多三层吧,不够再加 + // 不用循环了 + } + } + return tableDataNameObjectCreator; + } + + /** + * 获取数据集所对应的编辑面板 + * + * @param tabledata 数据集 + * @param name 名字 + * @return 返回数据集对应的pane + */ + public static AbstractTableDataPane creatTableDataPane(TableData tabledata, String name) { + AbstractTableDataPane datapane = null; + TableDataNameObjectCreator tableDataNameObjectCreator = getTableDataNameObjectCreator(tabledata); + Class> creatorClass = (Class>) tableDataNameObjectCreator.getUpdatePane(); + if (tableDataNameObjectCreator != null && creatorClass != null) { + try { + if (ComparatorUtils.equals(creatorClass, MultiTDTableDataPane.class) || ComparatorUtils.equals(creatorClass, TreeTableDataPane.class)) { + Constructor constructor = creatorClass.getDeclaredConstructor(new Class[]{String.class}); + constructor.setAccessible(true); + datapane = (AbstractTableDataPane) constructor.newInstance(name); + } else { + datapane = creatorClass.newInstance(); + } + datapane.populateBean(tabledata); // August:不管tabledata是刚刚新建的还是原来的,一律populate进去,如果出错就是代码写的不好 + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + return datapane; + } + + /** + * 创建数据集面板 + * + * @param tabledata 数据集 + * @return 返回数据集对应的pane + */ + public static AbstractTableDataPane creatTableDataPane(TableData tabledata) { + return creatTableDataPane(tabledata, StringUtils.EMPTY); + } + + /** + * 获取数据集所对应的图标路径 + * + * @param tabledata + * @return + */ + public static String getIconPath(TableData tabledata) { + TableDataNameObjectCreator tableDataNameObjectCreator = getTableDataNameObjectCreator(tabledata); + if (tableDataNameObjectCreator != null && tableDataNameObjectCreator.getIconPath() != null) { + return tableDataNameObjectCreator.getIconPath(); + } + return "/com/fr/design/images/data/database.png"; + } + + /** + * 获取已经排好顺序的数组 + * 先数据库查询,再程序,再内置数据集,再关联数据集,再文件数据集;这些内部按内部按先数字(0-9)、再字母(a-z)、然后汉字(拼音)进行排序。 + * + * @param source + * @return + */ + @SuppressWarnings("unchecked") + public static String[] getSortOfChineseNameOfTemplateData(TableDataSource source) { + clearAll(); + java.util.Iterator nameIt = source.getTableDataNameIterator(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + TableData td = source.getTableData(name); + addName(name, td); + } + return getSortedNameArray(); + } + + @SuppressWarnings("unchecked") + public static String[] getSortOfChineseNameOfServerData(DatasourceManagerProvider mgr) { + clearAll(); + java.util.Iterator nameIt = mgr.getTableDataNameIterator(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + TableData td = mgr.getTableData(name); + addName(name, td); + } + return getSortedNameArray(); + } + + private static String[] getSortedNameArray() { + Iterator> entryIt = map.entrySet().iterator(); + List namelist = new ArrayList(); + while (entryIt.hasNext()) { + Entry entry = entryIt.next(); + TableDataNameObjectCreator tableDataNameObjectCreator = entry.getValue(); + namelist.addAll(tableDataNameObjectCreator.getNames()); + } + return namelist.toArray(ArrayUtils.EMPTY_STRING_ARRAY); + } + + private static void addName(String name, TableData tabledata) { + if (tabledata == null) { + return; + } + + TableDataNameObjectCreator tableDataNameObjectCreator = getTableDataNameObjectCreator(tabledata); + if (tableDataNameObjectCreator == null) { + return; + } + tableDataNameObjectCreator.addNames(name); + } + + private static void clearAll() { + Iterator> entryIt = map.entrySet().iterator(); + while (entryIt.hasNext()) { + entryIt.next().getValue().clear(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataWrapper.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataWrapper.java new file mode 100644 index 0000000000..c35d0a7bc2 --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/TableDataWrapper.java @@ -0,0 +1,68 @@ +package com.fr.design.data.tabledata.wrapper; + +import com.fr.base.TableData; +import com.fr.design.gui.itree.refreshabletree.loader.ChildrenNodesLoader; + +import javax.swing.*; +import java.util.List; + +/** + * 将TableData包装下 用以区分模板数据集、服务器数据集、存储过程数据集 + * 定义了操作TableData的一些要用的方法:tabledata的名字、图标、产生的列名集合、预览数据集等 + * 注意现在存储过程StoreProcedure本质上不是TableData + * !!Notice:不支持对数据集的修改、重命名等改变TableData的操作。一个既定的数据集 + * (确定的SQL查询语句),对应相应的TableDataWrappe。 如果数据集变化了,那么TableDataWrappe也会重新生成。 + * 用以保证>>>>>>>>calculateColumnNameList()只计算一次,而且是正确的<<<<<< + * + * @author zhou + * @since 2012-3-28下午9:51:49 + */ +public interface TableDataWrapper extends ChildrenNodesLoader { + + /** + * 数据集名字 + * + * @return + */ + public String getTableDataName(); + + /** + * TableData + * + * @return + */ + public TableData getTableData(); + + /** + * 数据集图标 + * + * @return + */ + public Icon getIcon(); + + /** + * 数据集执行结果返回的所有字段 + * + * TODO:要不要加上Exception呢?个人感觉很有必要 + * @return + */ + public List calculateColumnNameList(); + + /** + * 预览数据集 + */ + public void previewData(); + + /** + * 预览数据集,带有显示值和实际值的标记结果 + */ + public void previewData(final int keyIndex, final int valueIndex); + + /** + * 是否异常 TODO:这个应该和calculateColumnNameList方法结合在一起 + * + * @return + */ + public boolean isUnusual(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/data/tabledata/wrapper/TemplateTableDataWrapper.java b/designer_base/src/com/fr/design/data/tabledata/wrapper/TemplateTableDataWrapper.java new file mode 100644 index 0000000000..823073aedc --- /dev/null +++ b/designer_base/src/com/fr/design/data/tabledata/wrapper/TemplateTableDataWrapper.java @@ -0,0 +1,37 @@ +package com.fr.design.data.tabledata.wrapper; + +import javax.swing.Icon; + +import com.fr.base.BaseUtils; +import com.fr.base.TableData; +import com.fr.data.impl.DBTableData; +import com.fr.design.icon.WarningIcon; +import com.fr.stable.StringUtils; + +public final class TemplateTableDataWrapper extends AbstractTableDataWrapper { + public TemplateTableDataWrapper(TableData tabledata) { + super(tabledata); + } + + public TemplateTableDataWrapper(TableData tabledata, String name) { + super(tabledata, name); + } + + @Override + public Icon getIcon() { + if (tabledata instanceof DBTableData && StringUtils.isBlank(((DBTableData) tabledata).getQuery())) { + return new WarningIcon(BaseUtils.readImage("/com/fr/design/images/data/database.png")); + } + return BaseUtils.readIcon(TableDataFactory.getIconPath(tabledata)); + } + + @Override + public boolean isUnusual() { + // 目前只判断DBTableData的异常 + if (tabledata instanceof DBTableData && StringUtils.isBlank(((DBTableData) tabledata).getQuery())) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/designer/EditingState.java b/designer_base/src/com/fr/design/designer/EditingState.java new file mode 100644 index 0000000000..3f4fdf6f05 --- /dev/null +++ b/designer_base/src/com/fr/design/designer/EditingState.java @@ -0,0 +1,13 @@ +package com.fr.design.designer; + +public interface EditingState { + public void revert(); + + public static EditingState NULL = new EditingState() { + + @Override + public void revert() { + } + + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/designer/TargetComponent.java b/designer_base/src/com/fr/design/designer/TargetComponent.java new file mode 100644 index 0000000000..4eedfa0129 --- /dev/null +++ b/designer_base/src/com/fr/design/designer/TargetComponent.java @@ -0,0 +1,177 @@ +package com.fr.design.designer; + +import javax.swing.*; + +import com.fr.design.event.TargetModifiedEvent; +import com.fr.design.event.TargetModifiedListener; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.DesignState; +import com.fr.design.menu.MenuDef; +import com.fr.design.menu.ShortCut; +import com.fr.design.menu.ToolBarDef; +import com.fr.stable.StringUtils; +import com.fr.design.mainframe.*; + +/** + * 模板设计界面 + */ +public abstract class TargetComponent extends JComponent { + private T target; + + public TargetComponent(T t) { + this.target = t; + } + + // TODO ALEX_SEP JWorkBook不想有copy, paste, cut的操作,怎么办? + public abstract void copy(); + + public abstract boolean paste(); + + public abstract boolean cut(); + + public abstract void stopEditing(); + + public final T getTarget() { + return target; + } + + + public abstract AuthorityEditPane createAuthorityEditPane(); + + public abstract ToolBarMenuDockPlus getToolBarMenuDockPlus(); + + public abstract int getMenuState(); + + public abstract JPanel getEastUpPane(); + + public abstract JPanel getEastDownPane(); + + public abstract void cancelFormat(); + + public void setTarget(T t) { + if (t != null) { + this.target = t; + } + } + + ///////////////////////////////////////Event Listener////////////// + + /** + * Adds a TargetModifiedListener to the listener list. + */ + public void addTargetModifiedListener(TargetModifiedListener targetModifiedListener) { + this.listenerList.add(TargetModifiedListener.class, targetModifiedListener); + } + + /** + * Removes a TargetModifiedListener from the listener list. + */ + public void removeTargetModifiedListener(TargetModifiedListener targetModifiedListener) { + this.listenerList.remove(TargetModifiedListener.class, targetModifiedListener); + } + + /** + * Fire template modified listeners. + */ + public void fireTargetModified() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == TargetModifiedListener.class) { + ((TargetModifiedListener) listeners[i + 1]).targetModified(new TargetModifiedEvent(this)); + } + } + + this.repaint(30); + } + + ///////////////////////////////////////ToolBarMenuDock////////////// + public abstract ToolBarDef[] toolbars4Target(); + + public abstract MenuDef[] menus4Target(); + + public abstract ShortCut[] shortcut4TemplateMenu(); + + public abstract ShortCut[] shortCuts4Authority(); + + public abstract JComponent[] toolBarButton4Form(); + + ///////////////////////////////////////EditingState////////////// + + public EditingState createEditingState() { + return EditingState.NULL; + } + + public static final TargetComponent NULLAVOID = new TargetComponent(StringUtils.EMPTY) { + + @Override + public void copy() { + } + + @Override + public boolean paste() { + return false; + } + + public int getMenuState(){ + return DesignState.WORK_SHEET; + } + + public void cancelFormat() { + return; + } + + @Override + public boolean cut() { + return false; + } + + @Override + public void stopEditing() { + } + + public AuthorityEditPane createAuthorityEditPane() { + return null; + } + + public ToolBarMenuDockPlus getToolBarMenuDockPlus() { + return null; + } + + @Override + public ToolBarDef[] toolbars4Target() { + return new ToolBarDef[0]; + } + + @Override + public MenuDef[] menus4Target() { + return new MenuDef[0]; + } + + @Override + public ShortCut[] shortcut4TemplateMenu() { + return new ShortCut[0]; + } + + public ShortCut[] shortCuts4Authority() { + return new ShortCut[0]; + + } + + public JComponent[] toolBarButton4Form() { + return new JComponent[0]; + } + + public JPanel getEastUpPane() { + return new JPanel(); + } + + public JPanel getEastDownPane() { + return new JPanel(); + } + + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/BasicDialog.java b/designer_base/src/com/fr/design/dialog/BasicDialog.java new file mode 100644 index 0000000000..703b192055 --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/BasicDialog.java @@ -0,0 +1,61 @@ +package com.fr.design.dialog; + +import java.awt.*; + +/* + * @author _denny + */ +public abstract class BasicDialog extends UIDialog { + public static final Dimension SMALL = new Dimension(340, 180); + public static final Dimension MEDIUM = new Dimension(600, 400); + public static final Dimension DEFAULT = new Dimension(660, 600); + public static final Dimension LARGE = new Dimension(900, 600); + public static final Dimension CHART = new Dimension(760, 560); + public static final Dimension MAP_SIZE = new Dimension(760, 450); + public static final Dimension UPDATE_ONLINE_SIZE = new Dimension(600,300); + + public BasicDialog(Frame parent) { + super(parent); + } + + public BasicDialog(Dialog parent) { + super(parent); + } + + public BasicDialog(Frame parent, BasicPane pane) { + this(parent, pane, true); + } + + public BasicDialog(Dialog parent, BasicPane pane) { + this(parent, pane, true); + } + + + public BasicDialog(Frame parent, BasicPane pane, boolean isNeedButtonPane) { + super(parent, pane, isNeedButtonPane); + } + + public BasicDialog(Dialog parent, BasicPane pane, boolean isNeedButtonPane) { + super(parent, pane, isNeedButtonPane); + } + + protected void setBasicDialogSize(Dimension d) { + super.setSize(d.width, d.height); + } + + protected void setBasicDialogSize(int w, int h) { + super.setSize(w, h); + } + + @Override + public void setSize(Dimension d) { + throw new UnsupportedOperationException(); + } + + @Override + public void setSize(int width, int height) { + throw new UnsupportedOperationException(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/BasicPane.java b/designer_base/src/com/fr/design/dialog/BasicPane.java new file mode 100644 index 0000000000..c94c246bf4 --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/BasicPane.java @@ -0,0 +1,395 @@ +package com.fr.design.dialog; + +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.general.Inter; +import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import java.awt.*; + +/* + * _denny: 这里的BasicPane通常会有populate & update方法 + * 记得populate 一定要在对应的dialog setVisible之前populate + */ +public abstract class BasicPane extends JPanel { + + /** + *显示窗口 + * @param window 窗口 + * @return 对话框 + */ + public BasicDialog showWindow(Window window) { + return this.showWindow(window, null); + } + + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + public BasicDialog showWindow(Window window, DialogActionListener l) { + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window); + } else { + dg = new DIALOG((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + + dg.setBasicDialogSize(BasicDialog.DEFAULT); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + /** + * 显示窗口 + * @param window 窗口 + * @param isNeedButtonsPane 是否需要确定删除按钮 + * @return 对话框 + */ + public BasicDialog showWindow(Window window, boolean isNeedButtonsPane) { + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window, isNeedButtonsPane); + } else { + dg = new DIALOG((Dialog) window, isNeedButtonsPane); + } + dg.setBasicDialogSize(BasicDialog.DEFAULT); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + + + /** + * 图表类型选择时 弹出的按钮大小, 不适合用最大最小, 因为图表大小 默认是规定好的, 那么界面大小也是必须配合. + * 并且包括 条件显示中 多个条件的大小 + * @param window 窗口 + * @param l 监听器 + * @return 对话框 + */ + public BasicDialog showWindow4ChartType(Window window, DialogActionListener l) { + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window); + } else { + dg = new DIALOG((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + + dg.setBasicDialogSize(BasicDialog.CHART); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + public BasicDialog showSmallWindow(Window window, DialogActionListener l) { + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window); + } else { + dg = new DIALOG((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + dg.setBasicDialogSize(BasicDialog.SMALL); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + public BasicDialog showMediumWindow(Window window, DialogActionListener l) { + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window); + } else { + dg = new DIALOG((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + dg.setBasicDialogSize(BasicDialog.MEDIUM); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + public BasicDialog showLargeWindow(Window window, DialogActionListener l) { + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window); + } else { + dg = new DIALOG((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + dg.setBasicDialogSize(BasicDialog.LARGE); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + public UIDialog showUnsizedWindow(Window window, DialogActionListener l) { + UIDialog dg; + if (window instanceof Frame) { + dg = new UnsizedDialog((Frame) window); + } else { + dg = new UnsizedDialog((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + public BasicDialog showWindow4ChartMapArray(Window window,DialogActionListener l){ + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window); + } else { + dg = new DIALOG((Dialog) window); + } + + if (l != null) { + dg.addDialogActionListener(l); + } + dg.setBasicDialogSize(BasicDialog.MAP_SIZE); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + + /** + * 显示窗口 + * @param window 窗口 + * @return 对话框 + */ + public BasicDialog showWindow4UpdateOnline(Window window){ + BasicDialog dg; + if (window instanceof Frame) { + dg = new DIALOG((Frame) window,false); + } else { + dg = new DIALOG((Dialog) window,false); + } + dg.setBasicDialogSize(BasicDialog.UPDATE_ONLINE_SIZE); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + protected abstract String title4PopupWindow(); + + public String getTitle(){ + return title4PopupWindow(); + } + + /** + * 作为名字面板 + * @return 面板 + */ + public NamePane asNamePane() { + return new NamePane(this); + } + + /** + * 检查是否符合规范 + * + * @throws Exception 异常 + */ + public void checkValid() throws Exception { + } + + public static final class NamePane extends BasicPane { + private UITextField nameTextField; + private BasicPane centerPane; + private UILabel showfield; + private PropertyChangeAdapter changeListener; + + private NamePane(BasicPane bPane) { + this.setLayout(new BorderLayout(4, 4)); + + nameTextField = new UITextField(30); + JPanel northPane = new JPanel(new BorderLayout(4, 4)); + northPane.add(new UILabel(Inter.getLocText("FR-Designer-Hyperlink_Name") + ":"), BorderLayout.WEST); + northPane.add(nameTextField, BorderLayout.CENTER); + northPane.add(showfield = new UILabel(" "), BorderLayout.EAST); + showfield.setForeground(new Color(204, 0, 1)); + showfield.setPreferredSize(new Dimension(220, showfield.getPreferredSize().height)); + this.add(northPane, BorderLayout.NORTH); + this.centerPane = bPane; + this.add(bPane, BorderLayout.CENTER); + this.nameTextField.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() { + + @Override + public void insertUpdate(DocumentEvent e) { + doTextChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + doTextChanged(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + doTextChanged(); + } + + }); + } + + private void doTextChanged() { + if (changeListener != null) { + changeListener.propertyChange(); + } + } + + public String getObjectName() { + return this.nameTextField.getText().trim(); + } + + public void setObjectName(String name) { + this.nameTextField.setText(name); + } + + public void setShowText(String name) { + this.showfield.setText(name); + } + + @Override + protected String title4PopupWindow() { + return centerPane.title4PopupWindow(); + } + + /** + * 检查是否符合规范 + * + * @throws Exception 异常 + */ + public void checkValid() throws Exception { + super.checkValid(); + + this.centerPane.checkValid(); + } + + /** + * 添加属性改变的监听器 + * @param listener 监听器 + */ + public void addPropertyChangeListener(PropertyChangeAdapter listener) { + this.changeListener = listener; + } + } + + private class DIALOG extends BasicDialog { + public DIALOG(Frame parent) { + super(parent, BasicPane.this); + this.setTitle(BasicPane.this.title4PopupWindow()); + } + + public DIALOG(Dialog parent) { + super(parent, BasicPane.this); + this.setTitle(BasicPane.this.title4PopupWindow()); + } + + + public DIALOG(Frame parent, boolean isNeedButtonPane) { + super(parent, BasicPane.this, isNeedButtonPane); + this.setTitle(BasicPane.this.title4PopupWindow()); + } + + + public DIALOG(Dialog parent, boolean isNeedButtonPane) { + super(parent, BasicPane.this, isNeedButtonPane); + this.setTitle(BasicPane.this.title4PopupWindow()); + } + + + + /** + * init Components + */ + + + /** + * Check valid. + */ + public void checkValid() throws Exception { + BasicPane.this.checkValid(); + } + + } + + private class UnsizedDialog extends UIDialog { + + public UnsizedDialog(Frame parent) { + super(parent, BasicPane.this); + this.setTitle(BasicPane.this.title4PopupWindow()); + } + + public UnsizedDialog(Dialog parent) { + super(parent, BasicPane.this); + this.setTitle(BasicPane.this.title4PopupWindow()); + } + + + public void checkValid() throws Exception { + BasicPane.this.checkValid(); + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/BasicScrollPane.java b/designer_base/src/com/fr/design/dialog/BasicScrollPane.java new file mode 100644 index 0000000000..7ff1bab92a --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/BasicScrollPane.java @@ -0,0 +1,200 @@ +package com.fr.design.dialog; + +import java.awt.AWTEvent; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JScrollBar; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.iscrollbar.UIScrollBar; + +public abstract class BasicScrollPane extends BasicBeanPane{ + private static final long serialVersionUID = -4293765343535336275L; + private static final int MAXVALUE = 100; + private static final int DET_WIDTH_OVER_HEIGHT = 4; + private static final int DET_HEIGHT = 5; + private static final int DET_WIDTH = 12; + private static final int MOUSE_WHELL_SPEED = 5; + private int maxheight = 280; + private int beginY = 0; + protected Color original; + + private UIScrollBar scrollBar; + protected JPanel leftcontentPane; + + + protected abstract JPanel createContentPane(); + + protected BasicScrollPane() { + enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + original = this.getBackground(); + this.setLayout(new BarLayout()); + scrollBar = new UIScrollBar(JScrollBar.VERTICAL) { + private static final long serialVersionUID = 155777947121777223L; + + @Override + public int getVisibleAmount() { + int preferheight = leftcontentPane.getPreferredSize().height; + if(preferheight <= 0) { + return 0; + } + int e = MAXVALUE * (getHeight() - 1) / preferheight; + setVisibleAmount(e); + return e; + } + + @Override + public int getMaximum() { + return MAXVALUE; + } + + }; + this.add(scrollBar); + scrollBar.addAdjustmentListener(new AdjustmentListener() { + + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + ajustValues(); + } + }); + // august:鼠标滚轮滑动事件 + this.addMouseWheelListener(new MouseWheelListener() { + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + int value = scrollBar.getValue(); + value += MOUSE_WHELL_SPEED * e.getWheelRotation(); + scrollBar.setValue(value); + ajustValues(); + } + }); + + layoutContentPane(); + } + + //上层pane已经有了scroll,需要把事件屏蔽掉 + protected BasicScrollPane(boolean noScroll) { + original = this.getBackground(); + this.setLayout(new BarLayout()); + scrollBar = new UIScrollBar(JScrollBar.VERTICAL) { + private static final long serialVersionUID = 155777947121777223L; + + @Override + public int getVisibleAmount() { + int preferheight = leftcontentPane.getPreferredSize().height; + if(preferheight <= 0) { + return 0; + } + int e = MAXVALUE * (getHeight() - 1) / preferheight; + setVisibleAmount(e); + return e; + } + + @Override + public int getMaximum() { + return MAXVALUE; + } + + }; + this.add(scrollBar); + layoutContentPane(); + } + + protected void layoutContentPane() { + leftcontentPane = createContentPane(); + leftcontentPane.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 5, original)); + this.add(leftcontentPane); + } + + /** + * august:不容易啊 还要用笔画图立个方程才计算出来 + * + * @param e + */ + protected void ajustValues() { + doLayout(); + } + + protected class BarLayout implements LayoutManager { + + @Override + public void addLayoutComponent(String name, Component comp) { + + } + + @Override + public void removeLayoutComponent(Component comp) { + + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return leftcontentPane.getPreferredSize(); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return leftcontentPane.getMinimumSize(); + } + + @Override + public void layoutContainer(Container parent) { + if(getHeight() >= leftcontentPane.getPreferredSize().height) { + scrollBar.setEnabled(false); + scrollBar.setVisible(false); + } else { + scrollBar.setEnabled(true); + scrollBar.setVisible(true); + } + maxheight = getHeight() - DET_HEIGHT; + if ((MAXVALUE - scrollBar.getVisibleAmount()) == 0) { + beginY = 0; + } else { + int preferheight = leftcontentPane.getPreferredSize().height; + int value = scrollBar.getValue(); + + int baseValue = MAXVALUE - scrollBar.getVisibleAmount(); + beginY = baseValue == 0 ? 0 : value * (preferheight - maxheight) / baseValue; + if(MAXVALUE - scrollBar.getVisibleAmount() != 0) { + beginY = value * (preferheight - maxheight) / (MAXVALUE - scrollBar.getVisibleAmount()); + } + } + int width = parent.getWidth(); + int height = parent.getHeight(); + if (leftcontentPane.getPreferredSize().height > maxheight) { + leftcontentPane.setBounds(0, -beginY, width - scrollBar.getWidth() - DET_WIDTH_OVER_HEIGHT, height + beginY); + scrollBar.setBounds(width - scrollBar.getWidth() - 1, 0, scrollBar.getWidth(), height); + } else { + leftcontentPane.setBounds(0, 0, width - DET_WIDTH, height); + } + leftcontentPane.validate(); + } + } + + @Override + public T updateBean() { + return null; + } + + /** + * 用于在调用removeAll以后恢复原来pane的结构,放在这边是因为BarLayout是内部类 + * @param pane + */ + public void reloaPane(JPanel pane){ + this.setLayout(new BarLayout()); + this.add(scrollBar); + leftcontentPane = pane; + leftcontentPane.setBorder(BorderFactory.createMatteBorder(0, 10, 0, 5, original)); + this.add(leftcontentPane); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/DialogActionAdapter.java b/designer_base/src/com/fr/design/dialog/DialogActionAdapter.java new file mode 100644 index 0000000000..a1f0c30444 --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/DialogActionAdapter.java @@ -0,0 +1,9 @@ +package com.fr.design.dialog; + +public abstract class DialogActionAdapter implements DialogActionListener { + @Override + public void doOk() {} + + @Override + public void doCancel() {} +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/DialogActionListener.java b/designer_base/src/com/fr/design/dialog/DialogActionListener.java new file mode 100644 index 0000000000..9addfd0fcc --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/DialogActionListener.java @@ -0,0 +1,8 @@ +package com.fr.design.dialog; + +public interface DialogActionListener { + + public void doOk(); + + public void doCancel(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/InformationWarnPane.java b/designer_base/src/com/fr/design/dialog/InformationWarnPane.java new file mode 100644 index 0000000000..e5dd4fd9fb --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/InformationWarnPane.java @@ -0,0 +1,172 @@ +package com.fr.design.dialog; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ibutton.UIToggleButton; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.design.utils.gui.GUICoreUtils; + +public class InformationWarnPane extends JPanel{ + private UITextArea moreText; + private JPanel controlPane; + private AlertDialog dg; + private String title; + private UIToggleButton arrow; + + private boolean isShow = false; + public void show() { + showWindow(SwingUtilities.getWindowAncestor(this)).setVisible(true); + } + + public InformationWarnPane(String infor, String moreInfo, String title) { + this.title = title; + this.setLayout(null); + this.setBounds(5,5,410,130); + UILabel image = new UILabel(new ImageIcon(getClass().getResource("/com/fr/design/images/buttonicon/warn.png"))); + image.setBounds(10, 25, 80, 80); + UITextArea warnLabel = new UITextArea(infor); + warnLabel.setLineWrap(true); + warnLabel.setWrapStyleWord(true); + warnLabel.setHighlighter(null); + warnLabel. setEditable(false); + warnLabel.setBackground(this.getBackground()); + warnLabel.setBounds(100, 20, 300, 80); + arrow = new UIToggleButton(BaseUtils.readIcon("com/fr/design/images/buttonicon/more.png")); + arrow.setRolloverIcon(BaseUtils.readIcon("/com/fr/design/images/buttonicon/more3.png")); + arrow.setBorderPainted(false); + arrow.setExtraPainted(false); + + arrow.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + arrow.setSelected(arrow.isSelected()); + boolean isSelected = arrow.isSelected(); + moreText.setVisible(isSelected); + if(isSelected) { + arrow.setIcon(BaseUtils.readIcon("/com/fr/design/images/buttonicon/more2.png")); + arrow.setRolloverIcon(BaseUtils.readIcon("/com/fr/design/images/buttonicon/more4.png")); + InformationWarnPane.this.setBounds(5,5,410,265); + controlPane.setBounds(175, 270, 80, 25); + dg.setBounds(dg.getX(), dg.getY(), 430, 330); + } else { + arrow.setIcon(BaseUtils.readIcon("com/fr/design/images/buttonicon/more.png")); + arrow.setRolloverIcon(BaseUtils.readIcon("/com/fr/design/images/buttonicon/more3.png")); + InformationWarnPane.this.setBounds(5,5,410,130); + controlPane.setBounds(175, 135, 80, 25); + dg.setBounds(dg.getX(), dg.getY(), 430, 195); + } + } + }); + + arrow.setBounds(90,100,30,30); + UILabel more = new UILabel(""+Inter.getLocText("More-information")+""); + more.setBounds(125,102,55,25); + + moreText = new UITextArea(moreInfo); + moreText.setForeground(Color.blue); + moreText.setBounds(100,130,300,130); + moreText.setLineWrap(true); + moreText.setWrapStyleWord(true); + moreText.setHighlighter(null); + moreText. setEditable(false); + moreText.setBackground(this.getBackground()); + + moreText.setVisible(arrow.isSelected()); + this.add(image); + this.add(warnLabel); + this.add(arrow); + this.add(more); + this.add(moreText); + } + + public AlertDialog showWindow(Window window) { + isShow = true; + if (window instanceof Frame) { + dg = new AlertDialog((Frame) window); + } else { + dg = new AlertDialog((Dialog) window); + } + dg.setBounds(0, 0, 430, 195); + dg.setIconImage(BaseUtils.readImage("/com/fr/base/images/oem/logo.png")); + GUICoreUtils.centerWindow(dg); + dg.setResizable(false); + return dg; + } + + public boolean isShow() { + return isShow; + } + + private class AlertDialog extends JDialog { + protected UIButton okButton; + + public AlertDialog(Frame parent) { + super(parent); + this.setTitle(InformationWarnPane.this.title); + this.initComponents(); + } + + public AlertDialog(Dialog parent) { + super(parent); + this.setTitle(InformationWarnPane.this.title); + this.initComponents(); + } + + /** + * init Components + */ + protected void initComponents() { + JPanel contentPane = (JPanel) this.getContentPane(); + contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + contentPane.setLayout(null); + contentPane.add(InformationWarnPane.this); + contentPane.add(this.createControlButtonPane()); + this.setModal(true); + this.pack(); + GUICoreUtils.centerWindow(this); + } + + private JPanel createControlButtonPane() { + controlPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + okButton = new UIButton("" + Inter.getLocText("OK") + "") { + @Override + public Dimension getPreferredSize() { + // TODO Auto-generated method stub + return new Dimension(30, 20); + } + }; + controlPane.add(okButton, BorderLayout.CENTER); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + isShow = false; + AlertDialog.this.setVisible(false); + } + }); + controlPane.setBounds(175, 135, 80, 25); + return controlPane; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/JWizardDialog.java b/designer_base/src/com/fr/design/dialog/JWizardDialog.java new file mode 100644 index 0000000000..989140ae0d --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/JWizardDialog.java @@ -0,0 +1,368 @@ +package com.fr.design.dialog; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JDialog; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.JSeparator; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; + +/** + * Wizard dialog. + */ +public class JWizardDialog extends BasicDialog { + //The label which holds the image to display on the left side of the wizard. + private JPanel logoPanel; + private UILabel logoLabel; + + //The panel to which JWizardPanel's are added. + private JPanel workArea; + + //The layout for the work area. + private CardLayout cardLayout; + + //The current JWizardPanel + private JWizardPanel currentWizard = null; + + private int currentStep = -1; + private int lastStep = -1; + private int panelCount = 0; + + //The buttons + private UIButton buttonBack; + private UIButton buttonNext; + private UIButton buttonFinish; + private UIButton buttonCancel; + + // True if the finish button should be enabled all the time + private boolean enableEarlyFinish = false; + + // True if the cancel button is enabled on the final step + private boolean enableCancelAtEnd = true; + + /** + * Shows dialog + */ + public static JWizardDialog showWindow(Window window) { + if (window instanceof Frame) { + return new JWizardDialog((Frame) window); + } else { + return new JWizardDialog((Dialog) window); + } + } + + protected JWizardDialog(Frame owner) { + super(owner); + initComponents(); + } + + protected JWizardDialog(Dialog owner) { + super(owner); + initComponents(); + } + + /** + * Initialize the JWizardDialog. + */ + protected void initComponents() { + JPanel contentPane = (JPanel)this.getContentPane(); + contentPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + contentPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + this.applyClosingAction(); + this.applyEscapeAction(); + // If the user tries to close the wizard, the result should be the + // same as pressing Cancel + setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); + + // Window close is the same as cancel. If the cancel button is + // disabled, then a window close does nothing + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + if (buttonCancel.isEnabled()) { + cancel(); + } + } + }); + + // Work area for WizardPanel's + workArea = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardLayout = new CardLayout(); + workArea.setLayout(cardLayout); + + // Buttons + buttonBack = new UIButton(Inter.getLocText("Previous")); + buttonBack.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + back(); + } + }); + buttonNext = new UIButton(Inter.getLocText("Next")); + buttonNext.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + next(); + } + }); + buttonFinish = new UIButton(Inter.getLocText("Finish")); + buttonFinish.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + finish(); + } + }); + buttonCancel = new UIButton(Inter.getLocText("Cancel")); + buttonCancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + cancel(); + } + }); + JPanel buttons = FRGUIPaneFactory.createRightFlowInnerContainer_S_Pane(); + + //p:几个按钮必须要等距,所以才需要用GridLayout. + JPanel bbPane = FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); + buttons.add(bbPane); + bbPane.add(buttonBack); + bbPane.add(buttonNext); + bbPane.add(buttonFinish); + bbPane.add(buttonCancel); + + JPanel buttonPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + buttonPanel.add(new JSeparator(), BorderLayout.NORTH); + buttonPanel.add(buttons); + + contentPane.add(buttonPanel, BorderLayout.SOUTH); + contentPane.add(workArea); + + this.setModal(true); + } + + /** + * Add an image which displays on the left side of the wizard. By + * default, no image is displayed. This must be set before the dialog + * is made visible. + * + * @param icon The icon representing the image to display. If null, no + * image is displayed. + */ + public void setWizardIcon(Icon icon) { + // If null, remove any existing logo panel + if (icon == null) { + if (logoPanel != null) { + remove(logoPanel); + logoPanel = null; + logoLabel = null; + } + } + //If not null, add it or replace an existing label + else { + if (logoPanel != null) { + remove(logoPanel); + } + logoPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); + logoLabel = new UILabel(icon); + logoPanel.add(logoLabel, BorderLayout.NORTH); + getContentPane().add(logoPanel, BorderLayout.WEST); + } + } + + /** + * Add a panel representing a step in the wizard. Since removing a + * panel would force a renumbering of the remaining panels and since + * you have flexible sequencing control, there is no matching + * removeWizardPanel() method. + * + * @param panel The JWizardPanel to add + */ + + public void addWizardPanel(JWizardPanel panel) { + if (currentWizard == null) { + currentWizard = panel; + currentStep = 0; + } + workArea.add(panel, Integer.toString(panelCount++)); + panel.setWizardParent(this); + } + + /** + * If this method is called, the Finish button is enabled immediately. + * By default, it is enabled only on the last step (any step where the + * next JWizardPanel step is -1). + */ + + public void setEarlyFinish() { + enableEarlyFinish = true; + } + + /** + * If this method is called, the Cancel button is disabled when on the + * last step. If setEarlyFinish() is called, it is still disabled only + * on the last step. + */ + + public void disableCancelAtEnd() { + enableCancelAtEnd = false; + } + + /** + * Returns the current step being displayed by the wizard. Steps start + * at 0. If no step is yet displayed, a -1 is returned. + * + * @return The current step being displayed by the wizard. + */ + + public int getCurrentStep() { + return currentStep; + } + + /** + * Returns the last step displayed by the wizard. Steps start at 0. If + * there is no previous step yet, -1 is returned. + * + * @return The last step being displayed by the wizard. + */ + + public int getLastStep() { + return lastStep; + } + + /** + * Set the sensitivity of each button based on the back and next step + * values. This should be called when changing steps or when the back + * or next button values are changed. + */ + public void applyButtonStates() { + int backStep = currentWizard.getBackStep(); + int nextStep = currentWizard.getNextStep(); + + boolean atBegin = backStep < 0 || backStep >= panelCount; + + boolean atEnd = nextStep < 0 || nextStep >= panelCount; + + buttonBack.setEnabled(!atBegin); + buttonNext.setEnabled(!atEnd); + buttonFinish.setEnabled(enableEarlyFinish || atEnd); + buttonCancel.setEnabled(!atEnd || enableCancelAtEnd); + + // Set the default button + if (buttonNext.isEnabled()) { + getRootPane().setDefaultButton(buttonNext); + } else if (buttonFinish.isEnabled()) { + getRootPane().setDefaultButton(buttonFinish); + } else if (buttonBack.isEnabled()) { + getRootPane().setDefaultButton(buttonBack); + } else { + getRootPane().setDefaultButton(null); + } + } + + /** + * Display the JWizardPanel with the given step number. This method is + * package public so that JWizardPanel can call it. The + * switchToStep() method may override the step choice. + * + * + * @param step The step number of the JWizardPanel to display. + * @see #switchToStep(int,int) + */ + protected void goTo(int step) { + // Give the user a last chance to change things + step = switchToStep(currentStep, step); + + // We can't do anything if we're outside the valid range + if (step < 0 || step >= panelCount) { + return; + } + + // Save the current step as the previous step + lastStep = currentStep; + + currentWizard = (JWizardPanel) workArea.getComponent(step); + currentStep = step; + cardLayout.show(workArea, Integer.toString(step)); + + // Set the button states + applyButtonStates(); + } + + //********************************************************************** + // Protected + //********************************************************************** + + /** + * Called when the Back button is pressed. This calls the back() + * method in the current JWizardPanel. + * + * @see JWizardPanel#back() + */ + protected void back() { + if (currentWizard != null) { + currentWizard.doBack(); + } + } + + /** + * Called when the Next button is pressed. This calls the next() + * method in the current JWizardPanel. + * + * @see JWizardPanel#next() + */ + protected void next() { + if (currentWizard != null) { + currentWizard.doNext(); + } + } + + /** + * Called when the Finish button is pressed. This calls dispose(). You + * will probably want to override this. + */ + protected void finish() { + doOK(); + } + + /** + * Called when the Cancel button is pressed. This calls dispose(). + */ + protected void cancel() { + doCancel(); + } + + /** + * This method is called just prior to switching from one step to + * another (after any next() or back() method is called). It receives + * the current and new indices. By default, it returns the new index. + * You can override the method if you need to control sequencing from + * this JWizardDialog class (normally, each step decides what the back + * and next steps should be). + * + * @param currentIndex The index of the current JWizardPanel. + * @param newIndex The index of the JWizardPanel we are about to display. + * @return The index of the JWizardPanel to display. + */ + protected int switchToStep(int currentIndex, int newIndex) { + return newIndex; + } + + /** + * Get the currentWizard Pane + */ + protected JWizardPanel getCurrentWizard() { + return this.currentWizard; + } + + @Override + public void checkValid() throws Exception { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/JWizardPanel.java b/designer_base/src/com/fr/design/dialog/JWizardPanel.java new file mode 100644 index 0000000000..0e75fc8e0d --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/JWizardPanel.java @@ -0,0 +1,229 @@ +package com.fr.design.dialog; + +import java.awt.BorderLayout; +import java.awt.Font; + +import javax.swing.BorderFactory; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.JSeparator; + +import com.fr.design.layout.FRGUIPaneFactory; + +/** + * WizardPane. Add with getContentPane(). + */ +public class JWizardPanel extends BasicPane { + JWizardDialog dialogParent; + + // The step title + JPanel titlePanel; + String stepTitle; + UILabel stepTitleLabel; + + // The content pane + JPanel contentPane; + + // The back and next steps + int backStep = -1; + int nextStep = -1; + + // Flags the first time the component is added to a window + boolean firstNotify = true; + + /** + * Creates a new JWizardPanel with a double buffer and a flow layout. The + * flow layout is assigned to the panel accessed through getContentPane(). + */ + public JWizardPanel() { + super(); + initComponents(); + } + + /** + * Initialize the JWizardPanel. + */ + private void initComponents() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + + // Set the layout for the content area + contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + + contentPane.setBorder(BorderFactory.createEmptyBorder(2, 2, 4, 4)); + + // Step title + titlePanel =FRGUIPaneFactory.createBorderLayout_S_Pane(); + titlePanel.add(new JSeparator(), BorderLayout.SOUTH); + stepTitleLabel = new UILabel(" "); + titlePanel.add(stepTitleLabel); + + add(titlePanel, BorderLayout.NORTH); + add(contentPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return "wizard"; + } + + /** + * Set the title to use for this step. Normally this title would be unique + * for each wizards step. + * + * @param stepTitle The title to use for this step. + */ + public void setStepTitle(String stepTitle) { + this.stepTitle = stepTitle; + stepTitleLabel.setText(stepTitle); + + stepTitleLabel.invalidate(); + validate(); + } + + /** + * Get the step title to use for this step. + * + * @return The step title to use for this step. + */ + public String getStepTitle() { + return stepTitle; + } + + /** + * Get a JPanel to use for adding your own components to this WizardPanel. + * Do not add components directly to the JWizardPanel. The JPanel uses the + * layout given in the JWizardPanel constructor. + * + * @return The JPanel to use for adding components for this wizard step. + */ + public JPanel getContentPane() { + return contentPane; + } + + /** + * Get the wizard step to go to when the Back button is pressed. + * + * @return The wizard step to go to when the Back button is pressed. + */ + + public int getBackStep() { + return backStep; + } + + /** + * Set the wizard step to go to when the Back button is pressed. This should + * be set in the constructor of the JWizardPanel subclass since it + * determines whether the Back button is enabled or not. + * + * @param backStep + * The wizard step to go to when the Back button is pressed. + */ + + public void setBackStep(int backStep) { + this.backStep = backStep; + JWizardDialog dialog = getWizardParent(); + if (dialog != null) { + dialog.applyButtonStates(); + } + } + + /** + * Get the wizard step to go to when the Next button is pressed. + * + * @return The wizard step to go to when the Next button is pressed. + */ + public int getNextStep() { + return nextStep; + } + + /** + * Set the wizard step to go to when the Next button is pressed. This should + * be set in the constructor of the JWizardPanel subclass since it + * determines whether the Next and Finish buttons are enabled or not. + * + * @param nextStep The wizard step to go to when the Next button is pressed. + */ + public void setNextStep(int nextStep) { + this.nextStep = nextStep; + JWizardDialog dialog = getWizardParent(); + if (dialog != null) { + dialog.applyButtonStates(); + } + } + + /** + * Returns the JWizardDialog in which this JWizardPanel resides. This is + * valid only after the panel has been added to the dialog. + * + * @return The JWizardDialog in which this JWizardPanel resides. + */ + + public JWizardDialog getWizardParent() { + return dialogParent; + } + + /** + * Do not call directly. + */ + public void addNotify() { + if (firstNotify) { + Font font = stepTitleLabel.getFont(); + font = font.deriveFont(Font.BOLD, font.getSize() * 14 / 10); + stepTitleLabel.setFont(font); + firstNotify = false; + } + super.addNotify(); + } + + /** + * Set the JWizardDialog parent for this JWizardPanel. + * + * @param dialogParent + * The JWizardPanel parent for this JWizardPanel. + */ + void setWizardParent(JWizardDialog dialogParent) { + this.dialogParent = dialogParent; + } + + /** + * Calls back(). This allows the JWizardDialog to call the protected method + * back(). + * + * @see #back() + */ + + void doBack() { + back(); + } + + /** + * Calls next(). This allows the JWizardDialog to call the protected method + * next(). + * + * @see #next() + */ + void doNext() { + next(); + } + + /** + * Called when the Back button is pressed. By default this displays the + * wizard step set by setBackStep(). + * + * @see #setBackStep(int) + */ + protected void back() { + dialogParent.goTo(getBackStep()); + } + + /** + * Called when the Next button is pressed. By default this displays the + * wizard step set by setNextStep(). + * + * @see #setNextStep(int) + */ + protected void next() { + dialogParent.goTo(getNextStep()); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/MultiTabPane.java b/designer_base/src/com/fr/design/dialog/MultiTabPane.java new file mode 100644 index 0000000000..3d87678068 --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/MultiTabPane.java @@ -0,0 +1,88 @@ +package com.fr.design.dialog; + + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Dimension; +import java.util.List; + +import javax.swing.JPanel; + +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.gui.ibutton.UITabGroup; + +/** + * + * 标准的多层Tab切换类型. +* @author kunsnat E-mail:kunsnat@gmail.com +* @version 创建时间:2013-4-22 上午10:31:03 + */ +public abstract class MultiTabPane extends FurtherBasicBeanPane{ + private static final long serialVersionUID = 2298609199400393886L; + protected UITabGroup tabPane; + protected String[] NameArray; + protected JPanel centerPane; + protected CardLayout cardLayout; + protected List paneList; + + protected abstract List initPaneList(); + public abstract void populateBean(T ob); + public abstract void updateBean(T ob); + + public int getSelectedIndex() { + return tabPane.getSelectedIndex(); + } + + public MultiTabPane() { + cardLayout = new CardLayout(); + paneList = initPaneList(); + relayoutWhenListChange(); + } + + /** + * 当List中的界面变化时, 重新布局 + */ + public void relayoutWhenListChange() { + centerPane = new JPanel(cardLayout) { + @Override + public Dimension getPreferredSize() { + if (tabPane.getSelectedIndex() == -1) { + return super.getPreferredSize(); + } else { + return paneList.get(tabPane.getSelectedIndex()).getPreferredSize(); + } + } + }; + NameArray = new String[paneList.size()]; + for (int i = 0; i < paneList.size(); i++) { + BasicPane pane = paneList.get(i); + NameArray[i] = pane.title4PopupWindow(); + centerPane.add(pane, NameArray[i]); + } + + tabPane = new UITabGroup(NameArray) { + @Override + public void tabChanged(int index) { + dealWithTabChanged(index); + } + }; + tabPane.setSelectedIndex(0); + tabPane.tabChanged(0); + initLayout(); + } + + protected void dealWithTabChanged(int index) { + cardLayout.show(centerPane, NameArray[index]); + tabChanged(); + } + + protected void tabChanged() { + + } + + protected void initLayout() { + this.setLayout(new BorderLayout(0, 4)); + this.add(tabPane, BorderLayout.NORTH); + this.add(centerPane, BorderLayout.CENTER); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/UIDialog.java b/designer_base/src/com/fr/design/dialog/UIDialog.java new file mode 100644 index 0000000000..7ba10164ba --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/UIDialog.java @@ -0,0 +1,234 @@ +package com.fr.design.dialog; + +import com.fr.base.FRContext; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; + +/** + * Created with IntelliJ IDEA. + * User: 小灰灰 + * Date: 13-7-16 + * Time: 下午2:17 + * To change this template use File | Settings | File Templates. + */ +public abstract class UIDialog extends JDialog { + public static final String OK_BUTTON = "basic_ok"; + public static final String CANCEL_BUTTON = "basic_cancel"; + private UIButton okButton, cancelButton; + private BasicPane pane; + private java.util.List listeners = new ArrayList(); + private boolean isDoOKSucceed; + + + public UIDialog(Frame parent) { + super(parent); + } + + public UIDialog(Dialog parent) { + super(parent); + } + + + public UIDialog(Frame parent, BasicPane pane) { + this(parent, pane, true); + } + + public UIDialog(Dialog parent, BasicPane pane) { + this(parent, pane, true); + } + + + public UIDialog(Frame parent, BasicPane pane, boolean isNeedButtonPane) { + super(parent); + this.pane = pane; + initComponents(isNeedButtonPane); + } + + public UIDialog(Dialog parent, BasicPane pane, boolean isNeedButtonPane) { + super(parent); + this.pane = pane; + initComponents(isNeedButtonPane); + } + + public void setDoOKSucceed(boolean isOk) { + isDoOKSucceed = isOk; + } + + private void initComponents(boolean isNeedButtonPane) { + JPanel contentPane = (JPanel) this.getContentPane(); + contentPane.setBorder(BorderFactory.createEmptyBorder(2, 4, 4, 4)); + contentPane.setLayout(new BorderLayout(0, 4)); + this.applyClosingAction(); + this.applyEscapeAction(); + contentPane.add(pane, BorderLayout.CENTER); + if (isNeedButtonPane) { + contentPane.add(this.createControlButtonPane(), BorderLayout.SOUTH); + } + this.setName(pane.title4PopupWindow()); + this.setModal(true); + this.pack(); + GUICoreUtils.centerWindow(this); + } + + private JPanel createControlButtonPane() { + JPanel controlPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + JPanel buttonsPane = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0)); + controlPane.add(buttonsPane, BorderLayout.EAST); + + //增加一个自定义按钮, 可以用于eg: 设为全局配置 + addCustomButton(buttonsPane); + //确定 + addOkButton(buttonsPane); + //取消 + addCancelButton(buttonsPane); + + this.getRootPane().setDefaultButton(okButton); + + return controlPane; + } + + protected void addCustomButton(JPanel buttonsPane){ + + } + + private void addCancelButton(JPanel buttonsPane) { + cancelButton = new UIButton(Inter.getLocText("Cancel")); + cancelButton.setName(CANCEL_BUTTON); + cancelButton.setMnemonic('C'); + buttonsPane.add(cancelButton); + cancelButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + doCancel(); + } + }); + } + + private void addOkButton(JPanel buttonsPane) { + okButton = new UIButton(Inter.getLocText("OK")); + okButton.setName(OK_BUTTON); + okButton.setMnemonic('O'); + buttonsPane.add(okButton); + okButton.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + doOK(); + } + }); + } + + + /** + * 添加监听器 + * + * @param l 监听器 + * + */ + public void addDialogActionListener(DialogActionListener l) { + listeners.add(l); + } + + /** + * 清除所有监听器 + * + */ + public void clearDialogActionListeners() { + listeners.clear(); + } + + /** + * 确定操作 + * + */ + public void doOK() { + try { + checkValid(); + } catch (Exception exp) { + JOptionPane.showMessageDialog(this, exp.getMessage()); + return; + } + + synchronized (this) { + // dialogExit();august:怎么能这儿exit呢,dispose了就是释放了对话框的线程锁了, + // 那么下面的doOk和原来的派遣线程就会竞争执行,万一派遣线程依赖doOk的结果、而doOK又是后执行的,那么就会出错了 + // 这Bug实在是太隐蔽了! + isDoOKSucceed = true; + for (DialogActionListener l : listeners) { + try { + l.doOk(); + } catch (RuntimeException e) { + isDoOKSucceed = false; + FRContext.getLogger().error(e.getMessage()); + } + } + if (isDoOKSucceed) { + dialogExit(); + } + } + } + + /** + * 取消操作 + * + */ + public void doCancel() { + + for (DialogActionListener l : listeners) { + l.doCancel(); + } + dialogExit(); + } + + /** + * Dialog exit. + */ + protected void dialogExit() { + this.setVisible(false); + this.dispose(); + } + + protected void applyClosingAction() { + addWindowListener(new WindowAdapter() { + + public void windowClosing(WindowEvent e) { + doCancel(); + } + }); + } + + protected void applyEscapeAction() { + // default pane. + JPanel defaultPane = (JPanel) this.getContentPane(); + + // esp. + InputMap inputMapAncestor = defaultPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + ActionMap actionMap = defaultPane.getActionMap(); + + // transfer focus to CurrentEditor + inputMapAncestor.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dialogExit"); + actionMap.put("dialogExit", new AbstractAction() { + + public void actionPerformed(ActionEvent evt) { + doCancel(); + } + }); + } + + /** + * 检测结果是否合法 + * + */ + public abstract void checkValid() throws Exception; + + public void setButtonEnabled(boolean b) { + this.okButton.setEnabled(b); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/dialog/package.html b/designer_base/src/com/fr/design/dialog/package.html new file mode 100644 index 0000000000..77262d5417 --- /dev/null +++ b/designer_base/src/com/fr/design/dialog/package.html @@ -0,0 +1,8 @@ + + +Defined some dialogs that can be used in your applications of applets, For example: +PageSetupDialog({@link com.fr.dialog.PageSetupDialog PageSetupDialog}), +StyleDialog({@link com.fr.dialog.core.ColorSelectBox ColorSelectBox}), +CellBorderDialog({@link com.fr.dialog.CellBorderDialog CellBorderDialog}).]!> + + \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/ValueEditorPane.java b/designer_base/src/com/fr/design/editor/ValueEditorPane.java new file mode 100644 index 0000000000..5efaf5d576 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/ValueEditorPane.java @@ -0,0 +1,400 @@ +package com.fr.design.editor; + +import com.fr.base.Formula; +import com.fr.design.DesignerEnvManager; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.imenu.UIMenuItem; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.editor.ColumnNameEditor; +import com.fr.design.editor.editor.Editor; +import com.fr.design.editor.editor.TextEditor; +import com.fr.design.editor.editor.XMLANameEditor; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ValueEditorPane extends BasicPane implements UIObserver, GlobalNameObserver { + + private Editor[] cards; + + private Editor currentEditor; + + private UIButton arrowButton; + private JPopupMenu menu; + private JPanel centerPane; + + private Object value; + + private GlobalNameListener globalNameListener = null; + private UIObserverListener uiObserverListener = null; + + public ValueEditorPane(Editor[] cards) { + this(cards, null, null); + } + + public ValueEditorPane(Editor[] cards, String popupName, String textEditorValue) { + initComponents(cards, popupName, textEditorValue, 200); + } + + public ValueEditorPane(Editor[] cards, String popupName, String textEditorValue, int centerPaneWidth) { + initComponents(cards, popupName, textEditorValue, centerPaneWidth); + } + + private void initComponents(final Editor[] cards, String popupName, String textEditorValue, int centerPaneWidth) { + + this.cards = cards; + + // Frank:布局 + this.setLayout(new BorderLayout(2, 0)); + centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + arrowButton = new UIButton(); + arrowButton.set4ToolbarButton(); + setCurrentEditor(0); + centerPane.setPreferredSize(new Dimension(centerPaneWidth, centerPane.getPreferredSize().height)); + arrowButton.setPreferredSize(new Dimension(20, centerPane.getPreferredSize().height)); + final Color beforeColor = arrowButton.getBackground(); + menu = createPopMenu(); + + arrowButton.addMouseListener(new MouseAdapter() { + public void mouseEntered(MouseEvent a) { + if (cards != null && cards.length > 1) { + arrowButton.setBackground(new Color(228, 246, 255)); + arrowButton.repaint(); + } + } + + public void mouseExited(MouseEvent a) { + arrowButton.setBackground(beforeColor); + arrowButton.setBorder(null); + } + }); + arrowButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (cards != null && cards.length > 1) { // 如果只有“列”的话,就不需要弹出菜单了 + Rectangle re = centerPane.getBounds(); + menu.setPopupSize(re.width + arrowButton.getWidth(), menu.getPreferredSize().height); + menu.show(centerPane, -arrowButton.getWidth(), re.height); + } + } + }); + + this.add(centerPane, BorderLayout.CENTER); + if (cards.length > 1) { + this.add(arrowButton, BorderLayout.WEST); + } + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Values-Editor"); + } + + public Editor getCurrentEditor() { + return currentEditor; + } + + public void setCurrentEditor(int i) { + this.add(arrowButton, BorderLayout.WEST); + currentEditor = this.cards[i]; + centerPane.removeAll(); + centerPane.add(currentEditor); + centerPane.validate(); + centerPane.repaint(); + arrowButton.setIcon(cards[i].getIcon()); + if (this.cards.length == 1) { + this.remove(arrowButton); + } + } + + public void setCurrentEditor(Class editorClass) { + for (int i = 0; i < cards.length; i++) { + if (cards[i].getClass() == editorClass) { + setCurrentEditor(i); + break; + } + } + } + + + private JPopupMenu createPopMenu() { + JPopupMenu scate = new JPopupMenu(); + + if (this.cards == null) { + return scate; + } + + for (int i = 0; i < this.cards.length; i++) { + UIMenuItem item = new UIMenuItem(cards[i].getName()); + final int j = i; + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (globalNameListener != null) { + globalNameListener.setGlobalName(Inter.getLocText("CellWrite-InsertRow_Policy")); + } + Object oldValue = currentEditor.getValue(); + setCurrentEditor(j); + currentEditor.selected(); + value = currentEditor.getValue(); + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + + ValueEditorPane.this.firePropertyChange("value", oldValue, value); + } + }); + scate.add(item); + if (i < cards.length - 1) { + scate.addSeparator(); + } + } + return scate; + } + + public void populate(Object object) { + for (int i = 0; i < cards.length; i++) { + if (cards[i].accept(object)) { + setCardValue(i,object); + break; + } + } + } + + public void populate(Object object,String name) { + for (int i = 0; i < cards.length; i++) { + if (cards[i].accept(object) && ComparatorUtils.equals(cards[i].getName(),name)) { + setCardValue(i,object); + break; + } + } + } + + private void setCardValue(int i,Object object){ + setCurrentEditor(i); + cards[i].setValue(object); + // kunsnat: bug7861 所有的Editor值都要跟随改变, 因为populate的editor 从"" + // 一定是最后的Editor哦. + for (int j = 0; j < cards.length; j++) { + if (i == j) { + continue; + } + this.cards[j].setValue(null); + } + } + + public Object update() { + String name = currentEditor.getName(); + Object columnIndex = currentEditor.getValue(); + //bug86542,这边为啥要new一个公式出来,只保留content,其他属性全不要了? +// if (ComparatorUtils.equals(name, Inter.getLocText("Formula"))) { +// columnIndex = new Formula(columnIndex == null ? "" : columnIndex.toString()); +// } + + return columnIndex; + } + + public Object update(String makeAdiff) { + String name = currentEditor.getName(); + Object columnIndex = currentEditor.getValue(); + Object columnName = StringUtils.EMPTY; + + if (ComparatorUtils.equals(name, Inter.getLocText("FR-Designer_Formula"))) { + columnIndex = new Formula(columnIndex == null ? "" : columnIndex.toString()); + } + + if (currentEditor instanceof ColumnNameEditor) { + columnName = ((ColumnNameEditor) currentEditor).getColumnName(); + } + + return new Object[]{columnIndex, columnName}; + } + + public Object update(boolean isXMLA) { + String name = currentEditor.getName(); + Object columnIndex = currentEditor.getValue(); + Object columnName = StringUtils.EMPTY; + + if (ComparatorUtils.equals(name, Inter.getLocText("FR-Designer_Formula"))) { + columnIndex = new Formula(columnIndex == null ? "" : columnIndex.toString()); + } + + if (isXMLA) { + columnName = ((XMLANameEditor) currentEditor).getColumnName(); + } + + return new Object[]{columnIndex, columnName}; + } + + public void setEditors(Editor[] editors, Object obj) { + this.cards = editors; + this.populate(obj); + } + + /** + * 检查是否有效 + * + * @throws Exception 异常 + */ + public void checkValid() throws Exception { + if (!(currentEditor instanceof TextEditor)) { + return; + } + + int i; + boolean containFormulaType = false; + for (i = 0; i < cards.length; i++) { + if (ComparatorUtils.equals(cards[i].getName(), Inter.getLocText("FR-Engine_Parameter-Formula"))) { + containFormulaType = true; + break; + } + } + if (!containFormulaType) { + return; + } + + final int j = i; + + if (!(currentEditor instanceof TextEditor)) { + return; + } + String string = (String) currentEditor.getValue(); + if (isFormula(string)) { + DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager(); + if (designerEnvManager.isSupportStringToFormula()) { + if (!designerEnvManager.isDefaultStringToFormula()) { + int returnValue = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("FR-Designer_Edit_String_To_Formula") + + "?", Inter.getLocText("FR-Designer_Tooltips"), JOptionPane.YES_NO_OPTION); + if (returnValue == JOptionPane.OK_OPTION) { + + setCurrentEditor(j); + Formula formula = new Formula(string); + currentEditor.setValue(formula); + } + } else { + setCurrentEditor(j); + Formula formula = new Formula(string); + currentEditor.setValue(formula); + } + } + } + + } + + private boolean isFormula(String string) { + return StringUtils.isNotBlank(string) && (string.length() > 0 && string.charAt(0) == '='); + } + + @Override + public void setEnabled(boolean enabled) { + arrowButton.setEnabled(enabled); + for (Editor card : cards) { + card.setEnabled(enabled); + } + } + + /** + * 重置组件 + */ + public void resetComponets() { + for (Editor card : cards) { + card.reset(); + } + } + + /** + * 清除组件数据 + */ + public void clearComponentsData() { + for (Editor card : cards) { + card.clearData(); + } + } + + public Editor[] getCards() { + return this.cards; + } + + public JPopupMenu getMenu() { + return this.menu; + } + + + /** + * 注册全局名字监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 是否对名字listener监听器做出响应 + * + * @return 如果要做出响应,则返回true + */ + public boolean shouldResponseNameListener() { + return false; + } + + public void setGlobalName(String name) { + for (Editor card : cards) { + setComponentGlobalName(card, name); + } + } + + private void setComponentGlobalName(Container card, String name) { + for (int i = 0, len = card.getComponentCount(); i < len; i++) { + Component component = card.getComponent(i); + if (component instanceof GlobalNameObserver) { + ((GlobalNameObserver) component).setGlobalName(name); + } else { + setComponentGlobalName((Container) component, name); + } + } + } + + /** + * 给组件登记一个观察者监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + for (Editor card : cards) { + doLoop(card, listener); + } + } + + private void doLoop(Container card, UIObserverListener listener) { + for (int i = 0, len = card.getComponentCount(); i < len; i++) { + Component component = card.getComponent(i); + if (component instanceof UIObserver) { + ((UIObserver) component).registerChangeListener(listener); + } else { + doLoop((Container) component, listener); + } + } + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/ValueEditorPaneFactory.java b/designer_base/src/com/fr/design/editor/ValueEditorPaneFactory.java new file mode 100644 index 0000000000..29ee9e60a6 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/ValueEditorPaneFactory.java @@ -0,0 +1,634 @@ +package com.fr.design.editor; + +import com.fr.base.Formula; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.editor.editor.*; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class ValueEditorPaneFactory { + + /** + * 创建带编辑器的ValueEditorPane + * + * @param editors 自定义的编辑器 + * @return 返回pane + */ + public static ValueEditorPane createValueEditorPane(Editor[] editors) { + return createValueEditorPane(editors, StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 创建编辑器 名称 弹出的ValueEditorPane + * + * @param editors 编辑器 + * @param popupName 弹出的名字 + * @param textEditorValue 值 + * @return 返回pane + */ + public static ValueEditorPane createValueEditorPane(Editor[] editors, String popupName, String textEditorValue) { + return new ValueEditorPane(editors, popupName, textEditorValue); + } + + /** + * 创建编辑器 名称 弹出的ValueEditorPane + * + * @param editors 编辑器 + * @param popupName 弹出的名字 + * @param textEditorValue 值 + * @param editor_center_width 编辑器主体的宽度 + * @return 返回pane + */ + public static ValueEditorPane createValueEditorPane(Editor[] editors, String popupName, String textEditorValue, int editor_center_width) { + return new ValueEditorPane(editors, popupName, textEditorValue, editor_center_width); + } + + /** + * 创建基本的值编辑器面板 + * + * @return 返回值编辑器面板 + */ + public static ValueEditorPane createBasicValueEditorPane() { + return createValueEditorPane(basicEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 创建公式编辑器面板 + * + * @return 返回公式编辑器面板 + */ + public static ValueEditorPane createFormulaValueEditorPane() { + return createValueEditorPane(new Editor[]{new FormulaEditor(Inter.getLocText("Parameter-Formula"))}, + StringUtils.EMPTY, StringUtils.EMPTY); + } + /** + * 创建基本的值编辑器面板 + * + * @param editor_center_width 指定值编辑器的主体宽度 + * @return 返回值编辑器面板 + */ + public static ValueEditorPane createBasicValueEditorPane(int editor_center_width) { + return createValueEditorPane(basicEditors(), StringUtils.EMPTY, StringUtils.EMPTY, editor_center_width); + } + + /** + * Process用的editorPane + * + * @return 值编辑器面板 + */ + public static ValueEditorPane createFormEditorPane() { + return createValueEditorPane(formEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * StoreProced用的EditorPane + * + * @return 值编辑器面板 + */ + public static ValueEditorPane createStoreProcedValueEditorPane() { + return createValueEditorPane(StoreProcedureEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 扩展的ValueEditorPane + * + * @return 值编辑器面板 + */ + public static ValueEditorPane createExtendedValueEditorPane() { + return createValueEditorPane(extendedEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * URL使用的ValueEditorPane + * + * @param popupName 弹出的名字 + * @param textEditorValue 编辑器值 + * @return 值编辑器返回 + */ + public static ValueEditorPane createURLValueEditorPane(String popupName, String textEditorValue) { + return createValueEditorPane(URLEditors(popupName, textEditorValue), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 创建日期的ValueEditorPane + * + * @param popupName 名字 + * @param textEditorValue 值 + * @return 值编辑器面板 + */ + public static ValueEditorPane createDateValueEditorPane(String popupName, String textEditorValue) { + return createValueEditorPane(dateEditors(popupName, textEditorValue), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 带有所有编辑器的ValueEditorPane + * + * @return 值编辑器面板 + */ + public static ValueEditorPane createAllValueEditorPane() { + return createValueEditorPane(allEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 创建不带公式面板的pane + * @return 编辑器面板 + */ + public static ValueEditorPane createBasicEditorWithoutFormulaPane(){ + return createValueEditorPane(basicEditorsWithoutFormula(), StringUtils.EMPTY, StringUtils.EMPTY); + } + /** + * 创建NoCRNoColumn + * + * @return 值编辑器 + */ + public static ValueEditorPane createNoCRNoColumnValueEditorPane() { + return createValueEditorPane(noCRnoColumnEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 创建数值编辑器 + * @return 值编辑器 + */ + public static ValueEditorPane createNumberValueEditorPane(){ + return createValueEditorPane(numberEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 创建日期编辑器 + * @return 值编辑器 + */ + public static ValueEditorPane createDateValueEditorPane(){ + return createValueEditorPane(dateEditors(), StringUtils.EMPTY, StringUtils.EMPTY); + } + /** + * 根据参数paraUseType 创建编辑器类型. + * + * @param paraUseType 参数类型 + * @return 值编辑器 + */ + public static ValueEditorPane createVallueEditorPaneWithUseType(int paraUseType) { + if (paraUseType == ParameterTableModel.NO_CHART_USE) { + return createBasicValueEditorPane(); + } else if (paraUseType == ParameterTableModel.FORM_NORMAL_USE) { + return createFormEditorPane(); + } else { + return createChartHotValueEditorPane(paraUseType); + } + } + + /** + * 图表用的参数编辑器的ValueEditorPane + * + * @param paraUseType 参数类型 + * @return 值编辑器 + */ + public static ValueEditorPane createChartHotValueEditorPane(int paraUseType) { + return createValueEditorPane(chartHotEditors(paraUseType), StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 基础的一些ValueEditorPane所用到的Editors + * + * @return 值编辑器 + */ + public static Editor[] basicEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor + }; + } + + /** + * 表单的一些编辑器. + * + * @return 值编辑器 + */ + public static Editor[] formEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor, + new WidgetNameEditor(Inter.getLocText("Widget")) + }; + } + + /** + * 扩展单元格的一些编辑器 + * + * @return 值编辑器 + */ + public static Editor[] extendedEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor, + new ParameterEditor(), + new ColumnRowEditor(Inter.getLocText("Cell")) + }; + } + + /** + * 带单元格组的编辑器 + * @return 值编辑器 + */ + public static Editor[] extendedCellGroupEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor, + new ParameterEditor(), + new ColumnRowEditor(Inter.getLocText("Cell")), + new ColumnRowGroupEditor(Inter.getLocText("Cell_Group")) + }; + } + + /** + * 只有单元格和单元格组的编辑器 + * @return 编辑器b + */ + public static Editor[] cellGroupEditor() { + return new Editor[] { + new ColumnRowEditor(Inter.getLocText("Cell")), + new ColumnRowGroupEditor(Inter.getLocText("Cell_Group")) + }; + } + + /** + * URL的一些编辑器. + * + * @param popupName 名字 + * @param textEditorValue 值 + * @return 值编辑器 + */ + public static Editor[] URLEditors(String popupName, String textEditorValue) { + return new Editor[]{ + new NoneEditor(textEditorValue, StringUtils.isEmpty(popupName) ? Inter.getLocText("None") : popupName), + new TextEditor() + }; + } + + /** + * 日期类型的一些编辑器 + * + * @param popupName 名字 + * @param textEditorValue 值 + * @return 值编辑器 + */ + public static Editor[] dateEditors(String popupName, String textEditorValue) { + return new Editor[]{ + new NoneEditor(textEditorValue, StringUtils.isEmpty(popupName) ? Inter.getLocText("None") : popupName), + new DateEditor(true, Inter.getLocText("Date")), + new FormulaEditor(Inter.getLocText("Parameter-Formula")) + }; + } + + /** + * 所有类型的编辑器 + * + * @return 值编辑器 + */ + public static Editor[] allEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); +// formulaEditor.setEnabled(true); + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor, + new ParameterEditor(), + new ColumnRowEditor(Inter.getLocText("Cell")), + new ColumnSelectedEditor(), + //23328 allEditors中删除控件选项 +// new WidgetNameEditor(Inter.getLocText("Widget")) + }; + } + + /** + * 不带公式编辑器 + * @return 编辑器不带公式 + */ + public static Editor[] basicEditorsWithoutFormula(){ + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + }; + } + + /** + * noCRnoColumn编辑器 + * + * @return 编辑器 + */ + public static Editor[] noCRnoColumnEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor, + new ParameterEditor(), + }; + } + + /** + * 数值编辑器 + * @return 编辑器 + */ + public static Editor[] numberEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new IntegerEditor(), + new DoubleEditor(), + formulaEditor, + new ParameterEditor(), + }; + } + + /** + * 日期编辑器 + * @return 编辑器 + */ + public static Editor[] dateEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + return new Editor[]{ + new DateEditor(true, Inter.getLocText("Date")), + formulaEditor, + new ParameterEditor(), + }; + } + + /** + * 存储的一些编辑器 + * + * @return 存储过程的编辑器 + */ + public static Editor[] StoreProcedureEditors() { + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + formulaEditor.setEnabled(true); + return new Editor[]{ + new CursorEditor(), + new TextEditor(), + new IntegerEditor(), + new DoubleEditor(), + new DateEditor(true, Inter.getLocText("Date")), + new BooleanEditor(), + formulaEditor + }; + } + + /** + * 图表热点的一些编辑器 + * + * @param paraUseType 参数类型 + * @return 值编辑器 + */ + public static Editor[] chartHotEditors(int paraUseType) { + List list = createEditors4Chart(paraUseType); + + list.add(new TextEditor()); + list.add(new IntegerEditor()); + list.add(new DoubleEditor()); + list.add(new DateEditor(true, Inter.getLocText("Date"))); + list.add(new BooleanEditor()); + + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + formulaEditor.setEnabled(true); + list.add(formulaEditor); + + return list.toArray(new Editor[list.size()]); + } + + /** + * 为图表创建编辑器. + * + * @param paraUseType 参数类型 + * @return 值编辑器 + */ + private static List createEditors4Chart(int paraUseType) { + if(paraUseType == ParameterTableModel.CHART_PIE_USE) { + return getPieEditor(); + } else if(paraUseType == ParameterTableModel.CHART_MAP_USE) { + return getMapEditor(); + } else if(paraUseType == ParameterTableModel.CHART_GIS_USE) { + return getGisEditor(); + } else if(paraUseType == ParameterTableModel.CHART__XY_USE) { + return getXYEditor(); + } else if(paraUseType == ParameterTableModel.CHART_BUBBLE_USE) { + return getBubbbleEdtor(); + } else if(paraUseType == ParameterTableModel.CHART_NO_USE) { + return getChartNoUseEditor(); + } else if(paraUseType == ParameterTableModel.CHART_METER_USE) { + return getMeterEditor(); + } else if(paraUseType == ParameterTableModel.CHART_STOCK_USE) { + return getStockEditor(); + } else if(paraUseType == ParameterTableModel.CHART_GANTT_USE) { + return getGanttEditor(); + } else if(paraUseType == ParameterTableModel.FORM_ELEMENTCASE_USE) { + return getFormElementCaseEditor(); + } else if(paraUseType == ParameterTableModel.FORM_CHART_USE) { + return getFormChartEditor(); + } + else { + return getChartEditor(); + } + } + + private static List getMeterEditor() { + ConstantsEditor cate = new ConstantsEditor(Inter.getLocText("CategoryName"), new Formula("CATEGORY")); + cate.setEnabled(false); + ConstantsEditor value = new ConstantsEditor(Inter.getLocText("Chart-Series_Value"), new Formula("VALUE")); + value.setEnabled(false); + + List lists = new ArrayList(); + lists.add(cate); + lists.add(value); + + return lists; + } + + private static List getPieEditor() { + ConstantsEditor series = new ConstantsEditor(Inter.getLocText("ChartF-Series_Name"), new Formula("SERIES")); + series.setEnabled(false); + ConstantsEditor value = new ConstantsEditor(Inter.getLocText("Chart-Series_Value"), new Formula("VALUE")); + value.setEnabled(false); + + List lists = new ArrayList(); + lists.add(series); + lists.add(value); + return lists; + } + + private static List getGisEditor() { + ConstantsEditor areaValue = new ConstantsEditor(Inter.getLocText("Area_Value"), new Formula("AREA_VALUE")); + areaValue.setEnabled(false); + ConstantsEditor chartAddress = new ConstantsEditor(Inter.getLocText("Chart-Address"), new Formula("ADDRESS")); + chartAddress.setEnabled(false); + ConstantsEditor addressName = new ConstantsEditor(Inter.getLocText("Chart-Address-Name"), new Formula("ADDRESS_NAME")); + addressName.setEnabled(false); + + List lists = new ArrayList(); + lists.add(chartAddress); + lists.add(addressName); + lists.add(areaValue); + + return lists; + } + + private static List getGanttEditor() { + ConstantsEditor projectid = new ConstantsEditor(Inter.getLocText("Chart_ProjectID"), new Formula("PROJECTID")); + projectid.setEnabled(false); + ConstantsEditor step = new ConstantsEditor(Inter.getLocText("Chart_Step_Name"), new Formula("STEP")); + step.setEnabled(false); + + List lists = new ArrayList(); + lists.add(projectid); + lists.add(step); + + return lists; + } + + private static List getXYEditor() { + ConstantsEditor series = new ConstantsEditor(Inter.getLocText("ChartF-Series_Name"), new Formula("SERIES")); + series.setEnabled(false); + ConstantsEditor value = new ConstantsEditor(Inter.getLocText("Chart-Series_Value"), new Formula("VALUE")); + value.setEnabled(false); + + List lists = new ArrayList(); + lists.add(series); + lists.add(value); + + return lists; + } + + private static List getStockEditor() { + List lists = new ArrayList(); + + return lists; + } + + private static List getBubbbleEdtor() { + ConstantsEditor series = new ConstantsEditor(Inter.getLocText("ChartF-Series_Name"), new Formula("SERIES")); + series.setEnabled(false); + ConstantsEditor value = new ConstantsEditor(Inter.getLocText("Chart-Series_Value"), new Formula("VALUE")); + value.setEnabled(false); + + List lists = new ArrayList(); + lists.add(series); + lists.add(value); + + return lists; + } + + private static List getChartNoUseEditor() { + List lists = new ArrayList(); + + return lists; + } + + private static List getMapEditor() { + ConstantsEditor areaValue = new ConstantsEditor(Inter.getLocText("Area_Value"), new Formula("AREA_VALUE")); + areaValue.setEnabled(false); + ConstantsEditor areaName = new ConstantsEditor(Inter.getLocText("Area_Name"), new Formula("AREA_NAME")); + areaName.setEnabled(false); + + List lists = new ArrayList(); + lists.add(areaName); + lists.add(areaValue); + + return lists; + } + + private static List getChartEditor() { + ConstantsEditor cate = new ConstantsEditor(Inter.getLocText("CategoryName"), new Formula("CATEGORY")); + cate.setEnabled(false); + ConstantsEditor series = new ConstantsEditor(Inter.getLocText("ChartF-Series_Name"), new Formula("SERIES")); + series.setEnabled(false); + ConstantsEditor value = new ConstantsEditor(Inter.getLocText("Chart-Series_Value"), new Formula("VALUE")); + value.setEnabled(false); + + List lists = new ArrayList(); + lists.add(cate); + lists.add(series); + lists.add(value); + + return lists; + } + + private static List getFormElementCaseEditor() { + + List lists = new ArrayList(); + + return lists; + } + + private static List getFormChartEditor() { + ConstantsEditor cate = new ConstantsEditor(Inter.getLocText("CategoryName"), new Formula("CATEGORY")); + cate.setEnabled(false); + ConstantsEditor series = new ConstantsEditor(Inter.getLocText("ChartF-Series_Name"), new Formula("SERIES")); + series.setEnabled(false); + ConstantsEditor value = new ConstantsEditor(Inter.getLocText("Chart-Series_Value"), new Formula("VALUE")); + value.setEnabled(false); + + List lists = new ArrayList(); + lists.add(cate); + lists.add(series); + lists.add(value); + + return lists; + } + + /** + * 产生一个实际值和显示值的面板 + * + * @param keyColumnPane 实际值 + * @param valueDictPane 显示值 + * @return 产生一个实际值和显示值的面板 + */ + public static JPanel createKeyAndValuePane(ValueEditorPane keyColumnPane, ValueEditorPane valueDictPane) { + JPanel pane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + + JPanel paneLeft = FRGUIPaneFactory.createBorderLayout_S_Pane(); + pane.add(paneLeft); + paneLeft.add(new UILabel(" " + Inter.getLocText("Actual_Value") + ":"), BorderLayout.NORTH); + paneLeft.add(keyColumnPane, BorderLayout.CENTER); + + JPanel paneRight = FRGUIPaneFactory.createBorderLayout_S_Pane(); + pane.add(paneRight); + paneRight.add(new UILabel(" " + Inter.getLocText("Display_Value") + ":"), BorderLayout.NORTH); + + paneRight.add(valueDictPane, BorderLayout.CENTER); + + return pane; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/BooleanEditor.java b/designer_base/src/com/fr/design/editor/editor/BooleanEditor.java new file mode 100644 index 0000000000..81673f4c06 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/BooleanEditor.java @@ -0,0 +1,113 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +/** + * CellEditor used to edit Boolean object. + * + * @editor zhou + * @since 2012-3-29下午6:01:09 + */ +public class BooleanEditor extends Editor { + + private UICheckBox booleanCheckBox; // boolean checkbox + + /** + * Constructor. + */ + public BooleanEditor() { + this(new Boolean(true)); + } + + public BooleanEditor(boolean b) { + this(new Boolean(b)); + } + + /** + * Constructor. + */ + + public BooleanEditor(Boolean value) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + booleanCheckBox = new UICheckBox("true"); + this.add(booleanCheckBox, BorderLayout.CENTER); + this.setValue(value); + this.setName(Inter.getLocText("Parameter-Boolean")); + booleanCheckBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireStateChanged(); + } + }); + } + + public JComponent getEditComp() { + return booleanCheckBox; + } + + /** + * Return the value of the CellEditor. + */ + @Override + public Boolean getValue() { + return new Boolean(this.booleanCheckBox.isSelected()); + } + + /** + * Set the value to the CellEditor. + */ + @Override + public void setValue(Boolean value) { + // populate data to UI + if (value == null) { + value = true; + } + this.booleanCheckBox.setSelected(value.booleanValue()); + } + + /** + * Sets whether or not this component is enabled. + */ + @Override + public void setEnabled(boolean enabled) { + this.booleanCheckBox.setEnabled(enabled); + } + + /** + * Request focus + */ + @Override + public void requestFocus() { + this.booleanCheckBox.requestFocus(); + } + + /** + * Fire editing stopped listeners. + */ + @Override + protected void fireEditingStopped() { + // populate UI to data. + this.setValue(new Boolean(this.booleanCheckBox.isSelected())); + + super.fireEditingStopped(); + } + + public String getIconName() { + return "type_bool"; + } + + @Override + public boolean accept(Object object) { + return object instanceof Boolean; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ColumnIndexEditor.java b/designer_base/src/com/fr/design/editor/editor/ColumnIndexEditor.java new file mode 100644 index 0000000000..29cdb7cd97 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ColumnIndexEditor.java @@ -0,0 +1,110 @@ +package com.fr.design.editor.editor; + +import com.fr.design.gui.icombobox.IntComboBox; +import com.fr.general.Inter; + +import java.awt.*; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; + +/** + * 列序号编辑器:里面是一排连续的整数(0-value) + * + * @author zhou + * @since 2012-6-1下午2:24:04 + */ +public class ColumnIndexEditor extends Editor { + protected IntComboBox valueColumnIndexComboBox; + + public ColumnIndexEditor() { + this(0); + } + + /** + * 默认名字是“列序号”,也可以通过第二个构造函数改变 + * + * @param value + */ + public ColumnIndexEditor(int value) { + this(value, Inter.getLocText("Datasource-Column_Index")); + } + + public ColumnIndexEditor(int value, String name) { + this.setLayout(new BorderLayout(0, 0)); + valueColumnIndexComboBox = new IntComboBox(); + for (int i = 1; i <= value; i++) { + valueColumnIndexComboBox.addItem(new Integer(i)); + } + + if (value > 0) { + valueColumnIndexComboBox.setSelectedInt(1); + } + this.add(valueColumnIndexComboBox, BorderLayout.CENTER); + this.setName(name); + valueColumnIndexComboBox.setBorder(null); + + } + + @Override + public Integer getValue() { + return valueColumnIndexComboBox.getSelectedInt(); + } + + @Override + public void setValue(Object value) { + valueColumnIndexComboBox.setSelectedInt(value == null ? 0 : Integer.parseInt(value.toString())); + } + + public String getIconName() { + return "ds_column_index"; + } + + /** + * object参数是否是Integer + * + * @param object 传进来用于判断的参数 + * @return 返回是否是Index + */ + public boolean accept(Object object) { + return object instanceof Integer; + } + + /** + * 增加一个ItemListener + * + * @param l 用于增加的Listener + */ + public void addItemListener(ItemListener l) { + valueColumnIndexComboBox.addItemListener(l); + } + + /** + * 增加一个ActionListener + * + * @param l 用于增加的Listener + */ + public void addActionListener(ActionListener l){ + valueColumnIndexComboBox.addActionListener(l); + } + + /** + * 重置 + */ + public void reset() { + valueColumnIndexComboBox.setSelectedIndex(-1); + } + + /** + * 清除所有项 + */ + public void clearData() { + valueColumnIndexComboBox.removeAllItems(); + } + + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + valueColumnIndexComboBox.setEnabled(enabled); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ColumnNameEditor.java b/designer_base/src/com/fr/design/editor/editor/ColumnNameEditor.java new file mode 100644 index 0000000000..3b3e10e312 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ColumnNameEditor.java @@ -0,0 +1,79 @@ +package com.fr.design.editor.editor; + +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; + +/** + * 列编辑器,里面是列名 + * + * @author zhou + * @since 2012-6-1下午2:25:16 + */ +public class ColumnNameEditor extends ColumnIndexEditor { + + private String[] columnNames; + + public ColumnNameEditor() { + this(ArrayUtils.EMPTY_STRING_ARRAY); + } + + public ColumnNameEditor(String[] columnNames) { + this(columnNames, Inter.getLocText("ColumnName")); + } + + public ColumnNameEditor(final String[] columnNames, String name) { + super(columnNames.length, name); + this.columnNames = columnNames; + valueColumnIndexComboBox.setRenderer(new UIComboBoxRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value == null) { + this.setText(""); + } else { + this.setText(columnNames[((Integer) value).intValue() - 1]); + } + + return this; + } + }); + } + + @Override + public void setValue(Object value) { + for (int i = 0; i < columnNames.length; i++) { + if (columnNames[i].equalsIgnoreCase(String.valueOf(value))) { + super.setValue(i + 1); + return; + } + } + + super.reset(); + } + + @Override + public boolean accept(Object object) { + return object instanceof String; + } + + + public String getColumnName() { + int index = ((Integer) this.getValue()).intValue() - 1; + return getColumnNameAtIndex(index); + } + + public String getColumnNameAtIndex(int index) { + return index >= 0 && columnNames.length > index ? columnNames[index] : StringUtils.EMPTY; + } + + public String getIconName() { + return "ds_column_name"; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ColumnRowEditor.java b/designer_base/src/com/fr/design/editor/editor/ColumnRowEditor.java new file mode 100644 index 0000000000..7c90d3d9a4 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ColumnRowEditor.java @@ -0,0 +1,74 @@ +package com.fr.design.editor.editor; + +import com.fr.design.gui.columnrow.ColumnRowPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.ColumnRow; + +import java.awt.*; + +/** + * the editor to edit ColumnRow + * + * @editor zhou + * @since 2012-3-29下午6:01:37 + */ +public class ColumnRowEditor extends Editor { + + private ColumnRowPane crPane; + + public ColumnRowEditor() { + this(""); + } + + public ColumnRowEditor(String name) { + this(null, name); + } + + + public ColumnRowEditor(ColumnRow value) { + this(value, ""); + } + + public ColumnRowEditor(ColumnRow value, String name) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + crPane = new ColumnRowPane(); + this.add(crPane, BorderLayout.CENTER); + this.setValue(value); + this.setName(name); + } + + @Override + public ColumnRow getValue() { + return this.crPane.update(); + } + + @Override + public void setValue(ColumnRow value) { + if (value == null) { + value = ColumnRow.valueOf(0, 0); + } + + this.crPane.populate(value); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + this.crPane.setEnabled(enabled); + } + + @Override + public void requestFocus() { + this.crPane.requestFocus(); + } + + public String getIconName() { + return "cell"; + } + + @Override + public boolean accept(Object object) { + return object instanceof ColumnRow; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ColumnRowGroupEditor.java b/designer_base/src/com/fr/design/editor/editor/ColumnRowGroupEditor.java new file mode 100644 index 0000000000..05329e6a7c --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ColumnRowGroupEditor.java @@ -0,0 +1 @@ +package com.fr.design.editor.editor; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.stable.ColumnRowGroup; import java.awt.*; /** * Author : Shockway * Date: 14-1-10 * Time: 下午1:46 */ public class ColumnRowGroupEditor extends Editor { private UITextField crEditor; public ColumnRowGroupEditor() { this(""); } public ColumnRowGroupEditor(String name) { this(null, name); } public ColumnRowGroupEditor(ColumnRowGroup value) { this(value, ""); } public ColumnRowGroupEditor(ColumnRowGroup value, String name) { this.setLayout(FRGUIPaneFactory.createBorderLayout()); crEditor = new UITextField(); this.add(crEditor, BorderLayout.CENTER); this.setValue(value); this.setName(name); } @Override public ColumnRowGroup getValue() { return new ColumnRowGroup(this.crEditor.getText()); } @Override public void setValue(ColumnRowGroup value) { if (value == null) { this.crEditor.setText(""); } else { this.crEditor.setText(value.toString()); } } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); this.crEditor.setEnabled(enabled); } /** * 获取焦点 */ public void requestFocus() { this.crEditor.requestFocus(); } public String getIconName() { return "cell_group"; } /** * 是否接收/支持这个对象 * @param object 检测对象 * @return 是否支持 */ public boolean accept(Object object) { return object instanceof ColumnRowGroup; } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ColumnSelectedEditor.java b/designer_base/src/com/fr/design/editor/editor/ColumnSelectedEditor.java new file mode 100644 index 0000000000..b3997c1b19 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ColumnSelectedEditor.java @@ -0,0 +1,98 @@ +package com.fr.design.editor.editor; + +import com.fr.design.data.DesignTableDataManager; +import com.fr.data.SimpleDSColumn; +import com.fr.design.data.datapane.TableDataComboBox; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.general.data.TableDataColumn; +import com.fr.stable.StringUtils; + +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.regex.Pattern; + +/** + * 选择数据列编辑器 + * + * @author zhou + * @since 2012-3-29下午6:05:08 + */ +public class ColumnSelectedEditor extends Editor { + TableDataComboBox tableDataComboBox; + private UIComboBox columnNameComboBox; + protected String[] columnNames; + + public ColumnSelectedEditor() { + this.setName(Inter.getLocText(new String[]{"Data", "Columns"})); + this.setLayout(FRGUIPaneFactory.createLeftZeroLayout()); + tableDataComboBox = new TableDataComboBox(DesignTableDataManager.getEditingTableDataSource()); + columnNames = new String[0]; + tableDataComboBox.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + columnNames = tableDataComboBox.getSelectedItem().calculateColumnNameList().toArray(columnNames); + columnNameComboBox.removeAllItems(); + for (int i = 0; i < columnNames.length; i++) { + columnNameComboBox.addItem(columnNames[i]); + } + columnNameComboBox.validate(); + } + }); + columnNameComboBox = new UIComboBox(); + tableDataComboBox.setPreferredSize(new Dimension(82, 20)); + this.add(tableDataComboBox); + columnNameComboBox.setPreferredSize(new Dimension(82, 20)); + this.add(columnNameComboBox); + } + + @Override + public SimpleDSColumn getValue() { + if (this.tableDataComboBox.getSelectedItem() == null && this.columnNameComboBox.getSelectedItem() == null) { + return null; + } + SimpleDSColumn dsColumn = new SimpleDSColumn(); + TableDataWrapper tableDataWrappe = this.tableDataComboBox.getSelectedItem(); + dsColumn.setDsName(tableDataWrappe.getTableDataName()); + TableDataColumn column; + String columnExp = (String) this.columnNameComboBox.getSelectedItem(); + if (StringUtils.isNotBlank(columnExp) && (columnExp.length() > 0 && columnExp.charAt(0) == '#') && !columnExp.endsWith("#")) { + String number = columnExp.substring(1); + Pattern pattern = Pattern.compile("[^\\d]"); + if (pattern.matcher(number).find()) { + column = TableDataColumn.createColumn(columnExp); + } else { + int serialNumber = Integer.parseInt(columnExp.substring(1)); + column = TableDataColumn.createColumn(serialNumber); + } + } else { + column = TableDataColumn.createColumn(columnExp); + } + dsColumn.setColumn(column); + return dsColumn; + } + + public String getIconName() { + return "ds_column"; + } + + @Override + public boolean accept(Object object) { + return object instanceof SimpleDSColumn; + } + + @Override + public void setValue(SimpleDSColumn value) { + if (value == null) { + return; + } else { + tableDataComboBox.setSelectedTableDataByName(value.getDsName()); + columnNameComboBox.setSelectedItem(TableDataColumn.getColumnName(value.getColumn())); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ConstantsEditor.java b/designer_base/src/com/fr/design/editor/editor/ConstantsEditor.java new file mode 100644 index 0000000000..bf4a7f006c --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ConstantsEditor.java @@ -0,0 +1,23 @@ +package com.fr.design.editor.editor; + +import com.fr.base.Formula; + + +public class ConstantsEditor extends FormulaEditor { + + public ConstantsEditor(String name, Formula formula) { + super(name, formula); + } + + protected void showFormulaPane() { + // do nothing 防止修改... + } + + public void setValue(Formula value) { + // do nothing 防止修改... + } + + public boolean accept(Object object) { + return object instanceof Formula && object.equals(this.getValue()); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/CursorEditor.java b/designer_base/src/com/fr/design/editor/editor/CursorEditor.java new file mode 100644 index 0000000000..05267c10c4 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/CursorEditor.java @@ -0,0 +1,42 @@ +package com.fr.design.editor.editor; + +import java.awt.Dimension; + +import com.fr.design.gui.ilable.UILabel; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +//TODO:august what's this? +public class CursorEditor extends Editor { + private UILabel label; + + public CursorEditor(){ + this.setLayout(FRGUIPaneFactory.createCenterFlowLayout()); + label = new UILabel(Inter.getLocText("Cursor")); + this.add(label); + this.setPreferredSize(new Dimension(10,20)); + this.setName(Inter.getLocText("Cursor")); + this.setEnabled(false); + } + + @Override + public CursorEditor getValue() { + return this; + } + + @Override + public String getIconName() { + return "type_cursor"; + } + + @Override + public boolean accept(Object object) { + return object instanceof CursorEditor ; + } + + @Override + public void setValue(CursorEditor value) { + label.setText(Inter.getLocText("Cursor")); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/DateEditor.java b/designer_base/src/com/fr/design/editor/editor/DateEditor.java new file mode 100644 index 0000000000..cef908aa6f --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/DateEditor.java @@ -0,0 +1,179 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import com.fr.base.FRContext; +import com.fr.design.gui.date.UIDatePicker; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.*; + +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * CellEditor used to edit Date object. + * + * @editor zhou + * @since 2012-3-29下午6:03:03 + */ +public class DateEditor extends Editor { + + private UIDatePicker uiDatePicker; + + /** + * Constructor. + */ + public DateEditor() { + this(null); + } + + public DateEditor(boolean es) { + this(null, es); + } + + public DateEditor(boolean es, String name) { + this(null, es, name); + } + + /** + * Constructor. + */ + public DateEditor(Date value) { + this(value, false); + } + + /** + * Constructor. + */ + public DateEditor(Date value, boolean format) { + this(value, format, ""); + } + + public DateEditor(Date value, boolean format, String name) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + uiDatePicker = new UIDatePicker(); + if (format) { + uiDatePicker.setStyle(uiDatePicker.STYLE_CN_DATE); + uiDatePicker.setEditable(false); + } + uiDatePicker.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireStateChanged(); + } + }); + this.uiDatePicker.setFocusTraversalKeysEnabled(false); + this.add(uiDatePicker, BorderLayout.CENTER); + + this.setValue(value); + this.setName(name); + } + + //uidatepicker的setstyle方法不起作用,先粗暴地加个构造方法 + public DateEditor(Date value, boolean format, String name, int dateFormat) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + uiDatePicker = new UIDatePicker(dateFormat); + if (format) { + uiDatePicker.setEditable(false); + } + uiDatePicker.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + fireStateChanged(); + } + }); + this.uiDatePicker.setFocusTraversalKeysEnabled(false); + this.add(uiDatePicker, BorderLayout.CENTER); + + this.setValue(value); + this.setName(name); + } + + + + public JComponent getEditComp() { + return uiDatePicker; + } + + /** + * Return the value of the CellEditor. + */ + @Override + public Date getValue() { + try { + return this.uiDatePicker.getSelectedDate(); + } catch (ParseException parseException) { + FRContext.getLogger().error(parseException.getMessage(), parseException); + return new Date(); + } + } + + /** + * Set the value to the CellEditor. + */ + @Override + public void setValue(Date value) { + // populate data to UI + if (value == null) { +// value = new Date(); + return; + } + + try { + this.uiDatePicker.setSelectedDate(value); + } catch (ParseException parseException) { + FRContext.getLogger().error(parseException.getMessage(), parseException); + } + } + + /** + * Sets whether or not this component is enabled. + */ + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + this.uiDatePicker.setEnabled(enabled); + } + + /** + * ValueEditorPane(无 日期 公式)切换成公式时执行此方法 + */ + public void selected() { + this.uiDatePicker.setSelectedItem(new Date()); + } + + /** + * Request focus + */ + @Override + public void requestFocus() { + this.uiDatePicker.requestFocus(); + } + + public String getIconName() { + return "type_date"; + } + + public void setUIDatePickerStyle(int style){ + this.uiDatePicker.setStyle(style); + } + + public SimpleDateFormat getUIDatePickerFormat(){ + return this.uiDatePicker.getDateFormat(); + } + + @Override + /** + * accept + */ + public boolean accept(Object object) { + return object instanceof Date; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/DoubleEditor.java b/designer_base/src/com/fr/design/editor/editor/DoubleEditor.java new file mode 100644 index 0000000000..a67be50d7a --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/DoubleEditor.java @@ -0,0 +1,46 @@ +package com.fr.design.editor.editor; + +import com.fr.base.Utils; +import com.fr.general.Inter; + +/** + * 双精度编辑器 + * + * @editor zhou + * @since 2012-3-29下午4:51:03 + */ +public class DoubleEditor extends NumberEditor { + + public DoubleEditor() { + this(new Double(0)); + } + + public DoubleEditor(Double value) { + super(value, Inter.getLocText("Parameter-Double")); + } + + @Override + public Double getValue() { + return new Double(this.numberField.getValue()); + } + + @Override + public void setValue(Double value) { + if (value == null) { + value = new Double(0); + } + this.numberField.setInteger(false); + this.numberField.setValue(value.doubleValue()); + oldValue = Utils.objectToString(value); + } + + public String getIconName() { + return "type_double"; + } + + @Override + public boolean accept(Object object) { + return object != null && object instanceof Double; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/Editor.java b/designer_base/src/com/fr/design/editor/editor/Editor.java new file mode 100644 index 0000000000..2834eee924 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/Editor.java @@ -0,0 +1,203 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import com.fr.base.BaseUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * The baics abstract CellEditor. 子类必须确定类型T + * + * @editor zhou + * @since 2012-3-29下午5:08:21 + */ +public abstract class Editor extends JComponent { + private static final long serialVersionUID = 1L; + private String editorName; + + /** + * Return the value of CellEditor. + */ + public abstract T getValue(); + + /** + * Set the value to the CellEditor. + */ + public abstract void setValue(T value); + + public abstract boolean accept(Object object); + + // 约定图片的文件名为this.getName(),处理起来方便些 + // b:这里国际化没有考虑 + public Icon getIcon() { + String iconName = "com/fr/design/images/buttonicon/" + this.getIconName() + ".png"; + try { + return BaseUtils.readIcon(iconName); + } catch (NullPointerException e) { + return null; + } + } + + public String getName() { + return this.editorName; + } + + public String getIconName(){ + return this.editorName; + } + + public void reset() { + + } + + public void clearData() { + + } + + @Override + public void setName(String name) { + this.editorName = name; + } + + /** + * Calls fireEditingStopped. + */ + public void startEditing() { + fireEditingStarted(); + } + + + /** + * Calls fireEditingStopped and returns true. + * + * @return true + */ + public boolean stopEditing() { + fireEditingStopped(); + return true; + } + + /** + * Calls fireEditingCanceled. + */ + public void cancelEditing() { + fireEditingCanceled(); + } + + public void selected() { + + } + + /** + * Adds a CellEditorListener to the listener list. + */ + public void addCellEditorListener(EditorListener cellEditorListener) { + listenerList.add(EditorListener.class, cellEditorListener); + } + + /** + * Removes a CellEditorListener from the listener list. + */ + public void removeCellEditorListener(EditorListener cellEditorListener) { + listenerList.remove(EditorListener.class, cellEditorListener); + } + + /** + * Return all of the CellEditorListeners added or an empty + * array if no listeners have been added + */ + public EditorListener[] getCellEditorListeners() { + return listenerList.getListeners(EditorListener.class); + } + + /** + * Fire editing started listeners. + */ + protected void fireEditingStarted() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == EditorListener.class) { + // Lazily create the event: + if (changeEvent == null) { + changeEvent = new ChangeEvent(this); + } + + ((EditorListener) listeners[i + 1]).editingStarted(changeEvent); + } + } + } + + /** + * Fire editing stopped listeners. + */ + protected void fireEditingStopped() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == EditorListener.class) { + // Lazily create the event: + if (changeEvent == null) { + changeEvent = new ChangeEvent(this); + } + + ((EditorListener) listeners[i + 1]).editingStopped(changeEvent); + } + } + } + + /** + * Fire editing canceled listeners. + */ + protected void fireEditingCanceled() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == EditorListener.class) { + // Lazily create the event: + if (changeEvent == null) { + changeEvent = new ChangeEvent(this); + } + + ((EditorListener) listeners[i + 1]).editingCanceled(changeEvent); + } + } + } + + protected void fireStateChanged() { + Object[] listeners = listenerList.getListenerList(); + + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + // Lazily create the event: + if (changeEvent == null) { + changeEvent = new ChangeEvent(this); + } + + ((ChangeListener) listeners[i + 1]).stateChanged(changeEvent); + } + } + } + + transient private ChangeEvent changeEvent = null; + + public void addChangeListener(ChangeListener changeListener) { + listenerList.add(ChangeListener.class, changeListener); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/EditorListener.java b/designer_base/src/com/fr/design/editor/editor/EditorListener.java new file mode 100644 index 0000000000..55d667e736 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/EditorListener.java @@ -0,0 +1,29 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import java.util.EventListener; + +import javax.swing.event.ChangeEvent; + +/** + * CellEditorListener used for CellEditor start, stop and cancel.. + */ +public interface EditorListener extends EventListener { + + /** + * This tells the listeners the editor has started editing. + */ + public void editingStarted(ChangeEvent evt); + + /** + * This tells the listeners the editor has stopped editing + */ + public void editingStopped(ChangeEvent evt); + + /** + * This tells the listeners the editor has canceled editing + */ + public void editingCanceled(ChangeEvent evt); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/FloatEditor.java b/designer_base/src/com/fr/design/editor/editor/FloatEditor.java new file mode 100644 index 0000000000..4fd9bba775 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/FloatEditor.java @@ -0,0 +1,46 @@ +package com.fr.design.editor.editor; + +import com.fr.base.Utils; +import com.fr.general.Inter; + +/** + * 单精度型编辑器 + * + * @author zhou + * @since 2012-3-29下午4:50:01 + */ +public class FloatEditor extends NumberEditor { + + public FloatEditor() { + this(new Float(0)); + } + + public FloatEditor(Float value) { + super(value, Inter.getLocText("Parameter-Float")); + } + + @Override + public Float getValue() { + return new Float(this.numberField.getValue()); + } + + @Override + public void setValue(Float value) { + if (value == null) { + value = new Float(0); + } + this.numberField.setInteger(false); + this.numberField.setValue(value.doubleValue()); + oldValue = Utils.objectToString(value); + } + + public String getIconName() { + return "type_double"; + } + + @Override + public boolean accept(Object object) { + return object != null && object instanceof Float; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/FormulaEditor.java b/designer_base/src/com/fr/design/editor/editor/FormulaEditor.java new file mode 100644 index 0000000000..44d8c9f8cd --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/FormulaEditor.java @@ -0,0 +1,178 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import com.fr.base.Formula; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.formula.FormulaFactory; +import com.fr.design.formula.UIFormula; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * CellEditor used to edit Formula object. + * + * @editor zhou + * @since 2012-3-29下午6:27:27 + */ +public class FormulaEditor extends Editor { + private Formula formula = new Formula(StringUtils.EMPTY); + private UITextField currentTextField; + private ShowPaneListener listerner = new ShowPaneListener(); + + /** + * Constructor. + */ + public FormulaEditor() { + this(""); + } + + public FormulaEditor(String name) { + this(name, null); + } + + public FormulaEditor(String name, Formula formula) { + if (formula != null) { + this.formula = formula; + } + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel editPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + currentTextField = new UITextField(28); + currentTextField.setText(this.formula.getContent()); + + editPane.add(currentTextField, BorderLayout.CENTER); + currentTextField.setEditable(false); + currentTextField.addMouseListener(listerner); + this.add(editPane, BorderLayout.CENTER); + this.setName(name); + } + + private class ShowPaneListener extends MouseAdapter { + public void mousePressed(MouseEvent e) { + if (currentTextField.isEnabled()) { + showFormulaPane(); + } + } + } + + public void setColumns(int i) { + this.currentTextField.setColumns(i); + } + + + /** + * 选中时弹出公式编辑框 + */ + public void selected() { + showFormulaPane(); + } + + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + currentTextField.setEnabled(enabled); + } + + + protected void showFormulaPane() { + final UIFormula formulaPane = FormulaFactory.createFormulaPaneWhenReserveFormula(); + formulaPane.populate(formula); + formulaPane.showLargeWindow(SwingUtilities.getWindowAncestor(FormulaEditor.this), new DialogActionAdapter() { + + @Override + public void doOk() { + formula = formulaPane.update(); + setValue(formula); + fireStateChanged(); + } + }).setVisible(true); + } + + /** + * Return the value of the CellEditor. + */ + @Override + public Formula getValue() { + if (formula != null && "=".equals(formula.getContent())) { + return null; + } + return formula; + } + + /** + * Set the value to the CellEditor. + */ + @Override + public void setValue(Formula value) { + if (value == null) { + value = new Formula(StringUtils.EMPTY); + } + this.formula = value; + currentTextField.setText(value.toString()); + } + + /** + * 增加文本监听 + * + * @param l 监听器 + */ + public void addDocumentListener(DocumentListener l) { + currentTextField.getDocument().addDocumentListener(l); + } + + public String getIconName() { + return "type_formula"; + } + + /** + * object是否是公司类型对象 + * + * @param object 需判断的对象 + * @return 是公式类型则返回true + */ + public boolean accept(Object object) { + return object instanceof Formula; + } + + /** + * 重置 + */ + public void reset() { + currentTextField.setText("="); + formula = new Formula(StringUtils.EMPTY); + } + + /** + * 清楚数据 + */ + public void clearData() { + reset(); + } + + /** + * 是否可用 + * + * @param flag 为true代表可用 + */ + public void enableEditor(boolean flag) { + this.setEnabled(flag); + this.currentTextField.setEnabled(flag); + if (flag == false) { + this.currentTextField.removeMouseListener(listerner); + } else { + int listenerSize = this.currentTextField.getMouseListeners().length; + for (int i = 0; i < listenerSize; i++) { + this.currentTextField.removeMouseListener(listerner); + } + this.currentTextField.addMouseListener(listerner); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/IntegerEditor.java b/designer_base/src/com/fr/design/editor/editor/IntegerEditor.java new file mode 100644 index 0000000000..b1661277a2 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/IntegerEditor.java @@ -0,0 +1,49 @@ +package com.fr.design.editor.editor; + +import com.fr.base.Utils; +import com.fr.general.Inter; + +/** + * 整数编辑器 + * + * @author zhou + * @since 2012-3-29下午4:02:06 + */ +public class IntegerEditor extends NumberEditor { + + private static final long serialVersionUID = 1L; + + public IntegerEditor() { + this(new Integer(0)); + } + + public IntegerEditor(Integer value) { + super(value, Inter.getLocText("Parameter-Integer")); + } + + @Override + public Integer getValue() { + return new Integer((int) this.numberField.getValue()); + } + + @Override + public boolean accept(Object object) { + return object != null && object instanceof Integer; + } + + public String getIconName() { + return "type_int"; + } + + @Override + public void setValue(Integer value) { + if (value == null) { + value = new Integer(0); + } + this.numberField.setInteger(true); + this.numberField.setValue(value.intValue()); + oldValue = Utils.objectToString(value); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/LongEditor.java b/designer_base/src/com/fr/design/editor/editor/LongEditor.java new file mode 100644 index 0000000000..cf296c5244 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/LongEditor.java @@ -0,0 +1,41 @@ +package com.fr.design.editor.editor; + +import com.fr.base.Utils; + +/** + * 长整形编辑器 + * + * @author zhou + * @since 2012-3-29下午4:50:31 + */ +public class LongEditor extends NumberEditor { + + public LongEditor() { + super(); + } + + public LongEditor(Long value, String name) { + super(value, name); + } + + @Override + public Long getValue() { + return new Long((int)this.numberField.getValue()); + } + + @Override + public void setValue(Long value) { + if (value == null) { + value = new Long(0); + } + this.numberField.setInteger(true); + this.numberField.setValue(value.intValue()); + oldValue = Utils.objectToString(value); + } + + @Override + public boolean accept(Object object) { + return object != null && object instanceof Long; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/NoneEditor.java b/designer_base/src/com/fr/design/editor/editor/NoneEditor.java new file mode 100644 index 0000000000..d28c31072f --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/NoneEditor.java @@ -0,0 +1,54 @@ +package com.fr.design.editor.editor; + +import java.awt.BorderLayout; + +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; + +public class NoneEditor extends Editor { + + private UITextField textField; + private String displayValue; + + public NoneEditor() { + this(null); + } + + public NoneEditor(String displayValue, String name) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.displayValue = displayValue; + textField = new UITextField(); + this.add(textField, BorderLayout.CENTER); + if (displayValue != null) { + textField.setText(displayValue); + } + textField.setEditable(false); + this.setName(name); + } + + public NoneEditor(String displayValue) { + this(displayValue, ""); + } + + @Override + public Object getValue() { + return null; + } + + @Override + public void setValue(Object value) { + if (displayValue != null) { + textField.setText(displayValue); + textField.setEditable(false); + } + } + + public String getIconName(){ + return "type_none"; + } + + @Override + public boolean accept(Object object) { + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/NumberEditor.java b/designer_base/src/com/fr/design/editor/editor/NumberEditor.java new file mode 100644 index 0000000000..c0ec2c7e69 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/NumberEditor.java @@ -0,0 +1,128 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import com.fr.design.gui.itextfield.UINumberField; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.StringUtils; + +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + + +/** + * CellEditor used to edit Number object. + * + * @editor zhou + * @since 2012-3-29下午1:35:12 + */ +public abstract class NumberEditor extends Editor { + private static final long serialVersionUID = 1L; + protected UINumberField numberField; // text field. + // the old value of text field. + protected String oldValue = StringUtils.EMPTY; + + /** + * Constructor. + */ + public NumberEditor() { + this(null, StringUtils.EMPTY); + } + + /** + * Constructor. + */ + public NumberEditor(T value, String name) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + numberField = new UINumberField(); + this.add(numberField, BorderLayout.CENTER); + this.numberField.addKeyListener(textKeyListener); + this.numberField.setHorizontalAlignment(UITextField.RIGHT); + this.setValue(value); + this.setName(name); + } + + /** + * 给numberField加键盘事件 + * + * @param keylistener + */ + public void addKeyListner2EditingComp(KeyListener keylistener) { + numberField.addKeyListener(keylistener); + } + + public void setColumns(int columns) { + this.numberField.setColumns(columns); + } + + /** + * Returns the horizontal alignment of the CellEditor. Valid keys are: + *
    + *
  • UITextField.LEFT + *
  • UITextField.CENTER + *
  • UITextField.RIGHT + *
  • UITextField.LEADING + *
  • UITextField.TRAILING + *
+ */ + public int getHorizontalAlignment() { + return this.numberField.getHorizontalAlignment(); + } + + /** + * Sets the horizontal alignment of the CellEditor. Valid keys are: + *
    + *
  • UITextField.LEFT + *
  • UITextField.CENTER + *
  • UITextField.RIGHT + *
  • UITextField.LEADING + *
  • UITextField.TRAILING + *
+ */ + public void setHorizontalAlignment(int horizontalAlignment) { + this.numberField.setHorizontalAlignment(horizontalAlignment); + } + + /** + * Sets whether or not this component is enabled. + */ + public void setEnabled(boolean enabled) { + this.numberField.setEnabled(enabled); + } + + public void selected() { + this.requestFocus(); + } + + public String getIconName() { + return "type_double"; + } + + /** + * Request focus + */ + public void requestFocus() { + this.numberField.requestFocus(); + } + + KeyListener textKeyListener = new KeyAdapter() { + + public void keyReleased(KeyEvent evt) { + int code = evt.getKeyCode(); + + if (code == KeyEvent.VK_ESCAPE) { + numberField.setText(oldValue); + } + if (code == KeyEvent.VK_ENTER) { + fireEditingStopped(); + } else { + fireStateChanged(); + } + } + }; + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/OldColumnIndexEditor.java b/designer_base/src/com/fr/design/editor/editor/OldColumnIndexEditor.java new file mode 100644 index 0000000000..59c1c79500 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/OldColumnIndexEditor.java @@ -0,0 +1,163 @@ +package com.fr.design.editor.editor; + +import com.fr.design.gui.ibutton.UIRadioButton; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.gui.icombobox.IntComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; + +public class OldColumnIndexEditor extends Editor { + private UIComboBox valueColumnIndexComboBox; + + protected UIRadioButton indexCheckBox; + protected UIRadioButton nameCheckBox; + protected String[] columnNames; + + public OldColumnIndexEditor(String name) { + this(0, name); + } + + public OldColumnIndexEditor(Object value, String name) { + this.setLayout(new BorderLayout(0, 0)); + valueColumnIndexComboBox = new IntComboBox(); + for (int i = 1; i <= ((Integer)value).intValue(); i++) { + valueColumnIndexComboBox.addItem(new Integer(i)); + } + + valueColumnIndexComboBox.setRenderer(columnNameListCellRenderer); + + if (((Integer)value).intValue() > 0) { + ((IntComboBox) valueColumnIndexComboBox).setSelectedInt(1); + } + this.add(valueColumnIndexComboBox, BorderLayout.CENTER); + this.setName(name); + valueColumnIndexComboBox.setBorder(null); + } + + + public OldColumnIndexEditor(String[] columnNames, String name) { + this(columnNames.length, name); + this.columnNames = columnNames; + + this.initComponents(); + } + + protected void initComponents() { + indexCheckBox = new UIRadioButton(Inter.getLocText("Datasource-Column_Index")); + nameCheckBox = new UIRadioButton(Inter.getLocText("ColumnName")); + indexCheckBox.addActionListener(actionListener); + nameCheckBox.addActionListener(actionListener); + javax.swing.ButtonGroup buttonGroup = new javax.swing.ButtonGroup(); + buttonGroup.add(indexCheckBox); + buttonGroup.add(nameCheckBox); + + JPanel checkPane = FRGUIPaneFactory.createLeftFlowZeroGapBorderPane(); + checkPane.add(indexCheckBox); + checkPane.add(nameCheckBox); + indexCheckBox.setSelected(true); + // 用名字啊 序号谁知道是对应的什么. +// nameCheckBox.setSelected(true); + + this.add(checkPane, BorderLayout.EAST); + } + + public boolean isColumnIndexSelect(){ + return this.indexCheckBox.isSelected(); + } + + public String[] getColumnNames() { + return columnNames; + } + + @Override + public Object getValue() { +// return this.isColumnIndexSelect() ? valueColumnIndexComboBox.getSelectedItem() +// : getColumnName(); + return valueColumnIndexComboBox.getSelectedItem(); + } + + public String getColumnName(){ + int index = ((Integer) valueColumnIndexComboBox.getSelectedItem()).intValue() - 1; + return index >= 0 && columnNames.length > index ? columnNames[index] : StringUtils.EMPTY; + } + + @Override + public void setValue(Object value) { + if(value instanceof Integer){ + valueColumnIndexComboBox.setSelectedItem(value); + }else{ +// value + } + } + + public String getIconName() { + return "ds_column"; + } + + @Override + public boolean accept(Object object) { + return object instanceof Integer || object instanceof String; + } + + protected ListCellRenderer columnNameListCellRenderer = new UIComboBoxRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if ((indexCheckBox != null && indexCheckBox.isSelected()) || columnNames == null) { + if (value == null) { + this.setText(""); + } else { + this.setText("" + value); + } + } else { + if (value == null) { + this.setText(""); + } else + this.setText(columnNames[((Integer) value).intValue() - 1]); + } + + return this; + } + }; + + private ActionListener actionListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (indexCheckBox != null) { + indexCheckBox.isSelected(); + } + OldColumnIndexEditor.this.invalidate(); + OldColumnIndexEditor.this.repaint(); + } + }; + + public void setEnabled(boolean enabled) { + if (valueColumnIndexComboBox != null) { + valueColumnIndexComboBox.setEnabled(enabled); + } + if (indexCheckBox != null) { + indexCheckBox.setEnabled(enabled); + } + if (nameCheckBox != null) { + nameCheckBox.setEnabled(enabled); + } + } + + public void addItemListener(ItemListener l) { + valueColumnIndexComboBox.addItemListener(l); + } + + public void removeItemListener(ItemListener l) { + valueColumnIndexComboBox.removeItemListener(l); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/ParameterEditor.java b/designer_base/src/com/fr/design/editor/editor/ParameterEditor.java new file mode 100644 index 0000000000..24dc661df1 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/ParameterEditor.java @@ -0,0 +1,64 @@ +package com.fr.design.editor.editor; + +import com.fr.base.Parameter; +import com.fr.design.gui.icombobox.ParameterComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; + +import java.awt.*; + +/** + * 参数Editor + * + * @editor zhou + * @since 2012-3-29下午5:24:41 + */ +public class ParameterEditor extends Editor { + + private ParameterComboBox parameterCombobox; + + public ParameterEditor() { + this(null); + } + + public ParameterEditor(Parameter parameter) { + parameterCombobox = new ParameterComboBox(); + parameterCombobox.setEditable(true); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(parameterCombobox, BorderLayout.CENTER); + + this.setValue(parameter); + this.setName(Inter.getLocText("Parameter")); + } + + @Override + public Parameter getValue() { + return parameterCombobox.getSelectedItem(); + } + + @Override + public void setValue(Parameter value) { + parameterCombobox.setSelectedParameter(value); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + parameterCombobox.setEnabled(enabled); + } + + @Override + public void requestFocus() { + parameterCombobox.requestFocus(); + } + + public String getIconName() { + return "parameter"; + } + + @Override + public boolean accept(Object object) { + return object instanceof Parameter; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/TextEditor.java b/designer_base/src/com/fr/design/editor/editor/TextEditor.java new file mode 100644 index 0000000000..e997f23ec1 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/TextEditor.java @@ -0,0 +1,153 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.editor.editor; + +import java.awt.BorderLayout; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +/** + * CellEditor used to edit String object. + * + * @editor zhou + * @since 2012-3-29下午6:00:43 + */ +public class TextEditor extends Editor { + + private UITextField textField; // text field. + // the old value of text field. + private String oldValue = StringUtils.EMPTY; + + /** + * Constructor. + */ + public TextEditor() { + this(null); + } + + public TextEditor(String value) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + textField = new UITextField(); + textField.setBorder(null); + this.add(textField, BorderLayout.CENTER); + this.textField.addKeyListener(textKeyListener); + + this.setValue(value); + this.setName(Inter.getLocText("Parameter-String")); + } + + public UITextField getTextField() { + return this.textField; + } + + /** + * Returns the horizontal alignment of the CellEditor. Valid keys are: + *
    + *
  • UITextField.LEFT + *
  • UITextField.CENTER + *
  • UITextField.RIGHT + *
  • UITextField.LEADING + *
  • UITextField.TRAILING + *
+ */ + public int getHorizontalAlignment() { + return this.textField.getHorizontalAlignment(); + } + + /** + * Sets the horizontal alignment of the CellEditor. Valid keys are: + *
    + *
  • UITextField.LEFT + *
  • UITextField.CENTER + *
  • UITextField.RIGHT + *
  • UITextField.LEADING + *
  • UITextField.TRAILING + *
+ */ + public void setHorizontalAlignment(int horizontalAlignment) { + this.textField.setHorizontalAlignment(horizontalAlignment); + } + + /** + * Return the value of the CellEditor. + */ + @Override + public String getValue() { + return this.textField.getText(); + } + + /** + * Set the value to the CellEditor. + */ + @Override + public void setValue(String value) { + // populate data to UI + if (value == null) { + value = StringUtils.EMPTY; + } + + oldValue = value.toString(); + this.textField.setText(oldValue); + } + + /** + * Sets whether or not this component is enabled. + */ + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + this.textField.setEnabled(enabled); + } + + + /** + * 请求焦点 + */ + public void requestFocus() { + this.textField.requestFocus(); + } + + KeyListener textKeyListener = new KeyAdapter() { + + @Override + public void keyReleased(KeyEvent evt) { + int code = evt.getKeyCode(); + if (code == KeyEvent.VK_ESCAPE) { + textField.setText(oldValue); + } + if (code == KeyEvent.VK_ENTER) { + fireEditingStopped(); + } else { + fireStateChanged(); + } + } + }; + + /** + * 被选中时文本输入框请求焦点 + */ + public void selected() { + this.textField.requestFocus(); + } + + public String getIconName() { + return "type_string"; + } + + /** + * 判断object是否是字符类型 + * + * @param object 需要判断的object + * @return 是字符类型则返回true + */ + public boolean accept(Object object) { + return object instanceof String; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/WidgetNameEditor.java b/designer_base/src/com/fr/design/editor/editor/WidgetNameEditor.java new file mode 100644 index 0000000000..fe39ca601e --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/WidgetNameEditor.java @@ -0,0 +1,110 @@ +package com.fr.design.editor.editor; + +import java.awt.BorderLayout; +import java.awt.Component; + +import javax.swing.JList; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +import com.fr.design.DesignModelAdapter; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.gui.icombobox.FilterComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.js.WidgetName; + +/** + * the editor to edit WidgetName + * + * @editor zhou + * @since 2012-3-29下午6:04:37 + */ +public class WidgetNameEditor extends Editor { + private FilterComboBox comb; + + + public WidgetNameEditor(String name) { + this(null, name); + } + + public WidgetNameEditor(WidgetName value) { + this(value, ""); + } + + private void generateWidgets() { + DesignModelAdapter model = DesignModelAdapter.getCurrentModelAdapter(); + this.comb.setItemList(model == null ? null : model.getWidgetsName()); + comb.setSelectedItem(comb.getEditor().getItem()); + } + + public WidgetNameEditor(WidgetName value, String name) { + comb = new FilterComboBox(); + comb.addPopupMenuListener(new PopupMenuListener() { + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + + } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + WidgetNameEditor.this.generateWidgets(); + } + + }); + this.generateWidgets(); + comb.setRenderer(new UIComboBoxRenderer() { + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof WidgetName) { + this.setText(((WidgetName) value).getName()); + } + + return this; + } + }); + comb.setEditable(true); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(comb, BorderLayout.CENTER); + + this.setValue(value); + this.setName(name); + } + + @Override + public WidgetName getValue() { + return (WidgetName) comb.getSelectedItem(); + } + + @Override + public void setValue(WidgetName value) { + comb.setSelectedItem(value); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + comb.setEnabled(enabled); + } + + @Override + public void requestFocus() { + comb.requestFocus(); + } + + public String getIconName() { + return "widgets"; + } + + @Override + public boolean accept(Object object) { + return object instanceof WidgetName; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/editor/editor/XMLANameEditor.java b/designer_base/src/com/fr/design/editor/editor/XMLANameEditor.java new file mode 100644 index 0000000000..3ab5b21097 --- /dev/null +++ b/designer_base/src/com/fr/design/editor/editor/XMLANameEditor.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.editor.editor; + +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; + +/** + * Created with IntelliJ IDEA. + * User: wikky + * Date: 14-3-21 + * Time: 上午9:12 + * To change this template use File | Settings | File Templates. + */ +public class XMLANameEditor extends ColumnIndexEditor{ + private String[] XMLANames; + + /** + * 多维数据集过滤界面的维度和度量值所用Editor + */ + public XMLANameEditor() { + this(ArrayUtils.EMPTY_STRING_ARRAY); + } + + /** + * 多维数据集过滤界面的维度和度量值所用Editor + * @param columnNames 度量值 + */ + public XMLANameEditor(String[] columnNames) { + this(columnNames, Inter.getLocText("Measure")); + } + + /** + * 多维数据集过滤界面的维度和度量值所用Editor + * @param columnNames 维度或度量值 + * @param name 显示名称 + */ + public XMLANameEditor(final String[] columnNames, String name) { + super(columnNames.length, name); + this.XMLANames = columnNames; + valueColumnIndexComboBox.setRenderer(new UIComboBoxRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value == null) { + this.setText(""); + } else { + this.setText(columnNames[((Integer) value).intValue() - 1]); + this.setToolTipText(columnNames[((Integer) value).intValue() - 1]); + } + + return this; + } + }); + } + + /** + *给XMLANames赋值 + * @param value 要赋予的值 + */ + @Override + public void setValue(Object value) { + for (int i = 0; i < XMLANames.length; i++) { + if (XMLANames[i].equalsIgnoreCase(String.valueOf(value))) { + super.setValue(i + 1); + return; + } + } + + super.reset(); + } + + /** + * 判断参数是否是String + * @param object 传进来用于判断的参数 + * @return 参数是否是String + */ + @Override + public boolean accept(Object object) { + return object instanceof String; + } + + /** + * 获取维度或度量值 + * @return 返回维度或度量值 + */ + public String getColumnName() { + int index = ((Integer) this.getValue()).intValue() - 1; + return getColumnNameAtIndex(index); + } + + /** + * 获取维度或度量值 + * @param index 所选择的序号 + * @return 返回序号对应的维度或度量值 + */ + public String getColumnNameAtIndex(int index) { + return index >= 0 && XMLANames.length > index ? XMLANames[index] : StringUtils.EMPTY; + } + + /** + * 获取图标名 + * @return + */ + public String getIconName() { + return "cube"; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/ChangeEvent.java b/designer_base/src/com/fr/design/event/ChangeEvent.java new file mode 100644 index 0000000000..2fbc61275d --- /dev/null +++ b/designer_base/src/com/fr/design/event/ChangeEvent.java @@ -0,0 +1 @@ +package com.fr.design.event; import java.util.EventObject; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 12-12-28 * Time: 下午8:25 */ public class ChangeEvent extends EventObject { /** * Constructs a prototypical Event. * * @param source The object on which the Event initially occurred. * @throws IllegalArgumentException if source is null. */ public ChangeEvent(Object source) { super(source); } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/ChangeListener.java b/designer_base/src/com/fr/design/event/ChangeListener.java new file mode 100644 index 0000000000..4edfeda02c --- /dev/null +++ b/designer_base/src/com/fr/design/event/ChangeListener.java @@ -0,0 +1 @@ +package com.fr.design.event; import java.util.EventListener; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 12-12-28 * Time: 下午8:24 */ public interface ChangeListener extends EventListener { public void fireChanged(ChangeEvent event); } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/GlobalNameListener.java b/designer_base/src/com/fr/design/event/GlobalNameListener.java new file mode 100644 index 0000000000..7b3a02e1b1 --- /dev/null +++ b/designer_base/src/com/fr/design/event/GlobalNameListener.java @@ -0,0 +1 @@ +package com.fr.design.event; /** * Author : Shockway * Date: 13-7-17 * Time: 上午10:38 */ public interface GlobalNameListener { /** * 设置选中的面板或是组件的名字 * @param name */ public void setGlobalName(String name); /** * 得到选中面板或者组件的名字 * @return */ public String getGlobalName(); } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/GlobalNameObserver.java b/designer_base/src/com/fr/design/event/GlobalNameObserver.java new file mode 100644 index 0000000000..48f1f46a60 --- /dev/null +++ b/designer_base/src/com/fr/design/event/GlobalNameObserver.java @@ -0,0 +1 @@ +package com.fr.design.event; /** * Author : Shockway * Date: 13-7-17 * Time: 上午10:37 */ public interface GlobalNameObserver { /** * 给组件登记一个全局名字观察者监听事件 * * @param listener 观察者监听事件 */ public void registerNameListener(GlobalNameListener listener); /** * 组件是否需要响应添加的观察者事件 * * @return 如果需要响应观察者事件则返回true,否则返回false */ public boolean shouldResponseNameListener(); /** * 设置全局名字 * @param name */ public void setGlobalName(String name); } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/TargetModifiedEvent.java b/designer_base/src/com/fr/design/event/TargetModifiedEvent.java new file mode 100644 index 0000000000..69535940f1 --- /dev/null +++ b/designer_base/src/com/fr/design/event/TargetModifiedEvent.java @@ -0,0 +1,19 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.event; + +import java.util.EventObject; + +/** + * ReportDataChangeEvent. + */ +public class TargetModifiedEvent extends EventObject { + + /** + * Constructs a CellSelectionChangeEvent object. + */ + public TargetModifiedEvent(Object source) { + super(source); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/TargetModifiedListener.java b/designer_base/src/com/fr/design/event/TargetModifiedListener.java new file mode 100644 index 0000000000..11ae362964 --- /dev/null +++ b/designer_base/src/com/fr/design/event/TargetModifiedListener.java @@ -0,0 +1,16 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.event; + +import java.util.EventListener; + +/** + * TemplateModifiedListener. + */ +public interface TargetModifiedListener extends EventListener { + /** + * Invoked when the target of the listener has changed the rpt content. + */ + public void targetModified(TargetModifiedEvent e); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/TemplateTreeDragSource.java b/designer_base/src/com/fr/design/event/TemplateTreeDragSource.java new file mode 100644 index 0000000000..7b387305c1 --- /dev/null +++ b/designer_base/src/com/fr/design/event/TemplateTreeDragSource.java @@ -0,0 +1,37 @@ +package com.fr.design.event; + +import com.fr.design.gui.itree.filetree.TemplateFileTree; +import com.fr.design.mainframe.dnd.ArrayTransferable; +import com.fr.design.mainframe.dnd.SerializableTransferable; +import com.fr.general.web.ParameterConsts; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; + +/** + * Created with IntelliJ IDEA. + * User: richie + * Date: 13-11-4 + * Time: 下午2:17 + */ +public class TemplateTreeDragSource extends DragSourceAdapter implements DragGestureListener { + private DragSource source; + + public TemplateTreeDragSource(JTree tree, int actions) { + source = new DragSource(); + source.createDefaultDragGestureRecognizer(tree, actions, this); + + } + public void dragGestureRecognized(DragGestureEvent dge) { + Component comp = dge.getComponent(); + if (comp instanceof TemplateFileTree) { + String selectedPath = ((TemplateFileTree)comp).getSelectedTemplatePath(); + source.startDrag(dge, DragSource.DefaultLinkDrop, new SerializableTransferable(selectedPath), this); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/UIObserver.java b/designer_base/src/com/fr/design/event/UIObserver.java new file mode 100644 index 0000000000..84e5145a7d --- /dev/null +++ b/designer_base/src/com/fr/design/event/UIObserver.java @@ -0,0 +1 @@ +package com.fr.design.event; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 13-3-18 * Time: 下午3:00 * 组件的事件观察者接口,用于确定UI组件是否需要响应监听事件以及增加监听事件用于监听组件是否做了改变模板值的操作 */ public interface UIObserver { /** * 给组件登记一个观察者监听事件 * * @param listener 观察者监听事件 */ public void registerChangeListener(final UIObserverListener listener); /** * 组件是否需要响应添加的观察者事件 * * @return 如果需要响应观察者事件则返回true,否则返回false */ public boolean shouldResponseChangeListener(); } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/event/UIObserverListener.java b/designer_base/src/com/fr/design/event/UIObserverListener.java new file mode 100644 index 0000000000..8154f903d5 --- /dev/null +++ b/designer_base/src/com/fr/design/event/UIObserverListener.java @@ -0,0 +1,14 @@ +package com.fr.design.event; + +import java.util.EventListener; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-3-22 + * Time: 下午5:22 + */ +public interface UIObserverListener extends EventListener { + public void doChange(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/After.java b/designer_base/src/com/fr/design/extra/After.java new file mode 100644 index 0000000000..bc45a1ca6d --- /dev/null +++ b/designer_base/src/com/fr/design/extra/After.java @@ -0,0 +1,11 @@ +package com.fr.design.extra; + +/** + * @author richie + * @date 2015-06-25 + * @since 8.0 + */ +public interface After { + + void done(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/AppStoreBuilder.java b/designer_base/src/com/fr/design/extra/AppStoreBuilder.java new file mode 100644 index 0000000000..ba8950ec2b --- /dev/null +++ b/designer_base/src/com/fr/design/extra/AppStoreBuilder.java @@ -0,0 +1,19 @@ +package com.fr.design.extra; + +/** + * Created by richie on 16/3/18. + * 应用商店构建器,需要负责去检查是否有最新的版本的应用商店,如果有且适合当前设计器版本,则弹窗提示用户是否升级到最新的应用商店. + * 用户点击更新后,构建器把最新版本的JavaScript以及HTML代码下载到安装目录下的scripts/store目录下 + * 初步想法,设计器中所有的URL请求,都从http(s)://support.finereport.com/config获取,然后存入设计器中,防止修改了某个url导致一系列无法兼容问题 + * 而我们需要做的仅仅是保持兼容support这个服务器的持续维护和兼容,相对来说就简单多了 + */ +public class AppStoreBuilder { + + public void checkStoreJavaSciptVersion() { + + } + + public void updateStoreJavaScript() { + + } +} diff --git a/designer_base/src/com/fr/design/extra/LoginCheckContext.java b/designer_base/src/com/fr/design/extra/LoginCheckContext.java new file mode 100644 index 0000000000..0e7461fb3b --- /dev/null +++ b/designer_base/src/com/fr/design/extra/LoginCheckContext.java @@ -0,0 +1,30 @@ +package com.fr.design.extra; + +import java.util.ArrayList; + +/** + * Created by 夏翔 on 2016/3/14 0014. + */ + + +public class LoginCheckContext { + private static ArrayList loginCheckListenerList = new ArrayList(); + + /** + * 触发登录框弹出的监听器 + */ + public static void fireLoginCheckListener() { + for (LoginCheckListener l : loginCheckListenerList) { + l.loginChecked(); + } + } + + /** + * 添加一个弹出登录框的监听事件 + * + * @param l 登录框弹出监听事件 + */ + public static void addLoginCheckListener(LoginCheckListener l) { + loginCheckListenerList.add(l); + } +} diff --git a/designer_base/src/com/fr/design/extra/LoginCheckListener.java b/designer_base/src/com/fr/design/extra/LoginCheckListener.java new file mode 100644 index 0000000000..e061fb1e1d --- /dev/null +++ b/designer_base/src/com/fr/design/extra/LoginCheckListener.java @@ -0,0 +1,8 @@ +package com.fr.design.extra; + +/** + * Created by 夏翔 on 2016/3/14 0013. + */ +public interface LoginCheckListener { + void loginChecked(); +} diff --git a/designer_base/src/com/fr/design/extra/PluginAbstractLoadingViewPane.java b/designer_base/src/com/fr/design/extra/PluginAbstractLoadingViewPane.java new file mode 100644 index 0000000000..9719bc097b --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginAbstractLoadingViewPane.java @@ -0,0 +1,191 @@ +package com.fr.design.extra; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author richie + * @date 2015-03-11 + * @since 8.0 + */ +public abstract class PluginAbstractLoadingViewPane extends PluginAbstractViewPane { + private static final String LOAD_CARD = "load"; + private static final String SUCCESS_CARD = "success"; + private static final String LOAD_ERROR = "error"; + + private static final int BUSYANIMATIONRATE = 30; + + private Icon[] busyIcons = new Icon[15]; + private UILabel statusAnimationLabel; + private Timer busyIconTimer; + private int busyIconIndex; + private CardLayout cardLayout; + + /** + * 初始化cardlayout页面 + * @param tabbedPane + */ + public PluginAbstractLoadingViewPane(UITabbedPane tabbedPane) { + cardLayout = new CardLayout(); + setLayout(cardLayout); + + add(initAndStartLoadingComponent(), LOAD_CARD); + add(createSuccessPane(), SUCCESS_CARD); + add(createErrorPane(), LOAD_ERROR); + showLoadingCard(); + loadDataInAnotherThread(); + } + /** + * 创建成功页面 + * @return 创建的页面对象 + */ + public abstract JPanel createSuccessPane(); + + /** + * 创建错误页面 + * @return 创建的页面对象 + */ + public abstract JPanel createErrorPane(); + + /** + * 显示加载页面 + */ + public void showLoadingCard() { + cardLayout.show(this, LOAD_CARD); + } + + /** + * 显示成功页面 + */ + public void showSuccessCard() { + cardLayout.show(this, SUCCESS_CARD); + } + + /** + * 显示加载错误页面 + */ + public void showLoadErrorCard() { + cardLayout.show(this, LOAD_ERROR); + } + + /** + * 停止加载 + */ + public void stopLoad() { + busyIconTimer.stop(); + } + + + private JPanel initAndStartLoadingComponent() { + return new PluginStatusCheckCompletePane(){ + + @Override + public void pressInstallButton() { + + } + + @Override + public void pressInstallFromDiskButton() { + installFromDiskFile(); + } + + @Override + public String textForInstallButton() { + return Inter.getLocText("FR-Designer-Plugin_Install"); + } + + + @Override + public String textForInstallFromDiskButton() { + return textForInstallFromDiskFileButton(); + } + + @Override + public JComponent centerPane() { + for (int i = 0; i < busyIcons.length; i++) { + busyIcons[i] = BaseUtils.readIcon("/com/fr/design/images/load/busy-icon" + i + ".png"); + } + int busyAnimationRate = BUSYANIMATIONRATE; + statusAnimationLabel = new UILabel(); + + statusAnimationLabel.setText(textForLoadingLabel()); + busyIconTimer = new Timer(busyAnimationRate, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + busyIconIndex = (busyIconIndex + 1) % busyIcons.length; + + statusAnimationLabel.setIcon(busyIcons[busyIconIndex]); + statusAnimationLabel.setHorizontalAlignment(SwingConstants.CENTER); + } + }); + busyIconTimer.start(); + + return statusAnimationLabel; + } + }; + + + } + + private void loadDataInAnotherThread() { + new SwingWorker(){ + + @Override + protected V doInBackground() throws Exception { + return loadData(); + } + + public void done() { + stopLoad(); + try { + V v = get(); + loadOnSuccess(v); + showSuccessCard(); + } catch (Exception e) { + showLoadErrorCard(); + loadOnFailed(e); + } + } + + }.execute(); + } + + protected abstract void installFromDiskFile(); + + /** + * 加载数据 + * @return 返回数据 + */ + public abstract V loadData() throws Exception; + + /** + * 加载成功 + * @param v 将得到的数据传入 + */ + public abstract void loadOnSuccess(V v); + + /** + * 加载失败 + * @param e 异常消息 + */ + public abstract void loadOnFailed(Exception e); + + /** + * 正在加载页的标题 + * @return 标题字符串 + */ + public abstract String textForLoadingLabel(); + + /** + * 从磁盘安装按钮的提示 + * @return 按钮标题字符串 + */ + public abstract String textForInstallFromDiskFileButton(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginAbstractViewPane.java b/designer_base/src/com/fr/design/extra/PluginAbstractViewPane.java new file mode 100644 index 0000000000..220882971e --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginAbstractViewPane.java @@ -0,0 +1,26 @@ +package com.fr.design.extra; + +import com.fr.design.dialog.BasicPane; + +import javax.swing.*; +import java.awt.*; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public abstract class PluginAbstractViewPane extends BasicPane { + + public JPanel createOperationPane() { + JPanel panel = new JPanel(); + panel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 20)); + panel.setPreferredSize(new Dimension(120, 60)); + return panel; + } + + @Override + protected String title4PopupWindow() { + return "View"; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginConstants.java b/designer_base/src/com/fr/design/extra/PluginConstants.java new file mode 100644 index 0000000000..7f60a0b52f --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginConstants.java @@ -0,0 +1,31 @@ +package com.fr.design.extra; + +/** + * @author richie + * @date 2015-03-11 + * @since 8.0 + */ +public class PluginConstants { + + public static final String PLUGIN_INSTALL_INFO = "http://feedback.finedevelop.com:3000/plugin"; + + /** + * 获取所有插件的服务器地址 + */ + public static final String PLUGIN_STORE_URL = "http://shop.finereport.com/ShopServer?pg=all_plugin"; + + /** + * 获取插件更新信息的服务器地址 + */ + public static final String PLUGIN_CHECK_UPDATE_URL = "http://shop.finereport.com/ShopServer?pg=all_plugin"; + + /** + * 插件下载服务器地址 + */ + public static final String PLUGIN_DOWNLOAD_URL = "http://shop.finereport.com/ShopServer?pg=plugin"; + + public static final int BYTES_NUM = 1024; + + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginControlPane.java b/designer_base/src/com/fr/design/extra/PluginControlPane.java new file mode 100644 index 0000000000..82657904f6 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginControlPane.java @@ -0,0 +1,153 @@ +package com.fr.design.extra; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.IOUtils; +import com.fr.general.Inter; +import com.fr.plugin.Plugin; +import com.fr.plugin.PluginLicense; +import com.fr.plugin.PluginLicenseManager; +import com.fr.plugin.PluginLoader; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.util.ArrayList; + +/** + * @author richie + * @date 2015-03-09 + * @since 8.0 + */ +public class PluginControlPane extends BasicPane { + private UIList pluginList; + private DefaultListModel listModel; + private PluginDetailPane detailPane; + private java.util.List listeners = new ArrayList(); + private Plugin[] plugins; + private UITextField searchTextField; + + public PluginControlPane() { + setLayout(new BorderLayout()); + searchTextField = new UITextField(); + searchTextField.setColumns(20); + searchTextField.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + doSearch(searchTextField.getText()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + doSearch(searchTextField.getText()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + doSearch(searchTextField.getText()); + } + }); + add(GUICoreUtils.createFlowPane(new UILabel(Inter.getLocText("FR-Designer-Plugin_Search") + ":"), searchTextField, FlowLayout.LEFT), BorderLayout.NORTH); + + pluginList = new UIList(); + DefaultListCellRenderer renderer = new DefaultListCellRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof Plugin) { + PluginLicense pluginLicense = PluginLicenseManager.getInstance().getPluginLicenseByID(((Plugin) value).getId()); + String extraInfo = ""; + if (pluginLicense.isJarDamage()) { + extraInfo = "(" + Inter.getLocText("FR-Plugin-Plugin_Damaged") + ")"; + } else if (pluginLicense.getLeftTime() != -1) { + if (pluginLicense.isAvailable()) { + extraInfo = "(" + (pluginLicense.isTrial() ? Inter.getLocText("FR-Plugin-Designer_Trial") : Inter.getLocText("FR-Plugin-Designer_Authorized")) + pluginLicense.getLeftTime() + Inter.getLocText("FR-Plugin-Designer_Left") + ")"; + } else { + extraInfo = "(" + (pluginLicense.isTrial() ? Inter.getLocText("FR-Plugin-Designer_Trial") : Inter.getLocText("FR-Plugin-Designer_Authorized")) + Inter.getLocText("FR-Plugin-Designer_Expired") + ")"; + } + } + setText(((Plugin) value).getName() + extraInfo); + setIcon(IOUtils.readIcon("/com/fr/design/images/server/plugin.png")); + } + return this; + } + }; + pluginList.setCellRenderer(renderer); + listModel = new DefaultListModel(); + pluginList.setModel(listModel); + JScrollPane jScrollPane = new JScrollPane(pluginList); + + + PluginDescriptionLabel label = new PluginDescriptionLabel(); + label.setText(Inter.getLocText("FR-Designer-Plugin_Plugin")); + JPanel leftPane = GUICoreUtils.createBorderLayoutPane( + jScrollPane, BorderLayout.CENTER, + label, BorderLayout.NORTH + ); + detailPane = new PluginDetailPane(); + JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPane, detailPane); + splitPane.setDividerLocation(200); + add(new UIScrollPane(splitPane)); + + pluginList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + Plugin plugin = (Plugin) pluginList.getSelectedValue(); + if (plugin != null) { + detailPane.populate(plugin); + for (PluginSelectListener l : listeners) { + l.valueChanged(plugin); + } + } else { + detailPane.reset(); + } + } + }); + } + + public void addPluginSelectionListener(PluginSelectListener l) { + listeners.add(l); + } + + public void loadPlugins(Plugin[] plugins) { + this.plugins = plugins; + for (Plugin plugin : plugins) { + listModel.addElement(plugin); + } + } + + private void doSearch(String text) { + if (StringUtils.isNotBlank(text)) { + listModel.clear(); + for (Plugin plugin : plugins) { + if (plugin.match(text)) { + listModel.addElement(plugin); + } + } + } + } + + public Plugin getSelectedPlugin() { + return (Plugin) pluginList.getSelectedValue(); + } + + public void deletePlugin(Plugin plugin) { + listModel.removeElement(plugin); + PluginLoader.getLoader().deletePlugin(plugin); + } + + @Override + protected String title4PopupWindow() { + return "Plugin"; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginDescriptionLabel.java b/designer_base/src/com/fr/design/extra/PluginDescriptionLabel.java new file mode 100644 index 0000000000..45c99de5e0 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginDescriptionLabel.java @@ -0,0 +1,23 @@ +package com.fr.design.extra; + +import com.fr.design.gui.ilable.UILabel; + +import java.awt.*; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginDescriptionLabel extends UILabel { + private static final Dimension S = new Dimension(120, 24); + + public PluginDescriptionLabel() { + super(); + } + + public Dimension getPreferredSize() { + return S; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginDetailPane.java b/designer_base/src/com/fr/design/extra/PluginDetailPane.java new file mode 100644 index 0000000000..4edfb934f6 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginDetailPane.java @@ -0,0 +1,71 @@ +package com.fr.design.extra; + +import com.fr.design.dialog.BasicPane; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.plugin.Plugin; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginDetailPane extends BasicPane { + + private JEditorPane textPane; + + public PluginDetailPane() { + setLayout(new BorderLayout()); + PluginDescriptionLabel label = new PluginDescriptionLabel(); + label.setText(Inter.getLocText("FR-Designer-Plugin_Plugin_Description")); + add(label, BorderLayout.NORTH); + + textPane = new JEditorPane(); + textPane.setContentType("text/html"); + textPane.setEditable(false); + textPane.addHyperlinkListener(new HyperlinkListener() { + @Override + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) { + return; + } + + URL linkUrl = e.getURL(); + if (linkUrl != null) { + try { + Desktop.getDesktop().browse(linkUrl.toURI()); + } catch (IOException | URISyntaxException e1) { + FRLogger.getLogger().error(e1.getMessage()); + } + } + } + + }); + + + add(textPane, BorderLayout.CENTER); + + } + + public void populate(Plugin plugin) { + textPane.setText(plugin.toHTML()); + } + + public void reset() { + textPane.setText(StringUtils.EMPTY); + } + + @Override + protected String title4PopupWindow() { + return "Detail"; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginFromStorePane.java b/designer_base/src/com/fr/design/extra/PluginFromStorePane.java new file mode 100644 index 0000000000..717cd11997 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginFromStorePane.java @@ -0,0 +1,259 @@ +package com.fr.design.extra; + +import com.fr.base.FRContext; +import com.fr.design.DesignerEnvManager; +import com.fr.design.RestartHelper; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.general.Inter; +import com.fr.plugin.Plugin; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.File; +import java.util.List; +import java.util.concurrent.ExecutionException; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginFromStorePane extends PluginAbstractLoadingViewPane { + private UILabel errorMsgLabel; + private UITabbedPane tabbedPane; + private PluginControlPane controlPane; + + private static final int LISTNUM1 = 1; + private static final int LISTNUM100 = 100; + + + + public PluginFromStorePane(final UITabbedPane tabbedPane) { + super(tabbedPane); + this.tabbedPane = tabbedPane; + } + + /** + * 创建成功页面 + * @return 创建的页面对象 + */ + public JPanel createSuccessPane() { + return new PluginStatusCheckCompletePane(){ + + + @Override + public void pressInstallButton() { + doUpdateOnline(this); + } + + @Override + public void pressInstallFromDiskButton() { + installFromDiskFile(); + } + + @Override + public String textForInstallButton() { + return Inter.getLocText("FR-Designer-Plugin_Install"); + } + + + @Override + public String textForInstallFromDiskButton() { + return Inter.getLocText("FR-Designer-Plugin_Install_From_Local"); + } + + @Override + public JPanel centerPane() { + controlPane = new PluginControlPane(); + final PluginStatusCheckCompletePane s = this; + controlPane.addPluginSelectionListener(new PluginSelectListener() { + @Override + public void valueChanged(Plugin plugin) { + s.setInstallButtonEnable(true); + } + }); + return controlPane; + } + }; + } + + /** + * 创建错误页面 + * @return 创建的页面对象 + */ + @Override + public JPanel createErrorPane() { + errorMsgLabel = new UILabel(); + errorMsgLabel.setHorizontalAlignment(SwingConstants.CENTER); + + return new PluginStatusCheckCompletePane(){ + + @Override + public void pressInstallButton() { + + } + + @Override + public void pressInstallFromDiskButton() { + installFromDiskFile(); + } + + @Override + public String textForInstallButton() { + return Inter.getLocText("FR-Designer-Plugin_Install"); + } + + + @Override + public String textForInstallFromDiskButton() { + return Inter.getLocText("FR-Designer-Plugin_Install_From_Local"); + } + + @Override + public JComponent centerPane() { + return errorMsgLabel; + } + }; + } + + /** + * 加载数据 + * @return 插件 + */ + public Plugin[] loadData() throws Exception { + //Thread.sleep(3000); + return PluginsReaderFromStore.readPlugins(); + } + + /** + * 加载成功处理 + * @param plugins 插件 + */ + public void loadOnSuccess(Plugin[] plugins) { + controlPane.loadPlugins(plugins); + tabbedPane.setTitleAt(2, Inter.getLocText("FR-Designer-Plugin_All_Plugins") + "(" + plugins.length + ")"); + } + + /** + * 加载失败 + * @param e 异常消息 + */ + public void loadOnFailed(Exception e) { + errorMsgLabel.setText(e.getCause().getMessage()); + } + + protected void installFromDiskFile() { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setFileFilter(new FileNameExtensionFilter("zip", "zip")); + int returnValue = fileChooser.showOpenDialog(PluginFromStorePane.this); + if (returnValue == JFileChooser.APPROVE_OPTION) { + final File chosenFile = fileChooser.getSelectedFile(); + installFromDiskZipFile(chosenFile); + + } + } + + + private void installFromDiskZipFile(File chosenFile) { + try { + PluginHelper.installPluginFromDisk(chosenFile, new After() { + @Override + public void done() { + int rv = JOptionPane.showOptionDialog( + PluginFromStorePane.this, + Inter.getLocText("FR-Designer-Plugin_Install_Successful"), + Inter.getLocText("FR-Designer-Plugin_Warning"), + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + new String[]{Inter.getLocText("FR-Designer-Basic_Restart_Designer"), Inter.getLocText("FR-Designer-Basic_Restart_Designer_Later")}, + null + ); + if (rv == JOptionPane.OK_OPTION) { + RestartHelper.restart(); + } + } + }); + + } catch (Exception e1) { + JOptionPane.showMessageDialog(PluginFromStorePane.this, e1.getMessage(), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + } + } + + private void doUpdateOnline(final PluginStatusCheckCompletePane pane) { + if (StringUtils.isNotEmpty(DesignerEnvManager.getEnvManager().getBBSName())){ + new SwingWorker(){ + + @Override + protected Void doInBackground() throws Exception { + Plugin plugin = controlPane.getSelectedPlugin(); + String id = null; + if (plugin != null) { + id = plugin.getId(); + } + String username = DesignerEnvManager.getEnvManager().getBBSName(); + String password = DesignerEnvManager.getEnvManager().getBBSPassword(); + try { + PluginHelper.downloadPluginFile(id,username,password, new Process() { + @Override + public void process(Double integer) { + publish(integer); + } + }); + Thread.sleep(2000); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return null; + } + + public void process(List list) { + pane.setProgress(list.get(list.size() - LISTNUM1) * LISTNUM100); + } + + public void done() { + //下载完成,开始执行安装 + try { + get(); + pane.didTaskFinished(); + installFromDiskZipFile(PluginHelper.getDownloadTempFile()); + } catch (InterruptedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } catch (ExecutionException e) { + FRContext.getLogger().error(e.getMessage(), e); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + }.execute(); + } else { + LoginCheckContext.fireLoginCheckListener(); + } + + } + + /** + * 正在加载页的标题 + * @return 标题字符串 + */ + public String textForLoadingLabel() { + return Inter.getLocText("FR-Designer-Plugin_Load_Plugins_From_Server"); + } + + /** + * 从磁盘安装按钮的提示 + * @return 按钮标题字符串 + */ + @Override + public String textForInstallFromDiskFileButton() { + return Inter.getLocText("FR-Designer-Plugin_Install_From_Local"); + } + + @Override + protected String title4PopupWindow() { + return "All"; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginHelper.java b/designer_base/src/com/fr/design/extra/PluginHelper.java new file mode 100644 index 0000000000..62f6c5e30f --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginHelper.java @@ -0,0 +1,298 @@ +package com.fr.design.extra; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.DesignerEnvManager; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.GeneralUtils; +import com.fr.general.IOUtils; +import com.fr.general.Inter; +import com.fr.general.http.HttpClient; +import com.fr.plugin.Plugin; +import com.fr.plugin.PluginLoader; +import com.fr.plugin.PluginManagerHelper; +import com.fr.stable.ArrayUtils; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; +import com.fr.stable.xml.XMLTools; + +import javax.swing.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.concurrent.ExecutionException; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginHelper { + private static final String TEMP_PATH = System.getProperty("user.dir") + "/tmp"; + private static final String DOWNLOAD_PATH = System.getProperty("user.dir") + "/download"; + private static final String TEMP_FILE = "temp.zip"; + + /** + * 下载插件 + * + * @param id 插件id + * @param p 下载百分比处理 + */ + public static void downloadPluginFile(String id, String username, String password, Process p) throws Exception { + HttpClient httpClient = new HttpClient(getDownloadPath(id, username, password)); + if (httpClient.getResponseCode() == HttpURLConnection.HTTP_OK) { + int totalSize = httpClient.getContentLength(); + InputStream reader = httpClient.getResponseStream(); + String temp = StableUtils.pathJoin(DOWNLOAD_PATH, TEMP_FILE); + StableUtils.makesureFileExist(new File(temp)); + FileOutputStream writer = new FileOutputStream(temp); + byte[] buffer = new byte[PluginConstants.BYTES_NUM]; + int bytesRead = 0; + int totalBytesRead = 0; + + while ((bytesRead = reader.read(buffer)) > 0) { + writer.write(buffer, 0, bytesRead); + buffer = new byte[PluginConstants.BYTES_NUM]; + totalBytesRead += bytesRead; + p.process(totalBytesRead / (double) totalSize); + } + reader.close(); + writer.flush(); + writer.close(); + } + } + + private static String getDownloadPath(String id, String username, String password) throws Exception { + HashMap map = new HashMap(); + map.put("id", id); + map.put("username", username); + map.put("password", password); + HttpClient httpClient = new HttpClient(PluginConstants.PLUGIN_DOWNLOAD_URL, map); + String resText = httpClient.getResponseText(); + String charSet = EncodeConstants.ENCODING_UTF_8; + resText = URLDecoder.decode(URLDecoder.decode(resText, charSet), charSet); + + return resText; + } + + public static File getDownloadTempFile() { + return new File(StableUtils.pathJoin(DOWNLOAD_PATH, TEMP_FILE)); + } + + /** + * 从压缩文件中读取插件信息 + * + * @param chosenFile 选择的压缩文件 + * @return 返回插件对象 + * @throws Exception 读取插件信息失败则抛出异常 + */ + public static Plugin readPlugin(File chosenFile) throws Exception { + // 需要先删除临时目录保证加压出来的文件不会和安装失败的文件混合到一起 + StableUtils.deleteFile(new File(TEMP_PATH)); + + IOUtils.unzip(chosenFile, TEMP_PATH); + File pluginFileDir = getTempPluginFileDirectory(); + if (pluginFileDir == null) { + return null; + } + Plugin plugin = null; + if (pluginFileDir.isDirectory()) { + File[] pluginFiles = pluginFileDir.listFiles(); + if (ArrayUtils.isNotEmpty(pluginFiles)) { + for (File f : pluginFiles) { + if (f.getName().equals("plugin.xml")) { + plugin = new Plugin(); + InputStream inputStream = plugin.readEncryptXml(new FileInputStream(f)); + XMLTools.readInputStreamXML(plugin, inputStream); + if (!plugin.isValidate()) { + return null; + } + inputStream.close(); + break; + } + } + } + } + return plugin; + } + + /** + * 从选中的压缩文件中安装插件 + * + * @param chosenFile 选择的压缩文件 + * @param after 操作完成事件 + * @throws Exception 安装失败则抛出异常 + */ + public static void installPluginFromDisk(File chosenFile, After after) throws Exception { + Plugin plugin = readPlugin(chosenFile); + installPluginFromUnzippedTempDir(FRContext.getCurrentEnv(), plugin, after); + } + + /** + * 从压缩文件中复制Restart*.class和restart.exe到bin目录下 + * + * @param file 插件文件 + * @param plugin 插件 + * @throws Exception + */ + public static void copyFilesToBinFolder(File file, Plugin plugin) throws Exception { + File[] pluginFiles = file.listFiles(); + for (File restartFile : pluginFiles) { + if (restartFile.getAbsolutePath().endsWith(".class")) { + String installHome = StableUtils.getInstallHome(); + IOUtils.copy(restartFile, new File(StableUtils.pathJoin(new String[]{installHome, "bin"}))); + } + } + } + + /** + * 从插件压缩包解压到得临时文件中安装插件 + * + * @param env 报表运行环境 + * @param plugin 插件 + * @param after 操作完成事件 + * @throws Exception + */ + public static void installPluginFromUnzippedTempDir(Env env, final Plugin plugin, final After after) throws Exception { + validPlugin(plugin); + if (plugin.isValidate()) { + File file = getTempPluginFileDirectory(); + env.copyFilesToPluginAndLibFolder(file, plugin); + copyFilesToBinFolder(file, plugin); + env.movePluginEmbFile(file, plugin); + } + // 删除放解压文件的临时文件夹 + StableUtils.deleteFile(new File(TEMP_PATH)); + new SwingWorker() { + + @Override + protected String doInBackground() throws Exception { + return sendInstalledPluginInfo(plugin); + } + + @Override + protected void done() { + try { + String text = get(); + FRLogger.getLogger().info("plugin install:" + text); + } catch (InterruptedException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } catch (ExecutionException e) { + FRLogger.getLogger().error(e.getMessage(), e); + } + if (after != null) { + after.done(); + } + } + }.execute(); + } + + private static void validPlugin(Plugin plugin) throws Exception { + if (plugin == null) { + throw new com.fr.plugin.PluginVerifyException(Inter.getLocText("FR-Designer-Plugin_Illegal_Plugin_Zip_Cannot_Be_Install")); + } + if (PluginLoader.getLoader().isInstalled(plugin)) { + throw new com.fr.plugin.PluginVerifyException(Inter.getLocText("FR-Designer-Plugin_Has_Been_Installed")); + } + if (plugin.isJarExpired()) { + String jarExpiredInfo = Inter.getLocText(new String[]{"FR-Designer-Plugin_Jar_Expired", ",", "FR-Designer-Plugin_Install_Failed", ",", "FR-Designer-Plugin_Please_Update_Jar", plugin.getRequiredJarTime()}); + FRLogger.getLogger().error(jarExpiredInfo); + throw new com.fr.plugin.PluginVerifyException(jarExpiredInfo); + } + File fileToCheck = getTempPluginFileDirectory(); + File oldfile = new File(StableUtils.pathJoin(FRContext.getCurrentEnv().getPath(), ProjectConstants.PLUGINS_NAME, "plugin-" + plugin.getId())); + if (!PluginManagerHelper.checkLic(plugin, fileToCheck)) { + if (!PluginManagerHelper.checkLic(plugin, oldfile)) {//安装时,在安装目录下和压缩包里都没有才弹框 + String checkLicFail = Inter.getLocText("FR-Designer-PluginLicense_Check_Failed"); + FRLogger.getLogger().error(checkLicFail); + throw new com.fr.plugin.PluginVerifyException(checkLicFail); + } + } + } + + /** + * 获取插件解压的临时文件夹 + * + * @return 临时文件 + */ + public static File getTempPluginFileDirectory() { + File file = new File(TEMP_PATH); + if (file.isDirectory() && !file.getName().startsWith(".")) { + File[] files = file.listFiles(); + if (ArrayUtils.isNotEmpty(files)) { + for (File f : files) { + if (foundConfigFile(f)) { + return f; + } + } + } + } + return null; + } + + private static boolean foundConfigFile(File dir) { + if (!dir.isDirectory()) { + return false; + } + File[] files = dir.listFiles(); + if (ArrayUtils.isNotEmpty(files)) { + for (File f : files) { + if ("plugin.xml".equals(f.getName())) { + return true; + } + } + } + return false; + } + + /** + * 从运行环境中卸载插件 + * + * @param env 报表运行环境 + * @param plugin 插件 + * @return 返回没有删除掉的文件的集合 + * @throws Exception 卸载出错的时候抛出此异常 + */ + public static String[] uninstallPlugin(Env env, Plugin plugin) throws Exception { + if (plugin == null || env == null) { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + PluginLoader.getLoader().deletePlugin(plugin); + return env.deleteFileFromPluginAndLibFolder(plugin); + } + + /** + * 比较插件的版本,这里简单的比价字符串,不需要用数字作为标号 + * 版本号相同也认为是更新 + * + * @param plugin 当前的插件 + * @param oldPlugin 老的插件 + * @return 当前插件比老的插件版本高则返回true,否则返回false + */ + public static boolean isNewThan(Plugin plugin, Plugin oldPlugin) { + return ComparatorUtils.compare(plugin.getVersion(), oldPlugin.getVersion()) >= 0; + } + + private static String sendInstalledPluginInfo(final Plugin plugin) { + if (StableUtils.isDebug()) { + return "debug status"; + } + HashMap map = new HashMap(); + map.put("key", DesignerEnvManager.getEnvManager().getActivationKey()); + map.put("detail", plugin.toJSONObject().toString()); + map.put("build", GeneralUtils.readBuildNO()); + //第三个参数encode, nodejs服务器那边如果参数不encode, 带了空格会报错, 直接用urlconnection也是一样, jetty没能还原. + HttpClient httpClient = new HttpClient(PluginConstants.PLUGIN_INSTALL_INFO, map, true); + httpClient.setTimeout(TIME_OUT); + httpClient.asGet(); + return httpClient.getResponseText(); + } + + private static final int TIME_OUT = 5000; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginInstalledPane.java b/designer_base/src/com/fr/design/extra/PluginInstalledPane.java new file mode 100644 index 0000000000..9d4ecd6d39 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginInstalledPane.java @@ -0,0 +1,143 @@ +package com.fr.design.extra; + +import com.fr.base.FRContext; +import com.fr.design.RestartHelper; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.general.Inter; +import com.fr.plugin.Plugin; +import com.fr.plugin.PluginLoader; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginInstalledPane extends PluginAbstractViewPane { + + private int num; + private UIButton disableButton; + private UIButton deleteButton; + private PluginControlPane controlPane; + + + public PluginInstalledPane() { + setLayout(new BorderLayout()); + controlPane = new PluginControlPane(); + add(controlPane, BorderLayout.CENTER); + + JPanel panel = createOperationPane(); + + add(panel, BorderLayout.SOUTH); + + disableButton = new UIButton(Inter.getLocText("FR-Designer-Plugin_Disable")); + disableButton.setEnabled(false); + deleteButton = new UIButton(Inter.getLocText("FR-Designer-Plugin_Delete")); + deleteButton.setEnabled(false); + panel.add(disableButton); + panel.add(deleteButton); + controlPane.addPluginSelectionListener(new PluginSelectListener() { + @Override + public void valueChanged(Plugin plugin) { + disableButton.setEnabled(true); + deleteButton.setEnabled(true); + changeTextForButton(plugin); + } + }); + disableButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Plugin plugin = controlPane.getSelectedPlugin(); + if (plugin != null) { + plugin.setActive(!plugin.isActive()); + changeTextForButton(plugin); + try { + FRContext.getCurrentEnv().writePlugin(plugin); + int rv = JOptionPane.showOptionDialog( + PluginInstalledPane.this, + plugin.isActive() ? Inter.getLocText("FR-Designer-Plugin_Has_Been_Actived") : Inter.getLocText("FR-Designer-Plugin_Has_Been_Disabled"), + Inter.getLocText("FR-Designer-Plugin_Warning"), + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + new String[]{Inter.getLocText("FR-Designer-Basic_Restart_Designer"), Inter.getLocText("FR-Designer-Basic_Restart_Designer_Later")}, + null + ); + if (rv == JOptionPane.OK_OPTION) { + RestartHelper.restart(); + } + } catch (Exception e1) { + FRContext.getLogger().error(e1.getMessage(), e1); + } + } + } + }); + deleteButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + doDelete(controlPane.getSelectedPlugin()); + } + }); + + PluginLoader loader = PluginLoader.getLoader(); + Plugin[] plugins = loader.getInstalled(); + controlPane.loadPlugins(plugins); + num = plugins.length; + } + + /** + * tab标题 + * @return 同上 + */ + public String tabTitle() { + return Inter.getLocText("FR-Designer-Plugin_Installed") + "(" + num + ")"; + } + + private void doDelete(Plugin plugin) { + int rv = JOptionPane.showOptionDialog( + PluginInstalledPane.this, + Inter.getLocText("FR-Designer-Plugin_Will_Be_Delete"), + Inter.getLocText("FR-Designer-Plugin_Warning"), + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + new String[]{Inter.getLocText("FR-Designer-Basic_Restart_Designer"), + Inter.getLocText("FR-Designer-Basic_Restart_Designer_Later"), + Inter.getLocText("FR-Designer-Basic_Cancel") + }, + null + ); + if (rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { + return; + } + + try { + String[] filesToBeDelete = PluginHelper.uninstallPlugin(FRContext.getCurrentEnv(), plugin); + controlPane.deletePlugin(plugin); + RestartHelper.saveFilesWhichToDelete(filesToBeDelete); + } catch (Exception e) { + JOptionPane.showMessageDialog(PluginInstalledPane.this, e.getMessage(), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + } + + if (rv == JOptionPane.OK_OPTION) { + RestartHelper.restart(); + } + } + + private void changeTextForButton(Plugin plugin) { + if (plugin.isActive()) { + disableButton.setText(Inter.getLocText("FR-Designer-Plugin_Disable")); + } else { + disableButton.setText(Inter.getLocText("FR-Designer-Plugin_Active")); + } + } + + @Override + protected String title4PopupWindow() { + return "Installed"; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginListPane.java b/designer_base/src/com/fr/design/extra/PluginListPane.java new file mode 100644 index 0000000000..59259034a2 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginListPane.java @@ -0,0 +1,16 @@ +package com.fr.design.extra; + +import com.fr.design.dialog.BasicPane; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginListPane extends BasicPane { + + @Override + protected String title4PopupWindow() { + return "Plugin"; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginManagerPane.java b/designer_base/src/com/fr/design/extra/PluginManagerPane.java new file mode 100644 index 0000000000..d2e267ed07 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginManagerPane.java @@ -0,0 +1,63 @@ +package com.fr.design.extra; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.StableUtils; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.concurrent.Worker; +import javafx.scene.web.WebEngine; + +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.swing.*; +import java.awt.*; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +/** + * @author richie + * @date 2015-03-09 + * @since 8.0 + * 应用中心的构建采用JavaScript代码来动态实现,但是不总是依赖于服务器端的HTML + * 采用JDK提供的JavaScript引擎,实际是用JavaScript语法实现Java端的功能,并通过JavaScript引擎动态调用 + * JavaScript放在安装目录下的scripts/store目录下,检测到新版本的时候,可以通过更新这个目录下的文件实现热更新 + * 不直接嵌入WebView组件的原因是什么呢? + * 因为如果直接嵌入WebView,和设计器的交互就需要预先设定好,这样灵活性会差很多,而如果使用JavaScript引擎, + * 就可以直接在JavaScript中和WebView组件做交互,而同时JavaScript中可以调用任何的设计器API. + */ +public class PluginManagerPane extends BasicPane { + + + public PluginManagerPane() { + setLayout(new BorderLayout()); + if (StableUtils.isDebug()) { + URL url = ClassLoader.getSystemResource(""); + String installHome = url.getPath(); + PluginWebPane webPane = new PluginWebPane(installHome); + add(webPane, BorderLayout.CENTER); + } else { + initTraditionalStore(); + } + } + + private void initTraditionalStore() { + UITabbedPane tabbedPane = new UITabbedPane(); + add(tabbedPane, BorderLayout.CENTER); + PluginInstalledPane installedPane = new PluginInstalledPane(); + tabbedPane.addTab(installedPane.tabTitle(), installedPane); + tabbedPane.addTab(Inter.getLocText("FR-Designer-Plugin_Update"), new PluginUpdatePane(tabbedPane)); + tabbedPane.addTab(Inter.getLocText("FR-Designer-Plugin_All_Plugins"), new PluginFromStorePane(tabbedPane)); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer-Plugin_Manager"); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginSelectListener.java b/designer_base/src/com/fr/design/extra/PluginSelectListener.java new file mode 100644 index 0000000000..b1962335b7 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginSelectListener.java @@ -0,0 +1,13 @@ +package com.fr.design.extra; + +import com.fr.plugin.Plugin; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public interface PluginSelectListener { + + public void valueChanged(Plugin plugin); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginStatusCheckCompletePane.java b/designer_base/src/com/fr/design/extra/PluginStatusCheckCompletePane.java new file mode 100644 index 0000000000..cf772d5d66 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginStatusCheckCompletePane.java @@ -0,0 +1,78 @@ +package com.fr.design.extra; + +import com.fr.design.gui.ibutton.UIButton; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author richie + * @date 2015-03-11 + * @since 8.0 + */ +public abstract class PluginStatusCheckCompletePane extends PluginAbstractViewPane { + + private UIButton installButton; + private JProgressBar progressBar; + + + public PluginStatusCheckCompletePane() { + setLayout(new BorderLayout()); + JComponent controlPane = centerPane(); + add(controlPane, BorderLayout.CENTER); + JPanel pane = createOperationPane(); + add(pane, BorderLayout.SOUTH); + installButton = new UIButton(textForInstallButton()); + installButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + pressInstallButton(); + } + }); + installButton.setEnabled(false); + UIButton installFromDiskButton = new UIButton(textForInstallFromDiskButton()); + installFromDiskButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + pressInstallFromDiskButton(); + } + }); + pane.add(installButton); + pane.add(installFromDiskButton); + + progressBar = new JProgressBar(); + progressBar.setVisible(false); + progressBar.setIndeterminate(false); + progressBar.setStringPainted(true); + progressBar.setPreferredSize(new Dimension(600, 20)); + pane.add(progressBar); + } + + + public abstract void pressInstallButton(); + + public abstract void pressInstallFromDiskButton(); + + public abstract String textForInstallButton(); + + public abstract String textForInstallFromDiskButton(); + + public abstract JComponent centerPane(); + + public void setInstallButtonEnable(boolean enable) { + installButton.setEnabled(enable); + } + + public void setProgress(double percent) { + progressBar.setVisible(true); + progressBar.setValue((int)percent); + progressBar.setString((int)percent + "%"); + progressBar.repaint(); + } + + public void didTaskFinished() { + progressBar.setVisible(false); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginTask.java b/designer_base/src/com/fr/design/extra/PluginTask.java new file mode 100644 index 0000000000..e67f4e426e --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginTask.java @@ -0,0 +1,53 @@ +package com.fr.design.extra; + +import com.fr.design.extra.exe.Executor; +import com.fr.design.extra.exe.Command; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.concurrent.Task; +import javafx.scene.web.WebEngine; +import netscape.javascript.JSObject; + +/** + * 插件安装,卸载,更新等任务 + * @param + */ +public class PluginTask extends Task { + + private Executor executor; + + public PluginTask(final WebEngine webEngine, final JSObject callback, final Executor executor) { + init(webEngine, callback); + this.executor = executor; + } + + private void init(final WebEngine webEngine, final JSObject callback) { + messageProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, String oldValue, String newValue) { + String fun = "(" + callback + ")('" + newValue + "')"; + try { + webEngine.executeScript(fun); + } catch (Exception e) { + webEngine.executeScript("alert(\"" + e.getMessage() + "\")"); + } + } + }); + } + + @Override + protected T call() throws Exception { + Command[] commands = executor.getCommands(); + for (Command command : commands) { + String message = command.getExecuteMessage(); + updateMessage(message); + command.run(); + } + return null; + } + + @Override + protected void done() { + updateMessage(executor.getTaskFinishMessage()); + } +} diff --git a/designer_base/src/com/fr/design/extra/PluginUpdatePane.java b/designer_base/src/com/fr/design/extra/PluginUpdatePane.java new file mode 100644 index 0000000000..e635af336e --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginUpdatePane.java @@ -0,0 +1,276 @@ +package com.fr.design.extra; + +import com.fr.base.FRContext; +import com.fr.design.DesignerEnvManager; +import com.fr.design.RestartHelper; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.general.Inter; +import com.fr.plugin.Plugin; +import com.fr.plugin.PluginLoader; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.File; +import java.util.List; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginUpdatePane extends PluginAbstractLoadingViewPane { + + private PluginControlPane controlPane; + private JLabel errorMsgLabel; + private UITabbedPane tabbedPane; + + private static final int PERSENT = 100; + + public PluginUpdatePane(UITabbedPane tabbedPane) { + super(tabbedPane); + this.tabbedPane = tabbedPane; + } + + /** + * 更新pane + * @return 同上 + */ + public JPanel createSuccessPane() { + return new PluginStatusCheckCompletePane() { + + @Override + public void pressInstallButton() { + doUpdateOnline(this); + } + + @Override + public void pressInstallFromDiskButton() { + installFromDiskFile(); + } + + @Override + public String textForInstallButton() { + return Inter.getLocText("FR-Designer_Plugin_Normal_Update"); + } + + + + @Override + public String textForInstallFromDiskButton() { + return Inter.getLocText("FR-Designer_Plugin_Normal_Update_From_Local"); + } + + @Override + public JPanel centerPane() { + controlPane = new PluginControlPane(); + final PluginStatusCheckCompletePane s = this; + controlPane.addPluginSelectionListener(new PluginSelectListener() { + @Override + public void valueChanged(Plugin plugin) { + s.setInstallButtonEnable(true); + } + }); + return controlPane; + } + }; + } + + /** + * 出错pane + * @return 同上 + */ + @Override + public JPanel createErrorPane() { + errorMsgLabel = new UILabel(); + errorMsgLabel.setHorizontalAlignment(SwingConstants.CENTER); + + return new PluginStatusCheckCompletePane() { + + @Override + public void pressInstallButton() { + doUpdateOnline(this); + } + + @Override + public void pressInstallFromDiskButton() { + installFromDiskFile(); + } + + @Override + public String textForInstallButton() { + return Inter.getLocText("FR-Designer_Plugin_Normal_Update"); + } + + + + @Override + public String textForInstallFromDiskButton() { + return Inter.getLocText("FR-Designer_Plugin_Normal_Update_From_Local"); + } + + @Override + public JComponent centerPane() { + return errorMsgLabel; + } + }; + } + + /** + * 加载插件 + * @return 所有插件 + */ + public Plugin[] loadData() throws Exception { + return PluginsReaderFromStore.readPluginsForUpdate(); + } + + /** + * 加载成功处理 + * + * @param plugins 插件 + */ + public void loadOnSuccess(Plugin[] plugins) { + controlPane.loadPlugins(plugins); + tabbedPane.setTitleAt(1, Inter.getLocText("FR-Designer-Plugin_Update") + "(" + plugins.length + ")"); + } + + /** + * 加载失败处理 + * + * @param e 异常 + */ + public void loadOnFailed(Exception e) { + errorMsgLabel.setText(e.getCause().getMessage()); + } + + /** + * 略 + * @return 略 + */ + @Override + public String textForLoadingLabel() { + return Inter.getLocText("FR-Designer-Plugin_Detecting_Update"); + } + + protected void installFromDiskFile() { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.setFileFilter(new FileNameExtensionFilter("zip", "zip")); + int returnValue = fileChooser.showOpenDialog(PluginUpdatePane.this); + if (returnValue == JFileChooser.APPROVE_OPTION) { + final File chosenFile = fileChooser.getSelectedFile(); + doUpdateFromFile(chosenFile); + } + } + + private void doUpdateOnline(final PluginStatusCheckCompletePane pane) { + if (StringUtils.isNotEmpty(DesignerEnvManager.getEnvManager().getBBSName())){ + new SwingWorker(){ + + @Override + protected Void doInBackground() throws Exception { + Plugin plugin = controlPane.getSelectedPlugin(); + String id = null; + if (plugin != null) { + id = plugin.getId(); + } + String username = DesignerEnvManager.getEnvManager().getBBSName(); + String password = DesignerEnvManager.getEnvManager().getBBSPassword(); + try { + PluginHelper.downloadPluginFile(id,username,password, new Process() { + @Override + public void process(Double integer) { + publish(integer); + } + }); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return null; + } + + public void process(List list) { + pane.setProgress(list.get(list.size() - 1) * PERSENT); + } + + public void done() { + //下载完成,开始执行安装 + try { + get(); + pane.didTaskFinished(); + doUpdateFromFile(PluginHelper.getDownloadTempFile()); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + }.execute(); + } else { + LoginCheckContext.fireLoginCheckListener(); + } + + } + + private void doUpdateFromFile(File chosenFile) { + try { + Plugin plugin = PluginHelper.readPlugin(chosenFile); + if (plugin == null) { + JOptionPane.showMessageDialog(PluginUpdatePane.this, Inter.getLocText("FR-Designer-Plugin_Illegal_Plugin_Zip"), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + return; + } + Plugin oldPlugin = PluginLoader.getLoader().getPluginById(plugin.getId()); + if (oldPlugin != null) { + // 说明安装了同ID的插件,再比较两个插件的版本 + if (PluginHelper.isNewThan(plugin, oldPlugin)) { + // 说明是新的插件,删除老的然后安装新的 + final String[] files = PluginHelper.uninstallPlugin(FRContext.getCurrentEnv(), oldPlugin); + PluginHelper.installPluginFromUnzippedTempDir(FRContext.getCurrentEnv(), plugin, new After() { + @Override + public void done() { + int rv = JOptionPane.showOptionDialog( + PluginUpdatePane.this, + Inter.getLocText("FR-Designer-Plugin_Update_Successful"), + Inter.getLocText("FR-Designer-Plugin_Warning"), + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + new String[]{Inter.getLocText("FR-Designer-Basic_Restart_Designer"), + Inter.getLocText("FR-Designer-Basic_Restart_Designer_Later") + }, + null + ); + + if (rv == JOptionPane.OK_OPTION) { + RestartHelper.restart(); + } + + // 如果不是立即重启,就把要删除的文件存放起来 + if (rv == JOptionPane.CANCEL_OPTION || rv == JOptionPane.CLOSED_OPTION) { + RestartHelper.saveFilesWhichToDelete(files); + } + } + }); + } else { + JOptionPane.showMessageDialog(PluginUpdatePane.this, Inter.getLocText("FR-Designer-Plugin_Version_Is_Lower_Than_Current"), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + } + } else { + JOptionPane.showMessageDialog(PluginUpdatePane.this, Inter.getLocText("FR-Designer-Plugin_Cannot_Update_Not_Install"), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + } + } catch (Exception e1) { + JOptionPane.showMessageDialog(PluginUpdatePane.this, e1.getMessage(), Inter.getLocText("FR-Designer-Plugin_Warning"), JOptionPane.ERROR_MESSAGE); + } + } + + /** + * 从磁盘安装按钮的提示 + * @return 按钮标题字符串 + */ + @Override + public String textForInstallFromDiskFileButton() { + return Inter.getLocText("FR-Designer_Plugin_Normal_Update_From_Local"); + } + @Override + protected String title4PopupWindow() { + return "Update"; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/PluginWebBridge.java b/designer_base/src/com/fr/design/extra/PluginWebBridge.java new file mode 100644 index 0000000000..b4eb6e9e1c --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginWebBridge.java @@ -0,0 +1,177 @@ +package com.fr.design.extra; + +import com.fr.design.extra.exe.*; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.plugin.Plugin; +import com.fr.plugin.PluginLoader; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; +import javafx.concurrent.Task; +import javafx.scene.web.WebEngine; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import netscape.javascript.JSObject; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * 开放给Web组件的接口,用于安装,卸载,更新以及更改插件可用状态 + */ +public class PluginWebBridge { + + private static PluginWebBridge helper; + + public static PluginWebBridge getHelper(WebEngine webEngine) { + if (helper != null) { + return helper; + } + synchronized (PluginWebBridge.class) { + if (helper == null) { + helper = new PluginWebBridge(webEngine); + } + return helper; + } + } + + private WebEngine webEngine; + + private PluginWebBridge(WebEngine webEngine) { + this.webEngine = webEngine; + } + + /** + * 从插件服务器上安装插件 + * + * @param pluginID 插件的ID + * @param callback 回调函数 + */ + public void installPluginOnline(final String pluginID, final JSObject callback) { + Task task = new PluginTask<>(webEngine, callback, new InstallOnlineExecutor(pluginID)); + new Thread(task).start(); + } + + /** + * 从磁盘上选择插件安装包进行安装 + * + * @param filePath 插件包的路径 + */ + public void installPluginFromDisk(final String filePath, final JSObject callback) { + Task task = new PluginTask<>(webEngine, callback, new InstallFromDiskExecutor(filePath)); + new Thread(task).start(); + } + + /** + * 卸载当前选中的插件 + * + * @param pluginIDs 插件集合 + */ + public void uninstallPlugin(JSObject pluginIDs, final JSObject callback) { + Task task = new PluginTask<>(webEngine, callback, new UninstallExecutor(jsObjectToStringArray(pluginIDs))); + new Thread(task).start(); + } + + /** + * 从插件服务器上更新选中的插件 + * + * @param pluginID 插件的ID + */ + public void updatePluginOnline(String pluginID, final JSObject callback) { + Task task = new PluginTask<>(webEngine, callback, new UpdateOnlineExecutor(pluginID)); + new Thread(task).start(); + } + + /** + * 从磁盘上选择插件安装包进行插件升级 + * + * @param filePath 插件包的路径 + */ + public void updatePluginFromDisk(String filePath, final JSObject callback) { + Task task = new PluginTask<>(webEngine, callback, new UpdateFromDiskExecutor(filePath)); + new Thread(task).start(); + } + + /** + * 修改选中的插件的活跃状态 + * + * @param pluginID 插件ID + * @param active 如果要把插件修改为激活状态,则为true,否则为false + */ + public void setPluginActive(String pluginID, boolean active, final JSObject callback) { + Task task = new PluginTask<>(webEngine, callback, new ModifyStatusExecutor(pluginID, active)); + new Thread(task).start(); + } + + /** + * 选择文件对话框 + * + * @return 选择的文件的路径 + */ + public String showFileChooser() { + return showFileChooserWithFilter(StringUtils.EMPTY, StringUtils.EMPTY); + } + + /** + * 选择文件对话框 + * + * @param des 过滤文件描述 + * @param filter 文件的后缀 + * @return 选择的文件的路径 + */ + public String showFileChooserWithFilter(String des, String filter) { + FileChooser fileChooser = new FileChooser(); + + if (StringUtils.isNotEmpty(filter)) { + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(des, filter)); + } + + File selectedFile = fileChooser.showOpenDialog(new Stage()); + if (selectedFile == null) { + return null; + } + return selectedFile.getAbsolutePath(); + } + + /** + * 选择文件对话框 + * + * @param des 过滤文件描述 + * @param args 文件的后缀 + * @return 选择的文件的路径 + */ + public String showFileChooserWithFilters(String des, JSObject args) { + FileChooser fileChooser = new FileChooser(); + String[] filters = jsObjectToStringArray(args); + if (ArrayUtils.isNotEmpty(filters)) { + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(des, filters)); + } + + File selectedFile = fileChooser.showOpenDialog(new Stage()); + if (selectedFile == null) { + return null; + } + return selectedFile.getAbsolutePath(); + } + + /** + * 获取已经安装的插件的数组 + * @return 已安装的插件组成的数组 + */ + public Plugin[] getInstalledPlugins() { + return PluginLoader.getLoader().getInstalled(); + } + + private String[] jsObjectToStringArray(JSObject obj) { + if (obj == null) { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + int len = (int) obj.getMember("length"); + List list = new ArrayList<>(); + for (int i = 0; i < len; i++) { + list.add(obj.getSlot(i).toString()); + } + return list.toArray(new String[len]); + } +} diff --git a/designer_base/src/com/fr/design/extra/PluginWebPane.java b/designer_base/src/com/fr/design/extra/PluginWebPane.java new file mode 100644 index 0000000000..8b899220fb --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginWebPane.java @@ -0,0 +1,58 @@ +package com.fr.design.extra; + +import javafx.application.Platform; +import javafx.embed.swing.JFXPanel; +import javafx.event.EventHandler; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebEvent; +import javafx.scene.web.WebView; +import netscape.javascript.JSObject; + +import javax.swing.*; + +/** + * Created by richie on 16/3/19. + */ +public class PluginWebPane extends JFXPanel { + + private WebEngine webEngine; + + public PluginWebPane(final String installHome) { + Platform.setImplicitExit(false); + Platform.runLater(new Runnable() { + @Override + public void run() { + Group root = new Group(); + Scene scene = new Scene(root); + PluginWebPane.this.setScene(scene); + WebView webView = new WebView(); + webEngine = webView.getEngine(); + webEngine.load("file:///" + installHome + "/scripts/store/web/index.html"); + webEngine.setOnAlert(new EventHandler>() { + @Override + public void handle(WebEvent event) { + showAlert(event.getData()); + } + }); + JSObject obj = (JSObject) webEngine.executeScript("window"); + obj.setMember("PluginHelper", PluginWebBridge.getHelper(webEngine)); + root.getChildren().add(webView); + } + }); + } + + private void showAlert(final String message) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JOptionPane.showMessageDialog(PluginWebPane.this, message); + } + }); +// Dialog alert = new Dialog<>(); +// alert.getDialogPane().setContentText(message); +// alert.getDialogPane().getButtonTypes().add(ButtonType.OK); +// alert.showAndWait(); + } +} diff --git a/designer_base/src/com/fr/design/extra/PluginsReaderFromStore.java b/designer_base/src/com/fr/design/extra/PluginsReaderFromStore.java new file mode 100644 index 0000000000..533ef33abe --- /dev/null +++ b/designer_base/src/com/fr/design/extra/PluginsReaderFromStore.java @@ -0,0 +1,99 @@ +package com.fr.design.extra; + +import com.fr.general.GeneralUtils; +import com.fr.general.Inter; +import com.fr.general.http.HttpClient; +import com.fr.json.JSONArray; +import com.fr.json.JSONException; +import com.fr.plugin.Plugin; +import com.fr.plugin.PluginLoader; +import com.fr.stable.EncodeConstants; +import com.fr.stable.StringUtils; + +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +/** + * @author richie + * @date 2015-03-10 + * @since 8.0 + */ +public class PluginsReaderFromStore { + private static Set plugins = new HashSet(); + private static Set pluginsToUpdate = new HashSet(); + + /** + * 从插件商店服务器读取插件信息,以JSON形式返回 + * + * @return 插件信息 + */ + public static Plugin[] readPlugins() throws Exception { + String resText; + try { + HttpClient httpClient = new HttpClient(PluginConstants.PLUGIN_STORE_URL); + resText = httpClient.getResponseText(); + String charSet = EncodeConstants.ENCODING_UTF_8; + resText = URLDecoder.decode(URLDecoder.decode(resText, charSet), charSet); + } catch (Exception e) { + throw new Exception(Inter.getLocText("FR-Designer-Plugin_PluginMarket_Coding")); + } + if (StringUtils.isNotEmpty(resText)) { + try { + plugins.clear();//先清空set + JSONArray jsonArray = new JSONArray(resText); + for (int i = 0, size = jsonArray.length(); i < size; i++) { + Plugin plugin = new Plugin(); + plugin.parseJSON(jsonArray.optJSONObject(i)); + if (plugin.isValidate()) { + plugins.add(plugin); + } + } + } catch (JSONException e) { + throw new Exception(Inter.getLocText("FR-Designer-Plugin_Read_Plugin_List_Error")); + } + } + + return plugins.toArray(new Plugin[plugins.size()]); + } + + /** + * 从插件商店服务器读取插件信息,以JSON形式返回 + * + * @return 插件信息 + */ + public static Plugin[] readPluginsForUpdate() throws Exception { + String resText; + try { + HashMap para = new HashMap(); + para.put("plugins", PluginLoader.getLoader().pluginsToString()); + //只有当前设计器的jar高于插件新版本需要的jarTime时, 才提示更新该插件. + para.put("jarTime", GeneralUtils.readBuildNO()); + HttpClient httpClient = new HttpClient(PluginConstants.PLUGIN_CHECK_UPDATE_URL, para); + resText = httpClient.getResponseText(); + String charSet = EncodeConstants.ENCODING_UTF_8; + resText = URLDecoder.decode(URLDecoder.decode(resText, charSet), charSet); + } catch (Exception e) { + throw new Exception(Inter.getLocText("FR-Designer-Plugin_PluginMarket_Coding")); + } + if (StringUtils.isNotEmpty(resText)) { + try { + pluginsToUpdate.clear(); + JSONArray jsonArray = new JSONArray(resText); + for (int i = 0, size = jsonArray.length(); i < size; i++) { + Plugin plugin = new Plugin(); + plugin.parseJSON(jsonArray.optJSONObject(i)); + if (plugin.isValidate()) { + pluginsToUpdate.add(plugin); + } + } + } catch (JSONException e) { + throw new Exception(Inter.getLocText("FR-Designer-Plugin_Read_Plugin_List_Error")); + } + } + + return pluginsToUpdate.toArray(new Plugin[pluginsToUpdate.size()]); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/Process.java b/designer_base/src/com/fr/design/extra/Process.java new file mode 100644 index 0000000000..9ec4589aab --- /dev/null +++ b/designer_base/src/com/fr/design/extra/Process.java @@ -0,0 +1,11 @@ +package com.fr.design.extra; + +/** + * @author richie + * @date 2015-03-11 + * @since 8.0 + */ +public interface Process { + + public void process(V v); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/extra/exe/Command.java b/designer_base/src/com/fr/design/extra/exe/Command.java new file mode 100644 index 0000000000..5b117586e5 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/Command.java @@ -0,0 +1,11 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public interface Command { + + String getExecuteMessage(); + + void run(); +} diff --git a/designer_base/src/com/fr/design/extra/exe/Executor.java b/designer_base/src/com/fr/design/extra/exe/Executor.java new file mode 100644 index 0000000000..f0eeafdd02 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/Executor.java @@ -0,0 +1,11 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public interface Executor { + + String getTaskFinishMessage(); + + Command[] getCommands(); +} diff --git a/designer_base/src/com/fr/design/extra/exe/InstallFromDiskExecutor.java b/designer_base/src/com/fr/design/extra/exe/InstallFromDiskExecutor.java new file mode 100644 index 0000000000..098a91c029 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/InstallFromDiskExecutor.java @@ -0,0 +1,54 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public class InstallFromDiskExecutor implements Executor { + private String filePath; + + public InstallFromDiskExecutor(String filePath) { + this.filePath = filePath; + + } + + @Override + public String getTaskFinishMessage() { + return "已成功安装"; + } + + @Override + public Command[] getCommands() { + return new Command[]{ + new Command() { + @Override + public String getExecuteMessage() { + return "正在解压文件" + filePath; + } + + @Override + public void run() { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }, + new Command() { + @Override + public String getExecuteMessage() { + return "正在安装"; + } + + @Override + public void run() { + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }; + } +} diff --git a/designer_base/src/com/fr/design/extra/exe/InstallOnlineExecutor.java b/designer_base/src/com/fr/design/extra/exe/InstallOnlineExecutor.java new file mode 100644 index 0000000000..7baf378fd2 --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/InstallOnlineExecutor.java @@ -0,0 +1,54 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public class InstallOnlineExecutor implements Executor { + + private String pluginID; + + public InstallOnlineExecutor(String pluginID) { + this.pluginID = pluginID; + } + + @Override + public String getTaskFinishMessage() { + return "已成功安裝"; + } + + @Override + public Command[] getCommands() { + return new Command[]{ + new Command() { + @Override + public String getExecuteMessage() { + return "正在下载插件:" + pluginID; + } + + @Override + public void run() { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }, + new Command() { + @Override + public String getExecuteMessage() { + return "正在安装插件:" + pluginID; + } + + @Override + public void run() { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + }; + } +} diff --git a/designer_base/src/com/fr/design/extra/exe/ModifyStatusExecutor.java b/designer_base/src/com/fr/design/extra/exe/ModifyStatusExecutor.java new file mode 100644 index 0000000000..ff5d82bd5f --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/ModifyStatusExecutor.java @@ -0,0 +1,25 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public class ModifyStatusExecutor implements Executor { + + private String pluginID; + private boolean active; + + public ModifyStatusExecutor(String pluginID, boolean active) { + this.pluginID = pluginID; + this.active = active; + } + + @Override + public String getTaskFinishMessage() { + return "插件" + pluginID + "已更改为可用状态:" + active; + } + + @Override + public Command[] getCommands() { + return new Command[0]; + } +} diff --git a/designer_base/src/com/fr/design/extra/exe/UninstallExecutor.java b/designer_base/src/com/fr/design/extra/exe/UninstallExecutor.java new file mode 100644 index 0000000000..5138c1a58a --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/UninstallExecutor.java @@ -0,0 +1,23 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public class UninstallExecutor implements Executor { + + private String[] pluginIDs; + + public UninstallExecutor(String[] pluginIDs) { + this.pluginIDs = pluginIDs; + } + + @Override + public String getTaskFinishMessage() { + return "插件已卸载完毕,重启后生效"; + } + + @Override + public Command[] getCommands() { + return new Command[0]; + } +} diff --git a/designer_base/src/com/fr/design/extra/exe/UpdateFromDiskExecutor.java b/designer_base/src/com/fr/design/extra/exe/UpdateFromDiskExecutor.java new file mode 100644 index 0000000000..cfc0ab222a --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/UpdateFromDiskExecutor.java @@ -0,0 +1,23 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public class UpdateFromDiskExecutor implements Executor { + + private String filePath; + + public UpdateFromDiskExecutor(String filePath) { + this.filePath = filePath; + } + + @Override + public String getTaskFinishMessage() { + return "插件已更新完毕"; + } + + @Override + public Command[] getCommands() { + return new Command[0]; + } +} diff --git a/designer_base/src/com/fr/design/extra/exe/UpdateOnlineExecutor.java b/designer_base/src/com/fr/design/extra/exe/UpdateOnlineExecutor.java new file mode 100644 index 0000000000..a5f49ea6ea --- /dev/null +++ b/designer_base/src/com/fr/design/extra/exe/UpdateOnlineExecutor.java @@ -0,0 +1,23 @@ +package com.fr.design.extra.exe; + +/** + * Created by richie on 16/3/19. + */ +public class UpdateOnlineExecutor implements Executor { + + private String pluginID; + + public UpdateOnlineExecutor(String pluginID) { + this.pluginID = pluginID; + + } + @Override + public String getTaskFinishMessage() { + return "插件已更新完毕:" + pluginID; + } + + @Override + public Command[] getCommands() { + return new Command[0]; + } +} diff --git a/designer_base/src/com/fr/design/extra/plugin.properties b/designer_base/src/com/fr/design/extra/plugin.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/designer_base/src/com/fr/design/file/FileOperations.java b/designer_base/src/com/fr/design/file/FileOperations.java new file mode 100644 index 0000000000..c46735d5c7 --- /dev/null +++ b/designer_base/src/com/fr/design/file/FileOperations.java @@ -0,0 +1,45 @@ +package com.fr.design.file; + + +public interface FileOperations { + /** + *打开选中的报表文件 + */ + public void openSelectedReport(); + + /** + *打开文件夹 + */ + public void openContainerFolder(); + + /** + *刷新 + */ + public void refresh(); + + /** + *删除文件 + */ + public void deleteFile(); + + /** + *加上文件锁 + */ + public void lockFile(); + + /** + *文件解锁 + */ + public void unLockFile(); + + public String getSelectedTemplatePath(); + + /** + *文件名是否存在 + * @param newName 原名 + * @param oldName 新的文件名 + * @param suffix 后缀名 + * @return 是否存在 + */ + public boolean isNameAlreadyExist(String newName, String oldName, String suffix); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/file/FileToolbarStateChangeListener.java b/designer_base/src/com/fr/design/file/FileToolbarStateChangeListener.java new file mode 100644 index 0000000000..a4cd3c125c --- /dev/null +++ b/designer_base/src/com/fr/design/file/FileToolbarStateChangeListener.java @@ -0,0 +1,5 @@ +package com.fr.design.file; + +public interface FileToolbarStateChangeListener { + public void stateChange(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/file/HistoryTemplateListPane.java b/designer_base/src/com/fr/design/file/HistoryTemplateListPane.java new file mode 100644 index 0000000000..26aa72f146 --- /dev/null +++ b/designer_base/src/com/fr/design/file/HistoryTemplateListPane.java @@ -0,0 +1,376 @@ +package com.fr.design.file; + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.*; +import java.util.List; +import java.util.logging.Level; + +import javax.swing.*; + +import com.fr.design.constants.UIConstants; +import com.fr.design.DesignerEnvManager; +import com.fr.design.gui.ilable.UILabel; + +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import com.fr.base.FRContext; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.dav.LocalEnv; +import com.fr.design.DesignModelAdapter; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilist.UIList; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.file.filetree.FileNode; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.Constants; +import com.fr.stable.project.ProjectConstants; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class HistoryTemplateListPane extends JPanel implements FileOperations { + private static final int LIST_BORDER = 4; + private List> historyList; + private JTemplate editingTemplate; + private FileToolbarStateChangeListener toobarStateChangeListener; + + private static HistoryTemplateListPane THIS; + + private UIList list; + + public static final HistoryTemplateListPane getInstance() { + if (THIS == null) { + THIS = new HistoryTemplateListPane(); + } + return THIS; + } + + public HistoryTemplateListPane() { + setLayout(new BorderLayout()); + historyList = new ArrayList>(); + list = new UIList(new HistoryListDataMode()) { + public int locationToIndex(Point location) { + int rowCount = getModel().getSize(); + int height = getPreferredSize().height - 2 * LIST_BORDER; + int rowHeight = height / rowCount; + int index = (location.y - LIST_BORDER) / rowHeight; + if (location.y < LIST_BORDER || index > rowCount - 1) { + return -1; + } else { + return index; + } + } + }; + ToolTipManager.sharedInstance().registerComponent(list); + list.setBackground(UIConstants.NORMAL_BACKGROUND); + list.setCellRenderer(new HistoryListCellRender()); + list.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() < 2) { + return; + } + openSelectedReport(); + } + }); + + + list.addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + if (toobarStateChangeListener != null) { + toobarStateChangeListener.stateChange(); + } + + } + }); + list.setBorder(BorderFactory.createEmptyBorder(LIST_BORDER, LIST_BORDER, LIST_BORDER, LIST_BORDER)); + UIScrollPane scrollPane = new UIScrollPane(list); + scrollPane.setBorder(null); + + this.add(scrollPane, BorderLayout.CENTER); + + } + + /** + *关闭选择的文件 + * @param selected 选择的 + */ + public void closeSelectedReport(JTemplate selected) { + if (contains(selected) == -1) { + return; + } + selected.fireJTemplateClosed(); + selected.stopEditing(); + try { + historyList.remove(contains(selected)); + selected.getEditingFILE().closeTemplate(); + FRLogger.getLogger().log(Level.INFO, Inter.getLocText(new String[]{"Template", "alraedy_close"}, new String[]{selected.getEditingFILE().getName(), "."})); + MutilTempalteTabPane.getInstance().refreshOpenedTemplate(historyList); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + } + + public JTemplate getCurrentEditingTemplate() { + return this.editingTemplate; + } + + public void setCurrentEditingTemplate(JTemplate jt) { + this.editingTemplate = jt; + //如果当前历史面板中没有 + + if (contains(jt) == -1) { + addHistory(); + } + MutilTempalteTabPane.getInstance().refreshOpenedTemplate(historyList); + //设置tab栏为当前选中的那一栏 + if (editingTemplate != null) { + MutilTempalteTabPane.getInstance().setSelectedIndex(contains(jt)); + } + + } + + /** + * 添加历史记录 + */ + public void addHistory() { + if (editingTemplate == null) { + return; + } + DesignerEnvManager.getEnvManager().addRecentOpenedFilePath(editingTemplate.getFullPathName()); + ((HistoryListDataMode) list.getModel()).add(editingTemplate); + } + + + public List> getHistoryList() { + return historyList; + } + + + /** + * 清空历史记录 + */ + public void removeAllHistory() { + historyList.clear(); + this.editingTemplate = null; + } + + public int getHistoryCount() { + return list.getModel().getSize(); + } + + + public UIList getList() { + return list; + } + + + public JTemplate get(int index) { + return (JTemplate) list.getModel().getElementAt(index); + } + + + public JTemplate getTemplate(int index) { + return historyList.get(index); + } + + /** + * 获取模板的index + * + * @param jt 模板 + * @return 位置 + */ + public int contains(JTemplate jt) { + for (int i = 0; i < historyList.size(); i++) { + if (ComparatorUtils.equals(historyList.get(i).getEditingFILE(), jt.getEditingFILE())) { + return i; + } + } + return -1; + } + + + /** + * 判断是否打开过该模板 + * @param filename 文件名 + * @return 文件位置 + */ + public int contains(String filename) { + for (int i = 0; i < historyList.size(); i++) { + String historyPath = historyList.get(i).getFullPathName(); + if (ComparatorUtils.equals(historyPath, filename)) { + return i; + } + } + return -1; + } + + /** + * 是否是当前编辑的文件 + * @param filename 文件名 + * @return 是则返回TRUE + */ + public boolean isCurrentEditingFile(String filename) { + String editingFileName = editingTemplate.getFullPathName(); + return ComparatorUtils.equals(filename, editingFileName); + } + + + private class HistoryListCellRender extends DefaultListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, final boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + JTemplate jt = (JTemplate) value; + UILabel nameLabel = new UILabel(jt.getEditingFILE().getName()); + final int nameWidth = nameLabel.getPreferredSize().width; + UILabel uiLabel = new UILabel() { + public void paint(Graphics g) { + GUIPaintUtils.fillPaint((Graphics2D) g, 18, 0, nameWidth + 2, getHeight(), true, Constants.NULL, isSelected ? UIConstants.FLESH_BLUE : UIConstants.NORMAL_BACKGROUND, UIConstants.ARC); + super.paint(g); + } + + }; + uiLabel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0)); + uiLabel.setIcon(jt.getIcon()); + uiLabel.setText(jt.getEditingFILE().getName()); + return uiLabel; + } + + } + + + private class HistoryListDataMode extends AbstractListModel { + + @Override + public int getSize() { + return historyList.size(); + } + + @Override + public JTemplate getElementAt(int index) { + if (index > getSize() - 1 || index < 0) { + return null; + } + Collections.reverse(historyList); + JTemplate select = historyList.get(index); + Collections.reverse(historyList); + return select; + } + + public void remove(int index) { + boolean outofindex = index >= historyList.size() || index < 0; + if (historyList.isEmpty() || outofindex) { + return; + } + historyList.remove(index); + } + + public void add(JTemplate jt) { + historyList.add(jt); + refresh(); + } + } + + /** + * 刷新 + */ + public void refresh() { + list.removeAll(); + list.setModel(new HistoryListDataMode()); + list.setSelectedIndex(list.getSelectedIndex()); + } + + /** + * 打开选择的文件 + */ + public void openSelectedReport() { + DesignerContext.getDesignerFrame().addAndActivateJTemplate((JTemplate) list.getSelectedValue()); + TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + refresh(); + } + + /** + * 打开文件所在文件夹 + */ + public void openContainerFolder() { + FileNode fileNode = new FileNode(((JTemplate) list.getSelectedValue()).getEditingFILE().getPath(), false); + LocalEnv localEnv = (LocalEnv) FRContext.getCurrentEnv(); + localEnv.openContainerFolder(fileNode); + } + + /** + * 删除文件 + */ + public void deleteFile() { +// TODO Auto-generated method stub + + } + + /*** + * 琐文件 + */ + public void lockFile() { +// TODO Auto-generated method stub + + } + + /** + * 解锁 + */ + public void unLockFile() { +// TODO Auto-generated method stub + + } + + /** + * 路径 + * @return 路径 + */ + public String getSelectedTemplatePath() { + if (list.getSelectedIndex() < 0 || list.getSelectedIndex() > list.getModel().getSize() - 1) { + return null; + } + ; + String path = ((HistoryListDataMode) list.getModel()).getElementAt(list.getSelectedIndex()).getEditingFILE().getPath(); + if (path.startsWith(ProjectConstants.REPORTLETS_NAME)) { + return path.substring(ProjectConstants.REPORTLETS_NAME.length()); + } + return path; + } + + public void setToobarStateChangeListener(FileToolbarStateChangeListener toobarStateChangeListener) { + this.toobarStateChangeListener = toobarStateChangeListener; + } + + /** + * 文件是否存在 + * + * @param newName 文件名 + * @param oldName 原名 + * @param suffix 后缀名 + * @return 文件是否存在 + */ + public boolean isNameAlreadyExist(String newName, String oldName, String suffix) { + boolean isNameAreadyExist = false; + for (int i = 0; i < getHistoryCount(); i++) { + JTemplate jt = ((HistoryListDataMode) list.getModel()).getElementAt(i); + if (ComparatorUtils.equals(jt.getEditingFILE().getName(), newName + suffix)) { + isNameAreadyExist = true; + break; + } + } + if (ComparatorUtils.equals(newName, oldName)) { + isNameAreadyExist = false; + } + + return isNameAreadyExist; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/file/MutilTempalteTabPane.java b/designer_base/src/com/fr/design/file/MutilTempalteTabPane.java new file mode 100644 index 0000000000..15c0f0bfbf --- /dev/null +++ b/designer_base/src/com/fr/design/file/MutilTempalteTabPane.java @@ -0,0 +1 @@ +package com.fr.design.file; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.event.AWTEventListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Arc2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.RoundRectangle2D; import java.io.File; import java.util.logging.Level; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.plaf.basic.BasicMenuItemUI; import com.fr.base.BaseUtils; import com.fr.base.GraphHelper; import com.fr.design.constants.UIConstants; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.gui.imenu.UIScrollPopUpMenu; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUIPaintUtils; import com.fr.file.FILE; import com.fr.file.FileNodeFILE; import com.fr.general.ComparatorUtils; import com.fr.general.FRLogger; import com.fr.general.Inter; import com.fr.stable.Constants; import com.fr.stable.ProductConstants; import com.fr.stable.project.ProjectConstants; /** * Author : daisy * Date: 13-8-5 * Time: 下午6:12 */ public class MutilTempalteTabPane extends JComponent implements MouseListener, MouseMotionListener, Action { private static Icon LIST_DOWN = BaseUtils.readIcon("/com/fr/design/images/buttonicon/list_normal.png"); private static Icon MOUSE_OVER_LIST_DOWN = BaseUtils.readIcon("/com/fr/design/images/buttonicon/list_pressed.png"); private static Icon MOUSE_PRESS_LIST_DOWN = BaseUtils.readIcon("/com/fr/design/images/buttonicon/list_pressed.png"); private static Icon CLOSE = BaseUtils.readIcon("/com/fr/design/images/buttonicon/close_icon.png"); private static Icon MOUSE_OVER_CLOSE = BaseUtils.readIcon("/com/fr/design/images/buttonicon/mouseoverclose icon.png"); private static Icon MOUSE_PRESS_CLOSE = BaseUtils.readIcon("/com/fr/design/images/buttonicon/pressclose icon.png"); private static final String ELLIPSIS = "..."; private static final int GAP_BEFORE_CLOSE = 10; private static final int GAP = 5; private static final int SMALLGAP = 3; private static final int LIST_BUTTON_WIDTH = 34; private static final int HEIGHT = 26; private static final int LIST_DOWN_HEIGHT = 25; private static final double FOR_CAL_BYTES = 0.5; private static final double CORNOR_RADIUS = 0.0; //选了30度和60度的特殊角度的x,y作为经过的两个点的坐标 private static final double SPECIAL_LOCATION_1 = 2.5; private static final double SPECIAL_LOCATION_2 = 4.330127; private static final int ICON_WIDTH = 22; //每个标签页的最大的长度和最小长度。这些长度均为均分 private static final int MAXWIDTH = 240; private static final int MINWIDTH = 100; private static MutilTempalteTabPane THIS; //用于存放工作簿 private java.util.List> openedTemplate; //选中的Tab项 private int selectedIndex = 0; // private int mouseOveredIndex = -1; //tab栏可以放下的每个tab的实际宽度 private int realWidth = MAXWIDTH; //当前标签页栏存放的所有标签页的index private int minPaintIndex = 0; private int maxPaintIndex = 0; /** * 鼠标按下时的坐标数组、鼠标放开时的坐标数组 */ private int[] xyPressedCoordinate = {0, 0}; //每个关闭图标的起始位置 private int[] startX; private boolean[] isNeedToolTips; private Graphics2D g2d; //记录关闭按钮的状态 private int closeIconIndex = -1; private boolean isCloseCurrent = false; private Icon clodeMode = CLOSE; private Icon listDownMode = LIST_DOWN; private boolean isShowList = false; //自动新建的模板B若没有进行任何编辑,切换到其他 // // 模板时,模板B会自动关闭 private JTemplate temTemplate = null; private AWTEventListener awt = new AWTEventListener() { public void eventDispatched(AWTEvent event) { if (event instanceof MouseEvent) { MouseEvent mv = (MouseEvent) event; if (mv.getClickCount() > 0 && !ComparatorUtils.equals(mv.getSource(), MutilTempalteTabPane.this)) { isShowList = false; } } } }; public static final MutilTempalteTabPane getInstance() { if (THIS == null) { THIS = new MutilTempalteTabPane(); } return THIS; } public JTemplate getSelectedFile() { return openedTemplate.get(selectedIndex); } /** * 关闭掉当前已打开文件列表中指定的文件 * * @param file 指定的文件 * */ public void closeFileTemplate(FILE file){ for (JTemplate temp : openedTemplate) { if(ComparatorUtils.equals(file, temp.getEditingFILE())){ closeSpecifiedTemplate(temp); break; } } } public Dimension getPreferredSize() { Dimension dimension = super.getPreferredSize(); dimension.height = HEIGHT; return dimension; } /** * 多工作簿面板 */ public MutilTempalteTabPane() { this.setLayout(new BorderLayout(0, 0)); this.addMouseListener(this); this.addMouseMotionListener(this); this.setBorder(null); this.setForeground(new Color(99, 99, 99)); this.setFont(new Font(Inter.getLocText("FR-Designer_Song_TypeFace"), 0, 12)); openedTemplate = HistoryTemplateListPane.getInstance().getHistoryList(); selectedIndex = openedTemplate.size() - 1; Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); } private UIMenuItem initCloseOther() { UIMenuItem closeOther = new UIMenuItem(Inter.getLocText("FR-Designer_FS_Close_Other_Templates")); setListDownItemPreferredSize(closeOther); closeOther.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (openedTemplate.size() == 1) { return; } SaveSomeTemplatePane saveSomeTempaltePane = new SaveSomeTemplatePane(false); //点击关闭其他模板,并且点击确定保存 if (saveSomeTempaltePane.showSavePane()) { for (int i = 0; i < openedTemplate.size(); i++) { if (i != selectedIndex) { //判断关闭的模板是不是格式刷的被参照的模板 closeFormat(openedTemplate.get(i)); HistoryTemplateListPane.getInstance().closeSelectedReport(openedTemplate.get(i)); } } JTemplate currentTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); HistoryTemplateListPane.getInstance().removeAllHistory(); DesignerContext.getDesignerFrame().activateJTemplate(currentTemplate); THIS.repaint(); } //如果取消保存了,则不关闭其他模板 } }); if (openedTemplate.size() == 1) { closeOther.setEnabled(false); } return closeOther; } private UIMenuItem[] createListDownTemplate() { UIMenuItem[] templates = new UIMenuItem[openedTemplate.size()]; for (int i = 0; i < openedTemplate.size(); i++) { final int index = i; final JTemplate tem = openedTemplate.get(i); templates[i] = new UIMenuItem(tempalteShowName(tem), tem.getIcon()); templates[i].setUI(new UIListDownItemUI()); setListDownItemPreferredSize(templates[i]); if (i == selectedIndex) { //画选中的高亮 templates[i].setBackground(UIConstants.SHADOW_CENTER); } templates[i].addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { selectedIndex = index; DesignerContext.getDesignerFrame().addAndActivateJTemplate(tem); } }); } return templates; } private void setListDownItemPreferredSize(UIMenuItem item) { Dimension dimension = item.getPreferredSize(); dimension.height = LIST_DOWN_HEIGHT; item.setPreferredSize(dimension); } private String tempalteShowName(JTemplate template) { String name = template.getEditingFILE().getName(); if (!template.isSaved() && !name.endsWith(" *")) { name += " *"; } return name; } /** * 刷新打开模板 * @param history 模板 */ public void refreshOpenedTemplate(java.util.List> history) { openedTemplate = history; } public void setTemTemplate(JTemplate auotCreate) { temTemplate = auotCreate; } private void showListDown() { UIScrollPopUpMenu menu = new UIScrollPopUpMenu(); menu.setBorder(BorderFactory.createEmptyBorder(-3, 3, 3, 0)); menu.add(initCloseOther()); JSeparator separator = new JSeparator() { public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); d.height = 1; return d; } }; menu.add(new JPanel() { public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); d.height = 1; return d; } }); separator.setForeground(UIConstants.LINE_COLOR); menu.add(separator); menu.add(new JPanel() { public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); d.height = 1; return d; } }); UIMenuItem[] items = createListDownTemplate(); for (int i = 0; i < items.length; i++) { menu.add(items[i]); } GUICoreUtils.showPopupMenu(menu, MutilTempalteTabPane.getInstance(), MutilTempalteTabPane.getInstance().getWidth() - menu.getPreferredSize().width, getY() - 1 + getHeight()); } public void setSelectedIndex(int index) { selectedIndex = index; } public void paintComponent(Graphics g) { super.paintComponent(g); double maxWidth = getWidth() - LIST_BUTTON_WIDTH; //最大宽度 g2d = (Graphics2D) g; paintBackgroundAndLine(g2d, maxWidth); } private void paintBackgroundAndLine(Graphics2D g2d, double maxWidth) { paintDefaultBackground(g2d); //最多能画的个数 int maxTemplateNum = (int) (maxWidth) / MINWIDTH; //计算开始画的最小模板index和最大模板index calMinAndMaxIndex(maxTemplateNum); calculateRealAverageWidth(maxWidth, maxTemplateNum); int maxStringlength = calculateStringMaxLength(); if (selectedIndex >= openedTemplate.size()) { selectedIndex = openedTemplate.size() - 1; } if (selectedIndex < 0) { selectedIndex = 0; } double templateStartX = 0; startX = new int[maxPaintIndex - minPaintIndex + 1]; isNeedToolTips = new boolean[maxPaintIndex - minPaintIndex + 1]; //从可以开始展示在tab面板上的tab开始画 for (int i = minPaintIndex; i <= maxPaintIndex; i++) { JTemplate template = openedTemplate.get(i); Icon icon = template.getIcon(); String name = tempalteShowName(template); //如果tab名字的长度大于最大能显示的英文字符长度,则进行省略号处理 if (getStringWidth(name) > maxStringlength) { name = getEllipsisName(name, maxStringlength); isNeedToolTips[i - minPaintIndex] = true; } else { isNeedToolTips[i - minPaintIndex] = false; } Icon selectedIcon = null; if (i == closeIconIndex) { selectedIcon = clodeMode; } else { selectedIcon = CLOSE; } if (i == selectedIndex) { startX[i - minPaintIndex] = paintSelectedTab(g2d, icon, templateStartX, name, selectedIcon); } else { boolean isLeft = i < selectedIndex; startX[i - minPaintIndex] = paintUnSelectedTab(g2d, icon, templateStartX, name, selectedIcon, isLeft, mouseOveredIndex, i); } templateStartX += realWidth; } paintListDown(g2d, maxWidth); paintUnderLine(templateStartX, maxWidth, g2d); } private void paintUnderLine(double templateStartX, double maxWidth, Graphics2D g2d) { //画下面的那条线 if (templateStartX < maxWidth) { GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, 2); generalPath.moveTo((float) templateStartX, getHeight() - 1); generalPath.lineTo((float) maxWidth, getHeight() - 1); g2d.fill(generalPath); g2d.setPaint(UIConstants.LINE_COLOR); g2d.draw(new Line2D.Double((float) templateStartX, getHeight() - 1, (float) maxWidth + LIST_BUTTON_WIDTH, getHeight() - 1)); } } private void paintDefaultBackground(Graphics2D g2d) { //画默认背景 g2d.setPaint(new GradientPaint(1, 1, UIConstants.SHADOW_GREY, 1, getHeight() - 1, UIConstants.SHADOW_GREY)); g2d.fillRect(getX(), getY(), getWidth(), getHeight()); } private void paintListDown(Graphics2D g2d, double maxWidth) { int x = (int) maxWidth + (LIST_BUTTON_WIDTH - listDownMode.getIconWidth()) / 2; int y = (getHeight() - listDownMode.getIconHeight()) / 2; listDownMode.paintIcon(this, g2d, x, y); } /** * 判断tab文字的长度大于能装下的最大文字长度,要用省略号 * * @param name * @param maxStringlength * @return */ private String getEllipsisName(String name, int maxStringlength) { //若是名字长度大于能显示的长度,那能显示的文字的最大长度还要减去省略号的最大长度 // int maxellipsislength = maxStringlength - ELLIPSIS.length(); int ellipsisWidth = getStringWidth(ELLIPSIS); int leftkeyPoint = 0; int rightKeyPoint = name.length() - 1; int leftStrWidth = 0; int rightStrWidth = 0; while (leftStrWidth + rightStrWidth + ellipsisWidth < maxStringlength) { if (leftStrWidth <= rightStrWidth) { leftkeyPoint++; } else { rightKeyPoint--; } leftStrWidth = getStringWidth(name.substring(0, leftkeyPoint)); rightStrWidth = getStringWidth(name.substring(rightKeyPoint)); if (leftStrWidth + rightStrWidth + ellipsisWidth > maxStringlength) { if (leftStrWidth <= rightStrWidth) { rightKeyPoint++; } break; } } return name.substring(0, leftkeyPoint) + ELLIPSIS + name.substring(rightKeyPoint); } private void calMinAndMaxIndex(int maxTemplateNum) { //如果个数大于最多能容纳的个数,则多余的进行处理 if (openedTemplate.size() > maxTemplateNum) { //所点击列表中的标签页处在标签页栏最后一个标签页之后,则标签页栏左移至所点击标签页出现 if (selectedIndex >= maxPaintIndex) { minPaintIndex = selectedIndex - maxTemplateNum + 1; maxPaintIndex = selectedIndex; if (minPaintIndex <= 0) { minPaintIndex = 0; maxPaintIndex = maxTemplateNum - 1; } } else if (selectedIndex <= minPaintIndex) { //所点击列表中的标签页处在标签页栏第一个标签页之前,则标签页栏右移至所点击标签页出现 minPaintIndex = selectedIndex; maxPaintIndex = minPaintIndex + maxTemplateNum - 1; if (maxPaintIndex > openedTemplate.size() - 1) { maxPaintIndex = openedTemplate.size() - 1; } } else { if (selectedIndex >= openedTemplate.size() - 1) { selectedIndex = openedTemplate.size() - 1; maxPaintIndex = selectedIndex; minPaintIndex = selectedIndex - maxTemplateNum + 1; } else { maxPaintIndex = minPaintIndex + maxTemplateNum - 1; if (maxPaintIndex > openedTemplate.size() - 1) { maxPaintIndex = openedTemplate.size() - 1; } } } } else { minPaintIndex = 0; maxPaintIndex = openedTemplate.size() - 1; } } //个数小于最多能容纳的个数的情况下,看看宽度每个要画多少 private void calculateRealAverageWidth(double maxwidth, int templateNum) { int num = openedTemplate.size() > templateNum ? templateNum : openedTemplate.size(); realWidth = (int) (maxwidth / (num)); if (realWidth > MAXWIDTH) { realWidth = MAXWIDTH; } else if (realWidth < MINWIDTH) { //平均下来每个的宽度小于最小宽度 realWidth = MINWIDTH; } } /** * 计算过长度之后的每个tab的能接受的文字的英文字符数 * * @return */ private int calculateStringMaxLength() { return realWidth - 3 * GAP - ICON_WIDTH - SMALLGAP - CLOSE.getIconWidth(); } private int getStringWidth(String str) { return GraphHelper.getFontMetrics(this.getFont()).stringWidth(str); } /** * 画选中的tab * * @param g2d * @param sheeticon * @param templateStartX * @param sheetName * @param closeIcon * @return */ private int paintSelectedTab(Graphics2D g2d, Icon sheeticon, double templateStartX, String sheetName, Icon closeIcon) { double[] x = {templateStartX, templateStartX, templateStartX + realWidth, templateStartX + realWidth, templateStartX}; double[] y = {-1, getHeight(), getHeight(), -1, -1}; RoundRectangle2D.Double rect1 = new RoundRectangle2D.Double(templateStartX, 1, this.getWidth(), this.getHeight(), 7, 7); g2d.setPaint(new GradientPaint(1, 1, UIConstants.NORMAL_BACKGROUND, 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); //选了30度和60度的特殊角度的x,y作为经过的两个点的坐标 double specialLocation1 = 2.5; double specialLocation2 = 4.330127; GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length); generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); generalPath.curveTo(((float) x[0] + CORNOR_RADIUS - specialLocation1), (y[0] + CORNOR_RADIUS - specialLocation2), ((float) x[0] + CORNOR_RADIUS - specialLocation2), (y[0] + CORNOR_RADIUS - specialLocation1), x[0], y[0] + CORNOR_RADIUS); for (int index = 1; index <= 2; index++) { generalPath.lineTo((float) x[index], (float) y[index]); } generalPath.lineTo((float) x[3], (float) y[3] + CORNOR_RADIUS); generalPath.curveTo(((float) x[3] - CORNOR_RADIUS + specialLocation1), ((float) y[3] + CORNOR_RADIUS - specialLocation2), ((float) x[3] - CORNOR_RADIUS + specialLocation2), ((float) y[3] + CORNOR_RADIUS - specialLocation1), (float) x[3] - CORNOR_RADIUS, (float) y[3]); generalPath.lineTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); generalPath.closePath(); g2d.fill(generalPath); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setPaint(UIConstants.LINE_COLOR); g2d.draw(new Arc2D.Double(x[0], y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0)); g2d.draw(new Line2D.Double(x[0], y[0] + CORNOR_RADIUS, x[1], y[1])); g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2])); g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3] + CORNOR_RADIUS)); g2d.draw(new Arc2D.Double(x[3] - CORNOR_RADIUS * 2, y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0)); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); int sheetIconY = (getHeight() - sheeticon.getIconHeight()) / 2; sheeticon.paintIcon(this, g2d, (int) templateStartX + GAP, sheetIconY); // 画字符 g2d.setPaint(getForeground()); g2d.drawString(sheetName, (int) templateStartX + sheeticon.getIconWidth() + 2 * GAP, getHeight() - GAP * 2); int closePosition = (int) templateStartX + realWidth - CLOSE.getIconWidth() - SMALLGAP; int closeY = (getHeight() - closeIcon.getIconHeight()) / 2; closeIcon.paintIcon(this, g2d, closePosition, closeY); return closePosition; } /** * 画没有选中的tab * * @param g2d * @param sheeticon * @param templateStartX * @param sheetName * @param closeIcon * @param isLeft * @return */ private int paintUnSelectedTab(Graphics2D g2d, Icon sheeticon, double templateStartX, String sheetName, Icon closeIcon, boolean isLeft, int mouseOveredIndex, int selfIndex) { double[] x = {templateStartX, templateStartX, templateStartX + realWidth, templateStartX + realWidth, templateStartX}; double[] y = {-1, getHeight() - 1, getHeight() - 1, -1, -1}; if (selfIndex == mouseOveredIndex) { g2d.setPaint(new GradientPaint(1, 1, UIConstants.HOVER_BLUE, 1, getHeight() - 1, UIConstants.HOVER_BLUE)); } else { g2d.setPaint(new GradientPaint(1, 1, UIConstants.SHADOW_GREY, 1, getHeight() - 1, UIConstants.SHADOW_GREY)); } GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length); unSelectedClosedPath(generalPath, isLeft, x, y); g2d.fill(generalPath); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setPaint(UIConstants.LINE_COLOR); if (isLeft) { g2d.draw(new Arc2D.Double(x[0], y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0)); } else { g2d.draw(new Arc2D.Double(x[0] - CORNOR_RADIUS * 2, y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0)); } g2d.draw(new Line2D.Double(x[0], y[0] + CORNOR_RADIUS, x[1], y[1] + 1)); g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2])); g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3] + CORNOR_RADIUS)); if (isLeft) { g2d.draw(new Arc2D.Double(x[3], y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0)); } else { g2d.draw(new Arc2D.Double(x[3] - CORNOR_RADIUS * 2, y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0)); } g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); int sheetIconY = (getHeight() - sheeticon.getIconHeight()) / 2; sheeticon.paintIcon(this, g2d, (int) templateStartX + GAP, sheetIconY); // 画字符 g2d.setPaint(getForeground()); g2d.drawString(sheetName, (int) templateStartX + sheeticon.getIconWidth() + 2 * GAP, getHeight() - GAP * 2); int closeY = (getHeight() - closeIcon.getIconHeight()) / 2; int closePosition = (int) templateStartX + realWidth - CLOSE.getIconWidth() - SMALLGAP; closeIcon.paintIcon(this, g2d, closePosition, closeY); return closePosition; } private void unSelectedClosedPath(GeneralPath generalPath, boolean isLeft, double[] x, double[] y) { if (isLeft) { generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); generalPath.curveTo(((float) x[0] + CORNOR_RADIUS - SPECIAL_LOCATION_1), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[0] + CORNOR_RADIUS - SPECIAL_LOCATION_2), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_1), x[0], y[0] + CORNOR_RADIUS); } else { generalPath.moveTo((float) x[0] - CORNOR_RADIUS, (float) y[0]); generalPath.curveTo(((float) x[0] - CORNOR_RADIUS + SPECIAL_LOCATION_1), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[0] - CORNOR_RADIUS + SPECIAL_LOCATION_2), (y[0] + CORNOR_RADIUS - SPECIAL_LOCATION_1), x[0], y[0] + CORNOR_RADIUS); } for (int index = 1; index <= 2; index++) { generalPath.lineTo((float) x[index], (float) y[index]); } generalPath.lineTo((float) x[3], (float) y[3] + CORNOR_RADIUS); if (isLeft) { generalPath.curveTo(((float) x[3] + CORNOR_RADIUS - SPECIAL_LOCATION_1), ((float) y[3] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[3] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) y[3] - CORNOR_RADIUS + SPECIAL_LOCATION_1), (float) x[3] + CORNOR_RADIUS, (float) y[3]); generalPath.lineTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); } else { generalPath.curveTo(((float) x[3] - CORNOR_RADIUS + SPECIAL_LOCATION_1), ((float) y[3] + CORNOR_RADIUS - SPECIAL_LOCATION_2), ((float) x[3] - CORNOR_RADIUS + SPECIAL_LOCATION_2), ((float) y[3] + CORNOR_RADIUS - SPECIAL_LOCATION_1), (float) x[3] - CORNOR_RADIUS, (float) y[3]); generalPath.lineTo((float) x[0] - CORNOR_RADIUS, (float) y[0]); } generalPath.closePath(); } /** * 点击 * @param e 鼠标事件 */ public void mouseClicked(MouseEvent e) { } /** * 按下 * @param e 鼠标事件 */ public void mousePressed(MouseEvent e) { int evtX = e.getX(); int evtY = e.getY(); this.setPressedXY(evtX, evtY); //是否点击关闭按钮 如果点击了关闭按钮,则将点击的模板关闭,不需要切换,如果没有点击关闭按钮,则切换到点击的模板处 boolean isOverCloseIcon = isOverCloseIcon(evtX); if (isOverListDown(evtX)) { listDownMode = isOverListDown(evtX) ? MOUSE_PRESS_LIST_DOWN : LIST_DOWN; if (!isShowList) { showListDown(); } isShowList = !isShowList; } else if (isOverCloseIcon) { //关闭按钮的图标变化 closeIconIndex = getTemplateIndex(evtX); clodeMode = MOUSE_PRESS_CLOSE; //关闭close图标所在的模板{ closeFormat(openedTemplate.get(closeIconIndex)); closeSpecifiedTemplate(openedTemplate.get(closeIconIndex)); DesignerContext.getDesignerFrame().getContentFrame().repaint(); isShowList = false; } else { //没有点击关闭和ListDown按钮,则切换到点击的模板处 closeIconIndex = -1; clodeMode = CLOSE; int tempSelectedIndex = selectedIndex; if (selectedIndex != getTemplateIndex(evtX) && getTemplateIndex(evtX) != -1) { openedTemplate.get(selectedIndex).stopEditing(); selectedIndex = getTemplateIndex(evtX); //如果在权限编辑情况下,不允许切换到表单类型的工作簿 if(BaseUtils.isAuthorityEditing() && !openedTemplate.get(selectedIndex).isJWorkBook()){ DesignerContext.getDesignerFrame().addAndActivateJTemplate(openedTemplate.get(tempSelectedIndex)); JOptionPane.showMessageDialog(this, Inter.getLocText("FR-Designer_Form-AuthorityEdited_Cannot_be_Supported") + "!", Inter.getLocText("FR-Designer_Alert"), JOptionPane.WARNING_MESSAGE); this.repaint(); return; } DesignerContext.getDesignerFrame().addAndActivateJTemplate(openedTemplate.get(getTemplateIndex(evtX))); } isShowList = false; } this.repaint(); } public void setIsCloseCurrent(boolean isCloseCurrent) { this.isCloseCurrent = isCloseCurrent; } /** * 关闭模板 * @param specifiedTemplate 模板 */ public void closeSpecifiedTemplate(JTemplate specifiedTemplate) { if (specifiedTemplate == null) { return; } //当前激活的模板 String filename = openedTemplate.get(selectedIndex).getEditingFILE().getPath(); if (filename.startsWith(ProjectConstants.REPORTLETS_NAME)) { filename = ((FileNodeFILE) openedTemplate.get(selectedIndex).getEditingFILE()).getEnvPath() + File.separator + filename; } filename = filename.replaceAll("/", "\\\\"); if (!specifiedTemplate.isALLSaved()) { specifiedTemplate.stopEditing(); int returnVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Utils-Would_you_like_to_save") + " \"" + specifiedTemplate.getEditingFILE() + "\" ?", ProductConstants.PRODUCT_NAME, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (returnVal == JOptionPane.YES_OPTION && specifiedTemplate.saveTemplate()) { specifiedTemplate.saveTemplate(); FRLogger.getLogger().log(Level.INFO, Inter.getLocText(new String[]{"Template", "already-saved"}, new String[]{specifiedTemplate.getEditingFILE().getName(), "."})); HistoryTemplateListPane.getInstance().closeSelectedReport(specifiedTemplate); activeTemplate(filename); } else if (returnVal == JOptionPane.NO_OPTION) { //不保存 HistoryTemplateListPane.getInstance().closeSelectedReport(specifiedTemplate); activeTemplate(filename); } //若是点击取消关闭,则什么都不做 } else { //若是已经保存过了,则关闭即可 HistoryTemplateListPane.getInstance().closeSelectedReport(specifiedTemplate); activeTemplate(filename); } } /** * 关闭模板 * @param closedTemplate 模板 */ public void closeFormat(JTemplate closedTemplate) { //表单不需要处理 if (!closedTemplate.isJWorkBook()) { return; } if (DesignerContext.getFormatState() == DesignerContext.FORMAT_STATE_NULL) { return; } //是被参照的模板被关闭,则重置格式刷 closedTemplate.doConditionCancelFormat(); } /** * 关闭掉一个模板之后该激活的Tab * * @param fileName */ private void activeTemplate(String fileName) { if (openedTemplate.isEmpty()) { //新建并激活模板 DesignerContext.getDesignerFrame().addAndActivateJTemplate(); selectedIndex = 0; //此时刚自动新建的模板在HistoryTemplateListPane的editingTemplate temTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); } else { //如果关闭的模板是当前选中的模板,则重新激活 if (closeIconIndex == selectedIndex) { if (closeIconIndex == maxPaintIndex) { selectedIndex -= 1; } } else if (isCloseCurrent) { //不是通过关闭按钮,而是通过文件关闭菜单关闭的当前模板的,也重新激活 if (selectedIndex > openedTemplate.size() - 1) { selectedIndex -= 1; if (selectedIndex < 0) { selectedIndex = 0; } isCloseCurrent = false; } } else { //如果关闭的模板不是当前选中的模板,则激活的模板不变 selectedIndex = HistoryTemplateListPane.getInstance().contains(fileName); } DesignerContext.getDesignerFrame().activateJTemplate(openedTemplate.get(selectedIndex)); } } /** * 鼠标释放 * @param e 鼠标事件 */ public void mouseReleased(MouseEvent e) { } /** * 鼠标进入 * @param e 鼠标事件 */ public void mouseEntered(MouseEvent e) { } private boolean isOverCloseIcon(int evtX) { boolean isOverCloseIcon = false; for (int i = 0; i < startX.length; i++) { if (evtX >= startX[i] && evtX <= startX[i] + CLOSE.getIconWidth()) { isOverCloseIcon = true; break; } } return isOverCloseIcon; } private boolean isOverListDown(int evtX) { int maxWidth = getWidth() - LIST_BUTTON_WIDTH; return evtX >= (maxWidth + SMALLGAP) && evtX <= (getWidth() - SMALLGAP); } private int getTemplateIndex(int evtX) { int textX = 0; for (int i = minPaintIndex; i <= maxPaintIndex; i++) { int textWidth = realWidth; if (evtX >= textX && evtX < textX + textWidth) { return i; } textX += textWidth; } return -1; } /** * 鼠标离开 * @param e 鼠标事件 */ public void mouseExited(MouseEvent e) { listDownMode = LIST_DOWN; closeIconIndex = -1; mouseOveredIndex = -1; this.repaint(); } /** * 鼠标拖拽 * @param e 鼠标事件 */ public void mouseDragged(MouseEvent e) { } /** * 鼠标移动 * @param e 鼠标事件 */ public void mouseMoved(MouseEvent e) { int evtX = e.getX(); mouseOveredIndex = getTemplateIndex(evtX); //看是否需要显示toolTip if (mouseOveredIndex != -1 && isNeedToolTips[mouseOveredIndex - minPaintIndex]) { setToolTipText(openedTemplate.get(mouseOveredIndex).getEditingFILE().getName()); } else { setToolTipText(null); } listDownMode = isOverListDown(evtX) ? MOUSE_OVER_LIST_DOWN : LIST_DOWN; boolean isOverCloseIcon = isOverCloseIcon(evtX); clodeMode = isOverCloseIcon ? MOUSE_OVER_CLOSE : CLOSE; closeIconIndex = isOverCloseIcon ? mouseOveredIndex : -1; this.repaint(); } private void setPressedXY(int x, int y) { this.xyPressedCoordinate[0] = x; this.xyPressedCoordinate[1] = y; } public Object getValue(String key) { return null; } /** * 加入值 * @param key 键 * @param value 值 */ public void putValue(String key, Object value) { } /** * 动作 * @param e 事件 */ public void actionPerformed(ActionEvent e) { } /** * 处理自动新建的模板 在切换时的处理 */ public void doWithtemTemplate() { //temtemplate保存的一定是手动新建的没有编辑或是编辑了没有保存的模板 //没有保存,说明有编辑;已经保存在磁盘里的文件,说明有过处理,并且已经保存,此时切换都不将其自动关闭 if (temTemplate == null || temTemplate == HistoryTemplateListPane.getInstance().getCurrentEditingTemplate()) { return; } if (!temTemplate.isSaved() || !temTemplate.getEditingFILE().isMemFile()) { temTemplate = null; } //自动新建的模板B若没有进行任何编辑(新建模板没有进行任何编辑时saved都是true):还没有存盘 if (temTemplate != null && temTemplate.getEditingFILE().isMemFile() && temTemplate.isSaved()) { HistoryTemplateListPane.getInstance().closeSelectedReport(temTemplate); temTemplate = null; setSelectedIndex(HistoryTemplateListPane.getInstance().contains(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate())); } } private class UIListDownItemUI extends BasicMenuItemUI { @Override protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { if (menuItem.getIcon() == null) { super.paintBackground(g, menuItem, bgColor); return; } ButtonModel model = menuItem.getModel(); Color oldColor = g.getColor(); int menuWidth = menuItem.getWidth(); int menuHeight = menuItem.getHeight(); g.setColor(UIConstants.NORMAL_BACKGROUND); g.fillRect(0, 0, menuWidth, menuHeight); boolean itemIsSelected = menuItem instanceof JMenu && model.isSelected(); if (menuItem.isOpaque()) { if (model.isArmed() || itemIsSelected) { GUIPaintUtils.fillPaint((Graphics2D) g, GAP, 0, menuWidth - GAP, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, UIConstants.ARC); } else { GUIPaintUtils.fillPaint((Graphics2D) g, GAP, 0, menuWidth - GAP, menuHeight, true, Constants.NULL, menuItem.getBackground(), UIConstants.ARC); } g.setColor(oldColor); } else if (model.isArmed() || itemIsSelected) { GUIPaintUtils.fillPaint((Graphics2D) g, GAP, 0, menuWidth - GAP, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, UIConstants.ARC); g.setColor(oldColor); } } } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/file/NewTemplatePane.java b/designer_base/src/com/fr/design/file/NewTemplatePane.java new file mode 100644 index 0000000000..c9af8808f8 --- /dev/null +++ b/designer_base/src/com/fr/design/file/NewTemplatePane.java @@ -0,0 +1 @@ +package com.fr.design.file; import com.fr.base.BaseUtils; import com.fr.design.constants.UIConstants; import com.fr.design.mainframe.DesignerContext; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Line2D; /** * Author : daisy * Date: 13-8-27 * Time: 下午6:07 */ public abstract class NewTemplatePane extends JComponent implements MouseListener, MouseMotionListener { private static final Icon GRAY_NEW_CPT = BaseUtils.readIcon("/com/fr/design/images/buttonicon/additicon_grey.png"); private static final int PRE_GAP = 0; private static final int HEIGHT = 26; private Graphics2D g2d; private Icon newWorkBookIconMode = null; private int newIconStartX = PRE_GAP; public NewTemplatePane() { newWorkBookIconMode = getNew(); this.setLayout(new BorderLayout(0, 0)); this.addMouseListener(this); this.addMouseMotionListener(this); this.setBorder(null); this.setForeground(new Color(99, 99, 99)); } public Dimension getPreferredSize() { Dimension dim = super.getPreferredSize(); dim.width = HEIGHT; return dim; } public void paintComponent(Graphics g) { super.paintComponent(g); g2d = (Graphics2D) g; int sheetIconY = (getHeight() - newWorkBookIconMode.getIconHeight()) / 2; newWorkBookIconMode.paintIcon(this, g2d, newIconStartX, sheetIconY); paintUnderLine(g2d); } private void paintUnderLine(Graphics2D g2d) { //画下面的那条线 g2d.setPaint(UIConstants.LINE_COLOR); g2d.draw(new Line2D.Double((float) 0, (float) (getHeight()-1), getWidth(), (float) (getHeight()-1))); } /** *鼠标点击 * @param e 事件 */ public void mouseClicked(MouseEvent e) { if (BaseUtils.isAuthorityEditing()) { newWorkBookIconMode = GRAY_NEW_CPT; } } /** *鼠标按下 * @param e 事件 */ public void mousePressed(MouseEvent e) { int evtX = e.getX(); if (BaseUtils.isAuthorityEditing()) { newWorkBookIconMode = GRAY_NEW_CPT; } if (isOverNewIcon(evtX) && newWorkBookIconMode != GRAY_NEW_CPT) { newWorkBookIconMode = getMousePressNew(); newIconStartX = 0; DesignerContext.getDesignerFrame().addAndActivateJTemplate(); } this.repaint(); } /** *鼠标松开 * @param e 事件 */ public void mouseReleased(MouseEvent e) { if (BaseUtils.isAuthorityEditing()) { newWorkBookIconMode = GRAY_NEW_CPT; } } /** *鼠标进入 * @param e 事件 */ public void mouseEntered(MouseEvent e) { if (BaseUtils.isAuthorityEditing()) { newWorkBookIconMode = GRAY_NEW_CPT; } } /** *鼠标离开 * @param e 事件 */ public void mouseExited(MouseEvent e) { newIconStartX = PRE_GAP; if (BaseUtils.isAuthorityEditing()) { newWorkBookIconMode = GRAY_NEW_CPT; } else { newWorkBookIconMode = getNew(); } this.repaint(); } /** *鼠标拖拽 * @param e 事件 */ public void mouseDragged(MouseEvent e) { } /** *鼠标移动 * @param e 事件 */ public void mouseMoved(MouseEvent e) { int evtX = e.getX(); if (BaseUtils.isAuthorityEditing()) { newWorkBookIconMode = GRAY_NEW_CPT; } else if (isOverNewIcon(evtX)) { newIconStartX = 0; newWorkBookIconMode = getMouseOverNew(); } this.repaint(); } private boolean isOverNewIcon(int evtX) { return (evtX >= PRE_GAP && evtX <= PRE_GAP + newWorkBookIconMode.getIconWidth()); } public void setButtonGray(boolean isGray) { newWorkBookIconMode = isGray ? GRAY_NEW_CPT : getNew(); } public abstract Icon getNew(); public abstract Icon getMouseOverNew(); public abstract Icon getMousePressNew(); } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/file/SaveSomeTemplatePane.java b/designer_base/src/com/fr/design/file/SaveSomeTemplatePane.java new file mode 100644 index 0000000000..568428c4e3 --- /dev/null +++ b/designer_base/src/com/fr/design/file/SaveSomeTemplatePane.java @@ -0,0 +1 @@ +package com.fr.design.file; import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilist.UIList; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.DialogActionAdapter; import com.fr.general.ComparatorUtils; import com.fr.general.FRLogger; import com.fr.general.Inter; import com.fr.stable.ProductConstants; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.logging.Level; /** * Author : daisy * Date: 13-8-9 * Time: 下午3:41 */ public class SaveSomeTemplatePane extends BasicPane { private UICheckBox[] templateCheckBoxes = null; private BasicDialog dialog; private JPanel templatesChoosePane; private UIScrollPane scrollPane; private java.util.List> unSavedTemplate = new ArrayList>(); private boolean isAllSaved = false; //该变量用来判断是在关闭其他模板或是关闭设计器的时候,是否需要判断当前模板有没有保存 private boolean isJudgeCurrentEditingTemplate = true; public SaveSomeTemplatePane(boolean isNeedTojudgeCurrent) { this.setLayout(FRGUIPaneFactory.createBorderLayout()); if (this.dialog == null) { this.dialog = this.showSmallWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { @Override public void doOk() { for (int i = 0; i < templateCheckBoxes.length; i++) { if (templateCheckBoxes[i].isSelected()) { saveSelectedTemplate(unSavedTemplate.get(i)); } } isAllSaved = true; } public void doCancel() { isAllSaved = false; } }); } UILabel tip = new UILabel(Inter.getLocText("Select_The_Source_To_Save")); this.add(tip, BorderLayout.NORTH); templatesChoosePane = FRGUIPaneFactory.createBorderLayout_S_Pane(); UIScrollPane scrollPane = new UIScrollPane(templatesChoosePane); this.add(scrollPane, BorderLayout.CENTER); this.isJudgeCurrentEditingTemplate = isNeedTojudgeCurrent; } private void initTemplatesChoosePane() { templatesChoosePane.setBorder(BorderFactory.createTitledBorder("")); for (int i = 0; i < unSavedTemplate.size(); i++) { templateCheckBoxes[i] = new UICheckBox(unSavedTemplate.get(i).getEditingFILE().getName()); templateCheckBoxes[i].setSelected(true); } final UIList templatesList = new UIList(templateCheckBoxes); templatesList.setModel(new UnSeletedTemplateListDataMode()); templatesList.setCellRenderer(new UnSelectedListCellRender()); templatesList.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { super.mousePressed(e); int index = templatesList.getSelectedIndex(); if (index < 0) { return; } UICheckBox checkBox = (UICheckBox) templatesList.getModel().getElementAt(index); checkBox.setSelected(!checkBox.isSelected()); templatesList.repaint(); } }); final UICheckBox filenameCheckBox = new UICheckBox(Inter.getLocText("Choose_All")); filenameCheckBox.setSelected(true); filenameCheckBox.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { boolean isSelected = filenameCheckBox.isSelected(); for (int i = 0; i < templatesList.getModel().getSize(); i++) { UICheckBox checkBox = (UICheckBox) templatesList.getModel().getElementAt(i); checkBox.setSelected(isSelected); } templatesList.repaint(); } }); templatesChoosePane.add(filenameCheckBox, BorderLayout.NORTH); templatesChoosePane.add(templatesList, BorderLayout.CENTER); } public boolean showSavePane() { populate(); //如果有未保存的文件 ,则跳出保存对话框,选择要存储的项目 if (!unSavedTemplate.isEmpty()) { dialog.setVisible(true); } else { isAllSaved = true; } return isAllSaved; } public void populate() { java.util.List> opendedTemplate = HistoryTemplateListPane.getInstance().getHistoryList(); JTemplate currentTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); for (int i = 0; i < opendedTemplate.size(); i++) { if (isneedToAdd(opendedTemplate.get(i), currentTemplate)) { unSavedTemplate.add(opendedTemplate.get(i)); } } templateCheckBoxes = new UICheckBox[unSavedTemplate.size()]; initTemplatesChoosePane(); } private boolean isneedToAdd(JTemplate template, JTemplate currentTemplate) { //所有模板都判断是不是保存 if (isJudgeCurrentEditingTemplate) { return !template.isALLSaved(); } //当前编辑的模板不判断是否已经保存 if (ComparatorUtils.equals(template, currentTemplate)) { return false; } else { return !template.isALLSaved(); } } private void saveSelectedTemplate(JTemplate specifiedTemplate) { if (!specifiedTemplate.isSaved()) { specifiedTemplate.stopEditing(); specifiedTemplate.saveTemplate(); } FRLogger.getLogger().log(Level.INFO, Inter.getLocText(new String[]{"Template", "already-saved"}, new String[]{specifiedTemplate.getEditingFILE().getName(), "."})); } public int saveLastOneTemplate() { JTemplate specifiedTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); if (!specifiedTemplate.isALLSaved()) { specifiedTemplate.stopEditing(); int returnVal = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Utils-Would_you_like_to_save") + " \"" + specifiedTemplate.getEditingFILE() + "\" ?", ProductConstants.PRODUCT_NAME, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (returnVal == JOptionPane.YES_OPTION && specifiedTemplate.saveTemplate()) { specifiedTemplate.saveTemplate(); FRLogger.getLogger().log(Level.INFO, Inter.getLocText(new String[]{"Template", "already-saved"}, new String[]{specifiedTemplate.getEditingFILE().getName(), "."})); } return returnVal; } return JOptionPane.YES_OPTION; } protected String title4PopupWindow() { return Inter.getLocText("Save"); } private class UnSelectedListCellRender extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, final boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); templateCheckBoxes[index] = (UICheckBox) value; templateCheckBoxes[index].setBackground(list.getBackground()); return templateCheckBoxes[index]; } } private class UnSeletedTemplateListDataMode extends AbstractListModel { @Override public int getSize() { return templateCheckBoxes.length; } @Override public UICheckBox getElementAt(int index) { if (index > getSize() - 1 || index < 0) { return null; } return templateCheckBoxes[index]; } } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/file/TemplateTreePane.java b/designer_base/src/com/fr/design/file/TemplateTreePane.java new file mode 100644 index 0000000000..e9009ff9fa --- /dev/null +++ b/designer_base/src/com/fr/design/file/TemplateTreePane.java @@ -0,0 +1,307 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.file; + +import com.fr.base.FRContext; +import com.fr.dav.LocalEnv; +import com.fr.design.gui.itree.filetree.TemplateFileTree; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.env.RemoteEnv; +import com.fr.file.FileNodeFILE; +import com.fr.file.filetree.FileNode; +import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.ProductConstants; +import com.fr.stable.CoreConstants; +import com.fr.stable.StableUtils; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.util.ArrayList; +import java.util.logging.Level; + +public class TemplateTreePane extends JPanel implements FileOperations { + + public static TemplateTreePane getInstance() { + return HOLDER.singleton; + } + + private static class HOLDER { + private static TemplateTreePane singleton = new TemplateTreePane(); + } + + private TemplateFileTree reportletsTree; + private FileToolbarStateChangeListener toobarStateChangeListener; + + private TemplateTreePane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setPreferredSize(new Dimension(250, super.getPreferredSize().height)); + JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(contentPane, BorderLayout.CENTER); + + reportletsTree = new TemplateFileTree(); + ToolTipManager.sharedInstance().registerComponent(reportletsTree); + UIScrollPane scrollPane = new UIScrollPane(reportletsTree); + scrollPane.setBorder(null); + contentPane.add(scrollPane, BorderLayout.CENTER); + + this.reportletsTree.addMouseListener(mouseFileTreeListener);// lx: add + // mouse + // listener + this.reportletsTree.addKeyListener(new KeyListener() { + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + openSelectedReport(); + } + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + openSelectedReport(); + } + if (toobarStateChangeListener != null) { + toobarStateChangeListener.stateChange(); + } + } + + @Override + public void keyTyped(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + openSelectedReport(); + } + } + }); + } + + public TemplateFileTree getTemplateFileTree() { + return this.reportletsTree; + } + + /** + * 刷新 + */ + public void refreshDockingView() { + reportletsTree.setFileNodeFilter(new IOFileNodeFilter(FRContext.getCurrentEnv().getSupportedTypes())); + reportletsTree.refreshEnv(FRContext.getCurrentEnv()); + } + + /* + * Tree.MouseAdapter + */ + MouseListener mouseFileTreeListener = new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent evt) { + if (SwingUtilities.isRightMouseButton(evt)) { + return; + } else if (evt.getClickCount() == 2) { + openSelectedReport(); + } + + + } + + public void mouseReleased(MouseEvent e) { + if (toobarStateChangeListener != null) { + toobarStateChangeListener.stateChange(); + } + } + }; + + + /** + * 打开选中的报表文件 + */ + public void openSelectedReport() { + String reportPath = reportletsTree.getSelectedTemplatePath(); + final String selectedFilePath = StableUtils.pathJoin(new String[]{ProjectConstants.REPORTLETS_NAME, reportPath}); + DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false))); + } + + /** + * 打开文件夹 + */ + public void openContainerFolder() { + FileNode fn = TemplateTreePane.this.reportletsTree.getSelectedFileNode(); + LocalEnv localEnv = (LocalEnv) FRContext.getCurrentEnv(); + String filePath = StableUtils.pathJoin(new String[]{localEnv.path, fn.getEnvPath()}); + filePath = filePath.substring(0, filePath.lastIndexOf(CoreConstants.SEPARATOR)); + try { + Desktop.getDesktop().open(new File(filePath)); + } catch (Exception e) { + localEnv.openContainerFolder(fn); + } + } + + /** + * 刷新 + */ + public void refresh() { + reportletsTree.refresh(); + FRLogger.getLogger().log(Level.INFO, Inter.getLocText(new String[]{"File-tree", "Refresh_Successfully"}) + "!"); + } + + /** + * 删除文件 + */ + public void deleteFile() { + String[] reportPaths = reportletsTree.getSelectedTemplatePaths(); + if (reportPaths.length == 0) { + return; + } + if (JOptionPane.showConfirmDialog(null, Inter.getLocText("Confirm-Delete-File")) != JOptionPane.OK_OPTION) { + return; + } + for (String reportPath : reportPaths) { + FileNodeFILE nodeFile = new FileNodeFILE(new FileNode(StableUtils.pathJoin(new String[]{ProjectConstants.REPORTLETS_NAME, reportPath}), false)); + + if (nodeFile.isLocked()) { + if (JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("fileLocked_undeleted"), + Inter.getLocText("Error"), JOptionPane.YES_OPTION, JOptionPane.ERROR_MESSAGE) == JOptionPane.YES_OPTION) { + refreshDockingView(); + } + break; + } + if (nodeFile.exists()) { + String path = StableUtils.pathJoin(new String[]{nodeFile.getEnvPath(), nodeFile.getPath()}); + FRContext.getCurrentEnv().deleteFile(nodeFile.getPath()); + deleteHistory(path.replaceAll("/", "\\\\")); + } else { + JOptionPane.showMessageDialog(this, Inter.getLocText("Warning-Template_Do_Not_Exsit"), ProductConstants.PRODUCT_NAME, + JOptionPane.INFORMATION_MESSAGE); + } + } + reportletsTree.refresh(); + } + + + private void deleteHistory(String fileName) { + int index = HistoryTemplateListPane.getInstance().contains(fileName); + int size = HistoryTemplateListPane.getInstance().getHistoryCount(); + if (index == -1) { + return; + } + //如果打开过,则删除,实时刷新多tab面板 + HistoryTemplateListPane.getInstance().getHistoryList().remove(index); + int openfileCount = HistoryTemplateListPane.getInstance().getHistoryCount(); + if (openfileCount == 0) { + DesignerContext.getDesignerFrame().addAndActivateJTemplate(); + } + MutilTempalteTabPane.getInstance().repaint(); + if (size == index + 1 && index != 0) { + //如果删除的是最后一个Tab,则定位到前一个 + MutilTempalteTabPane.getInstance().setSelectedIndex(index - 1); + } + JTemplate selectedfile = MutilTempalteTabPane.getInstance().getSelectedFile(); + if (!HistoryTemplateListPane.getInstance().isCurrentEditingFile(selectedfile.getFullPathName())) { + //如果此时面板上的实时刷新的selectedIndex得到的和历史的不一样 + DesignerContext.getDesignerFrame().activateJTemplate(selectedfile); + } + MutilTempalteTabPane.getInstance().repaint(); + } + + /** + * 加上文件锁 + */ + public void lockFile() { + FileNode fn = reportletsTree.getSelectedFileNode(); + RemoteEnv remoteEnv = (RemoteEnv) FRContext.getCurrentEnv(); + if (fn == null) { + return; + } + try { + remoteEnv.getLock(new String[]{fn.getEnvPath()}); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage()); + } + reportletsTree.refresh(); + } + + /** + * 文件解锁 + */ + public void unLockFile() { + FileNode fn = reportletsTree.getSelectedFileNode(); + if (fn == null) { + return; + } + RemoteEnv remoteEnv = (RemoteEnv) FRContext.getCurrentEnv(); + try { + remoteEnv.releaseLock(new String[]{fn.getEnvPath()}); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage()); + } + reportletsTree.refresh(); + } + + public String getSelectedTemplatePath() { + return reportletsTree.getSelectedTemplatePath(); + } + + public void setToobarStateChangeListener(FileToolbarStateChangeListener toobarStateChangeListener) { + this.toobarStateChangeListener = toobarStateChangeListener; + } + + /** + * 文件名是否存在 + * + * @param newName 原名 + * @param oldName 新的文件名 + * @param suffix 后缀名 + * @return 是否存在 + */ + public boolean isNameAlreadyExist(String newName, String oldName, String suffix) { + boolean isNameAlreadyExist = false; + + TemplateFileTree tt = reportletsTree; + DefaultMutableTreeNode gen = (DefaultMutableTreeNode) tt.getModel().getRoot(); + ArrayList al = new ArrayList(); + + findFiles(gen, al); + + for (int i = 0; i < al.size(); i++) { + if (ComparatorUtils.equals(al.get(i), newName + suffix)) { + isNameAlreadyExist = true; + break; + } + } + + if (ComparatorUtils.equals(newName, oldName)) { + isNameAlreadyExist = false; + } + + return isNameAlreadyExist; + } + + + private void findFiles(DefaultMutableTreeNode node, ArrayList al) { + String[] str = new String[node.getChildCount()]; + for (int j = 0; j < node.getChildCount(); j++) { + DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(j); + if (childNode.getChildCount() > 0) { + findFiles(childNode, al); + } else { + str[j] = node.getChildAt(j).toString(); + if (str[j].contains(".")) { + al.add(str[j]); + } + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/AbstractNameAndDescription.java b/designer_base/src/com/fr/design/formula/AbstractNameAndDescription.java new file mode 100644 index 0000000000..029eeb32da --- /dev/null +++ b/designer_base/src/com/fr/design/formula/AbstractNameAndDescription.java @@ -0,0 +1,31 @@ +package com.fr.design.formula; + +import com.fr.stable.StringUtils; + +public abstract class AbstractNameAndDescription implements NameAndDescription { + + @Override + public String searchResult(String keyWord, boolean findDescription) { + String functionName = getName(); + if (StringUtils.isBlank(functionName)) { + return null; + } + int sign = 1; + int length = keyWord.length(); + String temp = functionName.toUpperCase(); + for (int j = 0; j < length; j++) { + String check = keyWord.substring(j, j + 1); + int index = temp.indexOf(check.toUpperCase()); + if (index == -1) { + sign = 0; + break; + } else { + temp = temp.substring(index + 1); + } + } + if (sign == 1) { + return functionName; + } + return null; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/CustomVariableResolver.java b/designer_base/src/com/fr/design/formula/CustomVariableResolver.java new file mode 100644 index 0000000000..8f1437768d --- /dev/null +++ b/designer_base/src/com/fr/design/formula/CustomVariableResolver.java @@ -0,0 +1,22 @@ +package com.fr.design.formula; + +public class CustomVariableResolver extends VariableResolverAdapter { + private String[] columnNames; + private boolean isBindCell; + + public CustomVariableResolver(String[] columnNames, boolean isBindCell) { + this.columnNames = columnNames; + this.isBindCell = isBindCell; + } + + @Override + public String[] resolveColumnNames() { + return this.columnNames; + } + + @Override + public boolean isBindCell() { + return this.isBindCell; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/DefaultUIFormulaProcessor.java b/designer_base/src/com/fr/design/formula/DefaultUIFormulaProcessor.java new file mode 100644 index 0000000000..bb485da4e9 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/DefaultUIFormulaProcessor.java @@ -0,0 +1,20 @@ +package com.fr.design.formula; + +import com.fr.design.fun.impl.AbstractUIFormulaProcessor; + +/** + * @author richie + * @date 2015-04-17 + * @since 8.0 + */ +public class DefaultUIFormulaProcessor extends AbstractUIFormulaProcessor { + @Override + public UIFormula appearanceFormula() { + return new FormulaPane(); + } + + @Override + public UIFormula appearanceWhenReserveFormula() { + return new FormulaPaneWhenReserveFormula(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FormulaFactory.java b/designer_base/src/com/fr/design/formula/FormulaFactory.java new file mode 100644 index 0000000000..e0c19555aa --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FormulaFactory.java @@ -0,0 +1,29 @@ +package com.fr.design.formula; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.fun.UIFormulaProcessor; + +/** + * @author richie + * @date 2015-04-17 + * @since 8.0 + * 公式编辑器管理器 + */ +public class FormulaFactory { + + public static UIFormula createFormulaPane() { + return get().appearanceFormula(); + } + + public static UIFormula createFormulaPaneWhenReserveFormula() { + return get().appearanceWhenReserveFormula(); + } + + private static UIFormulaProcessor get() { + UIFormulaProcessor processor = ExtraDesignClassManager.getInstance().getUIFormulaProcessor(); + if (processor == null) { + processor = new DefaultUIFormulaProcessor(); + } + return processor; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FormulaPane.java b/designer_base/src/com/fr/design/formula/FormulaPane.java new file mode 100644 index 0000000000..34a523697a --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FormulaPane.java @@ -0,0 +1,997 @@ +package com.fr.design.formula; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.base.Formula; +import com.fr.design.actions.UpdateAction; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ilist.QuickList; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; +import com.fr.parser.FRLexer; +import com.fr.parser.FRParser; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; +import com.fr.stable.script.Expression; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.util.Locale; +/** + * 公式编辑面板 + * @editor zhou + * @since 2012-3-29下午1:50:53 + */ +public class FormulaPane extends BasicPane implements KeyListener, UIFormula{ + + protected VariableTreeAndDescriptionArea variableTreeAndDescriptionArea; + protected RSyntaxTextArea formulaTextArea; + protected UITextField keyWordTextField = new UITextField(18); + protected int currentPosition = 0; + protected int beginPosition = 0; + protected int insertPosition = 0; + protected JList tipsList; + protected DefaultListModel listModel = new DefaultListModel(); + protected int ifHasBeenWriten = 0; + protected DefaultListModel functionTypeListModel = new DefaultListModel(); + protected QuickList functionTypeList; + protected DefaultListModel functionNameModel; + protected JList functionNameList; + + public FormulaPane() { + initComponents(); + } + + protected void initComponents() { + this.setLayout(new BorderLayout(4, 4)); + + // text + JPanel textPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(textPane, BorderLayout.CENTER); + + JPanel checkBoxandbuttonPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + + UILabel formulaLabel = new UILabel(Inter.getLocText("FormulaD-Input_formula_in_the_text_area_below") + ":" + + " "); + formulaLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + formulaTextArea = new RSyntaxTextArea(); + configFormulaArea(); + formulaTextArea.addKeyListener(this); + + formulaTextArea.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + formulaTextArea.setForeground(Color.black); + String text = formulaTextArea.getText(); + // 判断在中文输入状态是否还包含提示符 要删掉 + String tip = "\n\n\n" + Inter.getLocText("Tips:You_Can_Input_B1_To_Input_The_Data_Of_The_First_Row_Second_Column"); + if(text.contains(tip)) { + text = text.substring(0, text.indexOf(tip)); + insertPosition = 0; + formulaTextArea.setText(text); + } + } + }); + + formulaTextArea.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + insertPosition = formulaTextArea.getCaretPosition(); + if (ifHasBeenWriten == 0) { + formulaTextArea.setText(""); + ifHasBeenWriten = 1; + formulaTextArea.setForeground(Color.black); + insertPosition = 0; + } + } + + @Override + public void mouseReleased(MouseEvent e) { + currentPosition = formulaTextArea.getCaretPosition(); + if (currentPosition == insertPosition) { + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + firstStepToFindTips(beginPosition); + fixFunctionNameList(); + } + } + }); + UIScrollPane formulaTextAreaScrollPane = new UIScrollPane(formulaTextArea); + formulaTextAreaScrollPane.setBorder(null); + textPane.add(formulaLabel, BorderLayout.NORTH); + textPane.add(formulaTextAreaScrollPane, BorderLayout.CENTER); + textPane.add(checkBoxandbuttonPane, BorderLayout.SOUTH); + + // tipsPane + JPanel tipsPane = new JPanel(new BorderLayout(4, 4)); + this.add(tipsPane, BorderLayout.EAST); + + JPanel searchPane = new JPanel(new BorderLayout(4, 4)); + searchPane.add(keyWordTextField, BorderLayout.CENTER); + UIButton searchButton = new UIButton(Inter.getLocText("Search")); + searchPane.add(searchButton, BorderLayout.EAST); + tipsPane.add(searchPane, BorderLayout.NORTH); + + keyWordTextField.addKeyListener(new KeyListener() { + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + String toFind = keyWordTextField.getText(); + search(toFind, false); + + fixFunctionNameList(); + e.consume(); + } + } + }); + + tipsList = new JList(listModel); + tipsList.addMouseListener(new DoubleClick()); + UIScrollPane tipsScrollPane = new UIScrollPane(tipsList); + tipsScrollPane.setPreferredSize(new Dimension(170, 75)); + tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + + tipsPane.add(tipsScrollPane, BorderLayout.CENTER); + + + UIButton checkValidButton = new UIButton(Inter.getLocText("FormulaD-Check_Valid")); + checkValidButton.addActionListener(checkValidActionListener); + + JPanel checkBoxPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + checkBoxandbuttonPane.add(checkBoxPane, BorderLayout.WEST); + checkBoxandbuttonPane.add(checkValidButton, BorderLayout.EAST); + + extendCheckBoxPane(checkBoxPane); + + searchButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String toFind = keyWordTextField.getText(); + search(toFind, false); + formulaTextArea.requestFocusInWindow(); + + fixFunctionNameList(); + } + }); + variableTreeAndDescriptionArea = new VariableTreeAndDescriptionArea(); + this.add(variableTreeAndDescriptionArea, BorderLayout.SOUTH); + } + + + protected void extendCheckBoxPane(JPanel checkBoxPane) { + + } + + protected void configFormulaArea() { + formulaTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_FORMULA); + formulaTextArea.setAnimateBracketMatching(true); + formulaTextArea.setAntiAliasingEnabled(true); + formulaTextArea.setAutoIndentEnabled(true); + formulaTextArea.setCodeFoldingEnabled(true); + formulaTextArea.setUseSelectedTextColor(true); + formulaTextArea.setCloseCurlyBraces(true); + formulaTextArea.setBracketMatchingEnabled(true); + formulaTextArea.setAntiAliasingEnabled(true); + formulaTextArea.setCloseMarkupTags(true); + formulaTextArea.setLineWrap(true); + } + + public class DoubleClick extends MouseAdapter { + + @Override + public void mouseClicked(MouseEvent e) { + int index = tipsList.getSelectedIndex(); + if (index != -1) { + String currentLineContent = (String) listModel.getElementAt(index); + if (e.getClickCount() == 2) { + if (ifHasBeenWriten == 0) { + formulaTextArea.setForeground(Color.black); + formulaTextArea.setText(""); + } + formulaTextArea.setForeground(Color.black); + currentPosition = formulaTextArea.getCaretPosition(); + String output = currentLineContent + "()"; + String textAll = formulaTextArea.getText(); + String textReplaced; + int position = 0; + if (insertPosition <= currentPosition) { + textReplaced = textAll.substring(0, insertPosition) + output + textAll.substring(currentPosition); + position = insertPosition + output.length() - 1; + } else { + textReplaced = textAll.substring(0, currentPosition) + output + textAll.substring(insertPosition); + position = currentPosition + output.length() - 1; + } + formulaTextArea.setText(textReplaced); + formulaTextArea.requestFocusInWindow(); + formulaTextArea.setCaretPosition(position); + insertPosition = position; + ifHasBeenWriten = 1; + listModel.removeAllElements(); + } else if (e.getClickCount() == 1) { + refreshDescriptionTextArea(currentLineContent); + + formulaTextArea.requestFocusInWindow(); + fixFunctionNameList(); + } + } + } + } + + @Override + public void keyPressed(KeyEvent e) { + if (ifHasBeenWriten == 0) { + this.formulaTextArea.setText(StringUtils.EMPTY); + } + } + + @Override + public void keyReleased(KeyEvent e) { + int key = e.getKeyCode(); + if (key == 38 || key == 40 || key == 37 || key == 39 || key == 10) //如果是删除符号 ,为了可读性 没有和其他按键的程序相融合 + { + listModel.removeAllElements(); + currentPosition = formulaTextArea.getCaretPosition(); + insertPosition = currentPosition; + beginPosition = getBeginPosition(); + } else { + if (this.formulaTextArea.getText().trim().length() == 0) { + insertPosition = 0; + this.listModel.removeAllElements(); + } else { + this.formulaTextArea.setForeground(Color.black); + currentPosition = formulaTextArea.getCaretPosition(); + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + firstStepToFindTips(beginPosition); + fixFunctionNameList(); + ifHasBeenWriten = 1; + } + } + } + + protected void fixFunctionNameList() { + if (tipsList.getSelectedValue() != null) { + int signOfContinue = 1; + int indexOfFunction = 0; + for (int i = 0; i < functionTypeListModel.size(); i++) { + int signOfType = 0; + FunctionGroup functionType = (FunctionGroup) functionTypeListModel.getElementAt(i); + NameAndDescription[] nads = functionType.getDescriptions(); + if (signOfContinue == 1) { + functionNameModel.removeAllElements(); + String functionName = ((String) tipsList.getSelectedValue()); + for (int k = 0; k < nads.length; k++) { + functionNameModel.addElement(nads[k]); + if (functionName.equals(nads[k].getName()))//若相等,找出显示的函数的index,setSelectedIndex() + { + signOfType = 1; + signOfContinue = 0; + indexOfFunction = k; + } + } + + if (signOfType == 1) { + functionTypeList.setSelectedIndex(i); + signOfType = 0; + } + } + } + functionNameList.setSelectedIndex(indexOfFunction); + functionNameList.ensureIndexIsVisible(indexOfFunction); + } + + } + + protected int getBeginPosition() { + int i = currentPosition; + String textArea = formulaTextArea.getText(); + for (; i > 0; i--) { + String tested = textArea.substring(i - 1, i).toUpperCase(); + char[] testedChar = tested.toCharArray(); + if (isChar(testedChar[0]) || isNum(testedChar[0])) { + continue; + } else { + break; + } + } + return i; + } + + protected void firstStepToFindTips(int theBeginPosition) { + String textArea = formulaTextArea.getText(); + + if (currentPosition > 0 && theBeginPosition < currentPosition) { + String next = textArea.substring(theBeginPosition, theBeginPosition + 1); + char[] nextChar = next.toCharArray(); + if (!isNum(nextChar[0])) { + String toFind = textArea.substring(theBeginPosition, currentPosition); + search(toFind, false); + formulaTextArea.requestFocusInWindow(); + } else { + listModel.removeAllElements(); + } + } else { + String toFind = textArea.substring(theBeginPosition, currentPosition); + search(toFind, false); + formulaTextArea.requestFocusInWindow(); + } + } + + private static boolean isNum(char tested) { + return tested >= '0' && tested <= '9'; + } + + private boolean isChar(char tested) { + return tested >= 'A' && tested <= 'Z'; + } + + @Override + public void keyTyped(KeyEvent e) { + } + + protected void search(String keyWord, boolean findDescription) { + listModel.removeAllElements(); + + keyWord = removeAllSpace(keyWord); + if (keyWord.length() != 0) { + NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions(); + int lengthOfDes = descriptions.length; + for (int i = 0; i < lengthOfDes; i++) { + NameAndDescription and = descriptions[i]; + + String functionName = and.searchResult(keyWord, findDescription); + if (StringUtils.isNotBlank(functionName)) { + listModel.addElement(functionName); + } + } + + if (!listModel.isEmpty()) { + tipsList.setSelectedIndex(0); + refreshDescriptionTextArea((String) listModel.getElementAt(0)); + } + } + } + + private void refreshDescriptionTextArea(String line) { + NameAndDescription[] descriptions = FunctionConstants.ALL.getDescriptions(); + int length = descriptions.length; + for (int i = 0; i < length; i++) { + NameAndDescription function = descriptions[i]; + String functionName = function.getName(); + if (functionName.equals(line)) { + variableTreeAndDescriptionArea.descriptionTextArea.setText(function.getDesc()); + variableTreeAndDescriptionArea.descriptionTextArea.moveCaretPosition(0); + break; + } + } + } + + private String removeAllSpace(String toFind) { + + int index = toFind.indexOf(" "); + while (index != -1) { + toFind = toFind.substring(0, index) + toFind.substring(index + 1); + index = toFind.indexOf(" "); + } + return toFind; + } + + /** + * Apply text. + */ + public void applyText(String text) { + if (text == null || text.length() <= 0) { + return; + } + if (ifHasBeenWriten == 0) { + formulaTextArea.setForeground(Color.black); + formulaTextArea.setText(""); + ifHasBeenWriten = 1; + insertPosition = 0; + } + String textAll = formulaTextArea.getText(); + currentPosition = formulaTextArea.getCaretPosition(); + int insert = 0; + int current = 0; + if (insertPosition <= currentPosition) { + insert = insertPosition; + current = currentPosition; + } else { + insert = currentPosition; + current = insertPosition; + } + String beforeIndexOfInsertString = textAll.substring(0, insert); + String afterIndexofInsertString = textAll.substring(current); + formulaTextArea.setText(beforeIndexOfInsertString + text + afterIndexofInsertString); + formulaTextArea.getText(); + if (text.indexOf("()") != -1) { + formulaTextArea.setCaretPosition(insert + text.length() - 1); + } + formulaTextArea.requestFocus(); + insertPosition = formulaTextArea.getCaretPosition(); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FormulaD-Formula_Definition"); + } + + /** + * Populate + */ + public void populate(Formula formula) { + this.populate(formula, VariableResolver.DEFAULT); + } + + public void populate(Formula formula, VariableResolver variableResolver) { + this.variableTreeAndDescriptionArea.populate(variableResolver); + + // set text + if (formula != null) { + String content = formula.getContent(); + if (content.trim().equals("=")) { + this.formulaTextArea.setForeground(Color.gray); + this.formulaTextArea.setText("\n\n\n" + Inter.getLocText("Tips:You_Can_Input_B1_To_Input_The_Data_Of_The_First_Row_Second_Column")); + this.formulaTextArea.setCaretPosition(0); + ifHasBeenWriten = 0; + this.listModel.removeAllElements(); + } else if (content.trim().charAt(0) == '=') { + this.formulaTextArea.setText(content.trim().substring(1)); + currentPosition = formulaTextArea.getCaretPosition(); + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + firstStepToFindTips(beginPosition); + fixFunctionNameList(); + ifHasBeenWriten = 1; + } else { + this.formulaTextArea.setText(content); + currentPosition = formulaTextArea.getCaretPosition(); + beginPosition = getBeginPosition(); + insertPosition = beginPosition; + firstStepToFindTips(beginPosition); + fixFunctionNameList(); + ifHasBeenWriten = 1; + } + } + } + + /** + * update + */ + public Formula update() { + Formula formula; + if (ifHasBeenWriten == 0) { + String content = StringUtils.EMPTY; + formula = new Formula(content); + return formula; + } else { + String content = this.formulaTextArea.getText(); + + if (StringUtils.isEmpty(content) || content.trim().charAt(0) == '=') { + formula = new Formula(content); + } else { + formula = new Formula("=" + content); + } + return formula; + } + } + + // check valid + protected ActionListener checkValidActionListener = new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + // Execute Formula default cell element. + String formulaText = formulaTextArea.getText().trim(); + + if (formulaText != null && formulaText.length() > 0) { + StringReader in = new StringReader(formulaText); + + FRLexer lexer = new FRLexer(in); + FRParser parser = new FRParser(lexer); + + Expression expression = null; + try { + expression = parser.parse(); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + // alex:继续往下面走,expression为null时告知不合法公式 + } + + JOptionPane.showMessageDialog( + FormulaPane.this, + /* + * alex:仅仅只需要根据expression是否为null作合法性判断 + * 不需要eval + * TODO 但有个问题,有些函数的参数个数是有规定的,何以判别之 + */ + (expression != null ? Inter.getLocText("FormulaD-Valid_Formula") : Inter.getLocText("FormulaD-Invalid_Formula")) + ".", ProductConstants.PRODUCT_NAME, + JOptionPane.INFORMATION_MESSAGE); + } + } + }; + + public class VariableTreeAndDescriptionArea extends JPanel { + + private JTree variablesTree; + private UITextArea descriptionTextArea; + + public VariableTreeAndDescriptionArea() { + this.initComponents(); + } + + private void initComponents() { + this.setLayout(new BorderLayout(4, 4)); + + // Function + JPanel functionPane = new JPanel(new BorderLayout(4, 4)); + this.add(functionPane, BorderLayout.WEST); + + + functionTypeList = new QuickList(functionTypeListModel); + UIScrollPane functionTypeScrollPane = new UIScrollPane(functionTypeList); + functionTypeScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + functionTypeScrollPane.setPreferredSize(new Dimension(140, 200)); + functionPane.add(this.createNamePane(Inter.getLocText("FormulaD-Function_category") + ":", functionTypeScrollPane), BorderLayout.WEST); + functionTypeList.setCellRenderer(new DefaultListCellRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof FunctionGroup) { + this.setText(((FunctionGroup) value).getGroupName()); + } + return this; + } + }); + + functionTypeListModel.addElement(FunctionConstants.COMMON); + for (int i = 0; i < FunctionConstants.EMBFUNCTIONS.length; i++) { + functionTypeListModel.addElement(FunctionConstants.EMBFUNCTIONS[i]); + } + functionTypeListModel.addElement(FunctionConstants.ALL); + functionTypeListModel.addElement(FunctionConstants.CUSTOM); + functionTypeListModel.addElement(FunctionConstants.PLUGIN); + + functionTypeList.addListSelectionListener(new ListSelectionListener() { + + public void valueChanged(ListSelectionEvent evt) { + Object selectedValue = ((JList) evt.getSource()).getSelectedValue(); + if (!(selectedValue instanceof FunctionGroup)) { + return; + } + + NameAndDescription[] nads = ((FunctionGroup) selectedValue).getDescriptions(); + functionNameModel = (DefaultListModel) functionNameList.getModel(); + + functionNameModel.clear(); + + for (NameAndDescription nad : nads) { + functionNameModel.addElement(nad); + } + + if (functionNameModel.size() > 0) { + functionNameList.setSelectedIndex(0); + functionNameList.ensureIndexIsVisible(0); + } + } + }); + + functionNameList = new JList(new DefaultListModel()); + UIScrollPane functionNameScrollPane = new UIScrollPane(functionNameList); + functionNameScrollPane.setPreferredSize(new Dimension(140, 200)); + functionPane.add( + this.createNamePane(Inter.getLocText("FormulaD-Function_name") + ":", functionNameScrollPane), + BorderLayout.CENTER); + functionNameScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + + functionNameList.setCellRenderer(new DefaultListCellRenderer() { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof NameAndDescription) { + this.setText(((NameAndDescription) value).getName()); + } + return this; + } + }); + + functionNameList.addListSelectionListener(new ListSelectionListener() { + + public void valueChanged(ListSelectionEvent evt) { + Object selectedValue = functionNameList.getSelectedValue(); + if (!(selectedValue instanceof NameAndDescription)) { + return; + } + + String description = ((NameAndDescription) selectedValue).getDesc(); + descriptionTextArea.setText(description); + setTextAreaText(description); + descriptionTextArea.moveCaretPosition(0); + } + }); + + functionNameList.addMouseListener(new MouseAdapter() { + + public void mouseClicked(MouseEvent evt) { + + if (evt.getClickCount() >= 2) { + Object selectedValue = functionNameList.getSelectedValue(); + if (!(selectedValue instanceof NameAndDescription)) { + return; + } + String insert = ((NameAndDescription) selectedValue).getName() + "()"; + applyText(insert); + + } + + if (SwingUtilities.isRightMouseButton(evt)) { + JPopupMenu popupMenu = new JPopupMenu(); + LookDetailAction lookDetailAction = new LookDetailAction(); + popupMenu.add(lookDetailAction); + + // peter: 只有弹出菜单有子菜单的时候,才需要弹出来. + GUICoreUtils.showPopupMenu(popupMenu, functionNameList, evt.getX() - 1, evt.getY() - 1); + } + } + }); + + // vairable. + variablesTree = new JTree(); + UIScrollPane variablesTreePane = new UIScrollPane(variablesTree); + variablesTreePane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + this.add(this.createNamePane( + Inter.getLocText("Variables") + ":", variablesTreePane), BorderLayout.CENTER); + variablesTree.setRootVisible(false); + variablesTree.setShowsRootHandles(true); + variablesTree.addMouseListener(applyTextMouseListener); + variablesTree.setCellRenderer(applyTreeCellRenderer); + + // Description + descriptionTextArea = new UITextArea(16, 27); + + UIScrollPane desScrollPane = new UIScrollPane(descriptionTextArea); + desScrollPane.setBorder(null); + this.add(this.createNamePane(Inter.getLocText("Formula_Description") + ":", desScrollPane), BorderLayout.EAST); + descriptionTextArea.setBackground(new Color(255, 255, 225)); + descriptionTextArea.setLineWrap(true); + descriptionTextArea.setWrapStyleWord(true); + descriptionTextArea.setEditable(false); + descriptionTextArea.addMouseListener(new MouseAdapter() { + + public void mouseClicked(MouseEvent evt) { + if (evt.getClickCount() >= 2) { + showPopupPane(); + } + } + }); + + variablesTree.addTreeSelectionListener(new TreeSelectionListener() { + + public void valueChanged(TreeSelectionEvent e) { + Object selectedValue = ((DefaultMutableTreeNode) variablesTree.getLastSelectedPathComponent()).getUserObject(); + if (selectedValue == null) { + return; + } + + StringBuilder desBuf = new StringBuilder(); + try { + Reader desReader; + String path; + + Locale locale = FRContext.getLocale(); + if (locale.equals(Locale.CHINA)) { + path = "/com/fr/design/insert/formula/variable/cn/"; + } else { + path = "/com/fr/design/insert/formula/variable/en/"; + } + if (selectedValue instanceof TextUserObject) { + + InputStream desInputStream = BaseUtils.readResource(path + + ((TextUserObject) selectedValue).displayText + + ".txt"); + if (desInputStream == null) { + String description = ""; + + desReader = new StringReader(description); + } else { + desReader = new InputStreamReader( + desInputStream); + } + + BufferedReader reader = new BufferedReader( + desReader); + String lineText; + while ((lineText = reader.readLine()) != null) { + if (desBuf.length() > 0) { + desBuf.append('\n'); + } + + desBuf.append(lineText); + } + + reader.close(); + desReader.close(); + } + } catch (IOException exp) { + FRContext.getLogger().error(exp.getMessage(), exp); + } + + descriptionTextArea.setText(desBuf.toString()); + + descriptionTextArea.moveCaretPosition(0); + } + }); + + // 选择: + functionTypeList.setSelectedIndex(0); + } + + /* + * 查看函数的详细信息 + */ + private class LookDetailAction extends UpdateAction { + + public LookDetailAction() { + this.setName(Inter.getLocText("Function_Detail")); + this.setMnemonic('L'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + } + + // 弹出的窗口中显示函数的用法明细 + public void actionPerformed(ActionEvent evt) { + showPopupPane(); + } + } + + private void showPopupPane() { + BasicPane basicPane = new BasicPane() { + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Function_Detail"); + } + }; + basicPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + UITextArea desArea = new UITextArea(); +// desArea。setEnabled(false); + desArea.setText(this.getTextAreaText()); + basicPane.add(new UIScrollPane(desArea), BorderLayout.CENTER); + BasicDialog dialog = basicPane.showWindow(DesignerContext.getDesignerFrame()); + dialog.setVisible(true); + } + + private String getTextAreaText() { + return this.descriptionTextArea.getText(); + } + + private void setTextAreaText(String text) { + this.descriptionTextArea.setText(text); + } + + private JPanel createNamePane(String name, JComponent comp) { + JPanel namePane = new JPanel(new BorderLayout(4, 4)); + namePane.add(new UILabel(name), BorderLayout.NORTH); + namePane.add(comp, BorderLayout.CENTER); + return namePane; + } + + private MouseListener applyTextMouseListener = new MouseAdapter() { + + public void mouseClicked(MouseEvent evt) { + if (evt.getClickCount() >= 2) { + Object source = evt.getSource(); + + if (source instanceof JTree) { + JTree tree = (JTree) source; + TreePath selectedTreePah = tree.getSelectionPath(); + if (selectedTreePah != null) { + DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) selectedTreePah.getLastPathComponent(); + Object userObject = selectedTreeNode.getUserObject(); + if (userObject != null && userObject instanceof TextUserObject) { + + applyText(((TextUserObject) userObject).getText()); + } + } + } + } + } + }; + private DefaultTreeCellRenderer applyTreeCellRenderer = new DefaultTreeCellRenderer() { + + public Component getTreeCellRendererComponent(JTree tree, + Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, + expanded, leaf, row, hasFocus); + + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; + Object userObj = treeNode.getUserObject(); + + if (userObj instanceof TextUserObject) { + this.setIcon(null); + this.setText(((TextUserObject) userObj).getDisplayText()); + } else if (userObj instanceof TextFolderUserObject) { + TextFolderUserObject textUserObject = (TextFolderUserObject) userObj; + if (leaf) { + this.setText(textUserObject.getText()); + } else { + this.setText(textUserObject.getText() + " - [" + + treeNode.getChildCount() + "]"); + } + + this.setIcon(textUserObject.getIcon()); + } + + return this; + } + }; + + public void populate(VariableResolver variableResolver) { + // varibale tree. + DefaultTreeModel variableModel = (DefaultTreeModel) variablesTree.getModel(); + + DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) variableModel.getRoot(); + rootNode.removeAllChildren(); + + if (variableResolver.isBindCell()) { + // 加上当前值"$$$" + DefaultMutableTreeNode bindCellNode = new DefaultMutableTreeNode(new TextUserObject("$$$")); + rootNode.add(bindCellNode); + } + + { + MutableTreeNode tableTreeNode = new TextFolderUserObject( + Inter.getLocText("FormulaD-Data_Fields"), + BaseUtils.readIcon("/com/fr/design/images/dialog/table.png"), + variableResolver.resolveColumnNames()).createMutableTreeNode(); + + rootNode.add(tableTreeNode); + } + + { + // Set cutReport Variable + rootNode.add(new TextFolderUserObject( + Inter.getLocText("Variables"), + BaseUtils.readIcon("/com/fr/design/images/dialog/variable.png"), + variableResolver.resolveCurReportVariables()).createMutableTreeNode()); + } + + + { + rootNode.add(new TextFolderUserObject( + Inter.getLocText(new String[]{"Datasource-Datasource", "Parameter"}), + BaseUtils.readIcon("/com/fr/design/images/dialog/parameter.gif"), + variableResolver.resolveTableDataParameterVariables()).createMutableTreeNode()); + } + + + { + MutableTreeNode reportParameterTreeNode = new TextFolderUserObject( + Inter.getLocText("ParameterD-Report_Parameter"), + BaseUtils.readIcon("/com/fr/design/images/m_report/p.gif"), + variableResolver.resolveReportParameterVariables()).createMutableTreeNode(); + + rootNode.add(reportParameterTreeNode); + } + + { + MutableTreeNode globalParameterTreeNode = new TextFolderUserObject( + Inter.getLocText("M_Server-Global_Parameters"), + BaseUtils.readIcon("/com/fr/design/images/dialog/parameter.gif"), + variableResolver.resolveGlobalParameterVariables()).createMutableTreeNode(); + rootNode.add(globalParameterTreeNode); + } + + + variableModel.reload(); + + // Expand + for (int row = 0; row < this.variablesTree.getRowCount(); row++) { + this.variablesTree.expandRow(row); + } + } + } + + public static class TextFolderUserObject { + + private String text; + private Icon icon; + private String[] subNodes = new String[0]; + + public TextFolderUserObject(String text, Icon icon, String[] subNodes) { + this.text = text; + this.icon = icon; + this.subNodes = subNodes; + } + + public String getText() { + return this.text; + } + + public Icon getIcon() { + return this.icon; + } + + MutableTreeNode createMutableTreeNode() { + DefaultMutableTreeNode variableTreeNode = new DefaultMutableTreeNode(this); + + for (String subNode : subNodes) { + variableTreeNode.add(new DefaultMutableTreeNode(new TextUserObject(subNode))); + } + + return variableTreeNode; + } + } + + public static class TextUserObject { + + public TextUserObject(String text) { + this(text, text); + } + + public TextUserObject(String text, String displayText) { + this.text = text; + this.displayText = displayText; + } + + public String getText() { + return this.text; + } + + public String getDisplayText() { + return this.displayText; + } + + private String text; + private String displayText; + } + + public static void main(String[] args) { + FunctionGroup group = FunctionConstants.ALL; + NameAndDescription[] nameAndDescriptions = group.getDescriptions(); + StringBuffer buffer = new StringBuffer(); + for (NameAndDescription d : nameAndDescriptions) { + String name = d.getName(); + buffer.append("\""); + buffer.append(name.toUpperCase()); + buffer.append("\""); + buffer.append("|"); + buffer.append("\n"); + buffer.append("\""); + buffer.append(name.toLowerCase()); + buffer.append("\""); + buffer.append("|"); + buffer.append("\n"); + } + System.out.println(buffer.toString()); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FormulaPaneWhenReserveFormula.java b/designer_base/src/com/fr/design/formula/FormulaPaneWhenReserveFormula.java new file mode 100644 index 0000000000..cd55c06bd3 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FormulaPaneWhenReserveFormula.java @@ -0,0 +1,64 @@ +package com.fr.design.formula; + +import com.fr.base.Formula; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.general.Inter; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; + +/** + * @author richie + * @date 2015-04-17 + * @since 8.0 + */ +public class FormulaPaneWhenReserveFormula extends FormulaPane { + private UICheckBox reserveCheckBox4Result; + private UICheckBox reserveCheckBox4Write; + + public FormulaPaneWhenReserveFormula() { + super(); + } + + @Override + protected void extendCheckBoxPane(JPanel checkBoxPane) { + // peter:添加公式是否兼容Excel的属性 + reserveCheckBox4Result = new UICheckBox(Inter.getLocText("FormulaD-Reserve_when_export-edit_result")); + reserveCheckBox4Result.setSelected(false); + reserveCheckBox4Result.addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent arg0) { + if (reserveCheckBox4Result.isSelected()) { + reserveCheckBox4Write.setSelected(true); + reserveCheckBox4Write.setEnabled(false); + } else { + reserveCheckBox4Write.setEnabled(true); + } + } + }); + reserveCheckBox4Write = new UICheckBox(Inter.getLocText("FormulaD-Reserve_when_bs-write_or_analy")); + reserveCheckBox4Write.setSelected(false); + + checkBoxPane.add(reserveCheckBox4Result, BorderLayout.CENTER); + checkBoxPane.add(reserveCheckBox4Write, BorderLayout.SOUTH); + } + + @Override + public void populate(Formula formula, VariableResolver variableResolver) { + super.populate(formula, variableResolver); + reserveCheckBox4Result.setSelected(formula.isReserveInResult()); + reserveCheckBox4Write.setSelected(formula.isReserveOnWriteOrAnaly()); + } + + @Override + public Formula update() { + Formula formula = super.update(); + if (formula != null) { + formula.setReserveInResult(this.reserveCheckBox4Result.isSelected()); + formula.setReserveOnWriteOrAnaly(this.reserveCheckBox4Write.isSelected()); + } + return formula; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FunctionConstants.java b/designer_base/src/com/fr/design/formula/FunctionConstants.java new file mode 100644 index 0000000000..dd30812716 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FunctionConstants.java @@ -0,0 +1,205 @@ +package com.fr.design.formula; + +import com.fr.base.FRContext; +import com.fr.file.FunctionManager; +import com.fr.file.FunctionManagerProvider; +import com.fr.function.*; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.plugin.ExtraClassManager; +import com.fr.stable.EncodeConstants; +import com.fr.stable.OperatingSystem; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.script.Function; +import com.fr.stable.script.FunctionDef; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public abstract class FunctionConstants { + + public static FunctionGroup PLUGIN = new FunctionGroup() { + @Override + public String getGroupName() { + return Inter.getLocText("FR-Base_Formula_Plugin"); + } + + @Override + public NameAndDescription[] getDescriptions() { + FunctionDef[] fs = ExtraClassManager.getInstance().getFunctionDef(); + int count = fs.length; + FunctionDefNAD[] nads = new FunctionDefNAD[count]; + for (int i = 0; i < count; i ++) { + nads[i] = new FunctionDefNAD(fs[i]); + } + return nads; + } + }; + + public static FunctionGroup CUSTOM = new FunctionGroup() { + @Override + public String getGroupName() { + return Inter.getLocText("FormulaD-Custom_Function"); + } + + @Override + public NameAndDescription[] getDescriptions() { + FunctionManagerProvider funtionManager = FunctionManager.getProviderInstance(); + if (funtionManager != null) { + int functionDefCount = funtionManager.getFunctionDefCount(); + + FunctionDefNAD[] nads = new FunctionDefNAD[functionDefCount]; + for (int i = 0; i < functionDefCount; i++) { + nads[i] = new FunctionDefNAD(funtionManager.getFunctionDef(i)); + } + + return nads; + } + + return new NameAndDescription[0]; + } + }; + + public static NameAndFunctionList COMMON = new NameAndFunctionList(Inter.getLocText("FormulaD-Most_Recently_Used"), new Function[] { + new SUM(), new COUNT(), new AVERAGE(), new CHAR(), new DATE(), new MAX(), new MIN(), new TIME(), new RANGE() + }); + + public static NameAndTypeAndFunctionList[] EMBFUNCTIONS = new NameAndTypeAndFunctionList[] { + new NameAndTypeAndFunctionList(Inter.getLocText("FormulaD-Math_&_Trig"), Function.MATH), + new NameAndTypeAndFunctionList(Inter.getLocText("FR-Designer_FormulaD-Text"), Function.TEXT), + new NameAndTypeAndFunctionList(Inter.getLocText("FormulaD-Date_&_Time"), Function.DATETIME), + new NameAndTypeAndFunctionList(Inter.getLocText("FR-Designer_FormulaD-Logical"), Function.LOGIC), + new NameAndTypeAndFunctionList(Inter.getLocText("FR-Designer_FormulaD-Array"), Function.ARRAY), + new NameAndTypeAndFunctionList(Inter.getLocText("FR-Designer_FormulaD-Report"), Function.REPORT), + new NameAndTypeAndFunctionList(Inter.getLocText("FR-Designer_FormulaD-Other"), Function.OTHER), + new NameAndTypeAndFunctionList(Inter.getLocText(new String[]{"Level_coordinates", "FormulaD-Functions"}), Function.HA) + }; + + public static FunctionGroup ALL = new FunctionGroup() { + @Override + public String getGroupName() { + return Inter.getLocText("FR-Designer_FormulaD-All"); + } + + @Override + public NameAndDescription[] getDescriptions() { + List all = new ArrayList(); + for (int i = 0; i < EMBFUNCTIONS.length; i++) { + all.addAll(Arrays.asList(EMBFUNCTIONS[i].getDescriptions())); + } + Collections.addAll(all, PLUGIN.getDescriptions()); + Collections.addAll(all, CUSTOM.getDescriptions()); + + java.util.Collections.sort(all, NameAndDescriptionComparator); + + return all.toArray(new NameAndDescription[all.size()]); + } + }; + + + + private static Comparator NameAndDescriptionComparator = new Comparator() { + @Override + public int compare(NameAndDescription o1, NameAndDescription o2) { + return ComparatorUtils.compare(o1.getName(), o2.getName()); + } + }; + + private static String[] findClassNamesUnderFilePath(String filePath) { + java.util.List classNameList = new ArrayList(); + /* + * alex:如果是jar包中的class文件 + * file:/D:/opt/FineReport6.5/WebReport/WEB-INF/lib/fr-server-6.5.jar!/com/fr/rpt/script/function + */ + if (filePath.indexOf("!/") >= 0) { + String[] arr = filePath.split("!/"); + String jarPath = arr[0].substring(6); // alex:substring(6)去掉前面的file:/这六个字符 + String classPath = arr[1]; + if (OperatingSystem.isMacOS()){ + //windows里substring后是d:\123\456, mac下substring后是Application/123/456 + jarPath = StringUtils.perfectStart(jarPath, "/"); + } + + ZipFile zip; + try { + zip = new ZipFile(jarPath); + Enumeration entries = zip.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + if (entry.isDirectory()) { + continue; + } + + String entryName = entry.getName(); + if (entryName.indexOf(classPath) < 0 || !entryName.endsWith(".class")) { + continue; + } + + classNameList.add(entryName.substring(classPath.length() + 1)); + } + } catch (IOException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } else { + File dir = new File(filePath); + + for (File f : dir.listFiles()) { + String fileName = f.getName(); + if (fileName.endsWith(".class")) { + classNameList.add(fileName); + } + } + } + + return classNameList.toArray(new String[classNameList.size()]); + } + + // alex:读取com.fr.script.function包下面所有的Function类 + static { + String pkgName = "com.fr.function"; + Class iface = Function.class; + ClassLoader classloader = iface.getClassLoader(); + URL url = classloader.getResource(pkgName.replace('.', '/')); + String classFilePath = url.getFile(); + + /* + * alex:url.getFile获取的地址中,如果有空格或中文会被URLEncoder.encode处理 + * 会变成%20这种%打头的东西,但是new File的时候%20是无法解析成空格,所以在此需要做URLDecoder.decode处理 + */ + try { + classFilePath = URLDecoder.decode(classFilePath, EncodeConstants.ENCODING_UTF_8); + } catch (UnsupportedEncodingException e1) { + FRContext.getLogger().error(e1.getMessage(), e1); + } + FRContext.getLogger().info("ClassFilePath:" + classFilePath); + /* + * alex:如果是jar包中的class文件 + * file:/D:/opt/FineReport6.5/WebReport/WEB-INF/lib/fr-server-6.5.jar!/com/fr/rpt/script/function + */ + for (String fileName : findClassNamesUnderFilePath(classFilePath)) { + try { + Class cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6)); + if (StableUtils.classInstanceOf(cls, iface)) { + Function inst; + inst = (Function)cls.newInstance(); + for (int fi = 0; fi < EMBFUNCTIONS.length; fi++) { + if (EMBFUNCTIONS[fi].test(inst)) { + break; + } + } + + } + } catch (ClassNotFoundException e) { + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FunctionDefNAD.java b/designer_base/src/com/fr/design/formula/FunctionDefNAD.java new file mode 100644 index 0000000000..c7c2177b58 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FunctionDefNAD.java @@ -0,0 +1,22 @@ +package com.fr.design.formula; + +import com.fr.stable.script.FunctionDef; +import com.fr.stable.StringUtils; + +public class FunctionDefNAD extends AbstractNameAndDescription { + private FunctionDef def; + + FunctionDefNAD(FunctionDef def) { + this.def = def; + } + + @Override + public String getName() { + return def == null ? StringUtils.EMPTY : def.getName(); + } + + @Override + public String getDesc() { + return def == null ? StringUtils.EMPTY : def.getDescription(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FunctionGroup.java b/designer_base/src/com/fr/design/formula/FunctionGroup.java new file mode 100644 index 0000000000..4764454ede --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FunctionGroup.java @@ -0,0 +1,7 @@ +package com.fr.design.formula; + + +public interface FunctionGroup { + String getGroupName(); + NameAndDescription[] getDescriptions(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FunctionManagerPane.java b/designer_base/src/com/fr/design/formula/FunctionManagerPane.java new file mode 100644 index 0000000000..4af0c27997 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FunctionManagerPane.java @@ -0,0 +1,220 @@ +package com.fr.design.formula; + +import com.fr.base.FRContext; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.data.tabledata.tabledatapane.ClassNameSelectPane; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.controlpane.JControlPane; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextarea.DescriptionTextArea; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.file.FunctionManagerProvider; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.stable.Nameable; +import com.fr.stable.project.ProjectConstants; +import com.fr.stable.script.FunctionDef; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class FunctionManagerPane extends BasicPane { + + private UITextField functionTextField; + private FunctionControlPane functionControlPane; + + public FunctionManagerPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + //path pane + JPanel datasourcePathPane = FRGUIPaneFactory.createBorderLayout_L_Pane(); + this.add(datasourcePathPane, BorderLayout.NORTH); + + + datasourcePathPane.add(new UILabel(Inter.getLocText( + "Function-Function_File") + ":"), BorderLayout.WEST); + this.functionTextField = new UITextField(); + datasourcePathPane.add(this.functionTextField, BorderLayout.CENTER); + this.functionTextField.setEditable(false); + + functionControlPane = new FunctionControlPane(); + this.add(functionControlPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Function-Function_Manager"); + } + + /** + * Populate. + */ + public void populate(FunctionManagerProvider functionManager) { + this.functionTextField.setText(FRContext.getCurrentEnv().getPath() + File.separator + + ProjectConstants.RESOURCES_NAME + + File.separator + functionManager.fileName()); + + List nameObjectList = new ArrayList(); + for (int i = 0; i < functionManager.getFunctionDefCount(); i++) { + String name = functionManager.getFunctionDef(i).getName(); + nameObjectList.add(new NameObject(name, functionManager.getFunctionDef(i))); + } + functionControlPane.populate(nameObjectList.toArray(new NameObject[nameObjectList.size()])); + + } + + /** + * Update. + */ + public void update(FunctionManagerProvider functionManager) { + // Nameable[]居然不能强转成NameObject[],一定要这么写... + Nameable[] res = this.functionControlPane.update(); + NameObject[] res_array = new NameObject[res.length]; + java.util.Arrays.asList(res).toArray(res_array); + + functionManager.clearAllFunctionDef(); + + for (int i = 0; i < res_array.length; i++) { + FunctionDef fd = (FunctionDef) res_array[i].getObject(); + fd.setName(res_array[i].getName()); + functionManager.addFunctionDef(fd); + } + } + + /** + * CellRenderer. + */ + class FunctionControlPane extends JControlPane { + + public FunctionControlPane() { + super(); + } + + @Override + public NameableCreator[] createNameableCreators() { + NameableCreator funcDef = new NameObjectCreator(Inter.getLocText("FR-Designer_Function"), FunctionDef.class, + FunctionContentPane.class); + return new NameableCreator[]{funcDef}; + } + + @Override + protected String title4PopupWindow() { + return FunctionManagerPane.this.title4PopupWindow(); + } + } + + public static class FunctionContentPane extends BasicBeanPane { + private FunctionDef editing; + + private UITextField classNameTextField; + private UITextArea descriptionTextArea; + + public FunctionContentPane() { + this.initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0)); + JPanel northPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); + this.add(northPane, BorderLayout.NORTH); + JPanel reportletNamePane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + classNameTextField = new UITextField(28); + reportletNamePane.add(classNameTextField); + UIButton browserButton = new UIButton(Inter.getLocText("FR-Designer_Select")); + browserButton.setPreferredSize(new Dimension(browserButton.getPreferredSize().width, classNameTextField.getPreferredSize().height)); + reportletNamePane.add(browserButton); + browserButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + final ClassNameSelectPane bPane = new ClassNameSelectPane(); + bPane.setClassPath(classNameTextField.getText()); + bPane.showWindow( (Dialog) SwingUtilities.getWindowAncestor(FunctionContentPane.this), + new DialogActionAdapter() { + public void doOk() { + classNameTextField.setText(bPane.getClassPath()); + } + }).setVisible(true); + } + }); + UIButton editorButton = new UIButton(Inter.getLocText("FR-Designer_Edit")); + editorButton.setPreferredSize(new Dimension(editorButton.getPreferredSize().width, classNameTextField.getPreferredSize().height)); + reportletNamePane.add(editorButton); + editorButton.addActionListener(createEditorButtonActionListener()); + northPane.add(GUICoreUtils.createFlowPane(new Component[]{new UILabel(Inter.getLocText("DS-Class_Name") + ":"), + reportletNamePane}, FlowLayout.LEFT)); + DescriptionTextArea descriptionArea = new DescriptionTextArea(); + descriptionArea.setWrapStyleWord(true); + descriptionArea.setLineWrap(true); + northPane.add(descriptionArea); + descriptionArea.setText(Inter.getLocText(new String[]{"Function-The_class_must_inherit","Fuction-The_compiled_class_should_be_copied_to", + "Function-J2EE_server", "Directory", "Function-Source_Code", "Example"}, + new String[]{" \"com.fr.script.AbstractFunction\".", "\n", " \"" + File.separator + "WEB-INF" + File.separator + "classes\"", + ",", ".\n", ":" + FRContext.getCurrentEnv().getPath() + File.separator + "classes"})); + JPanel descriptionPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); //Description Pane + this.add(descriptionPane, BorderLayout.SOUTH); + descriptionPane.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); + descriptionPane.add(new UILabel(Inter.getLocText("FR-Designer_Description") + ":"), BorderLayout.NORTH); + this.descriptionTextArea = new UITextArea(6, 24); + descriptionPane.add(new JScrollPane(this.descriptionTextArea), BorderLayout.CENTER); + } + + private ActionListener createEditorButtonActionListener() { + return new ActionListener() { + public void actionPerformed(ActionEvent e) { + final JavaEditorPane javaEditorPane = new JavaEditorPane(classNameTextField.getText(), JavaEditorPane.DEFAULT_FUNCTION_STRING); + final BasicDialog dlg = javaEditorPane.showMediumWindow(SwingUtilities.getWindowAncestor(FunctionContentPane.this), + new DialogActionAdapter() { + public void doOk() { + classNameTextField.setText(javaEditorPane.getClassText()); + } + }); + javaEditorPane.addSaveActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dlg.doOK(); + } + }); + dlg.setVisible(true); + } + }; + } + + @Override + protected String title4PopupWindow() { + return "Function"; + } + + public String getReportletPath() { + return this.classNameTextField.getText(); + } + + @Override + public void populateBean(FunctionDef ob) { + editing = ob; + + this.classNameTextField.setText(ob.getClassName()); + this.descriptionTextArea.setText(ob.getDescription()); + } + + @Override + public FunctionDef updateBean() { + editing.setClassName(this.classNameTextField.getText()); + editing.setDescription(this.descriptionTextArea.getText()); + + return editing; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/FunctionNAD.java b/designer_base/src/com/fr/design/formula/FunctionNAD.java new file mode 100644 index 0000000000..9babc51e56 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/FunctionNAD.java @@ -0,0 +1,42 @@ +package com.fr.design.formula; + +import java.util.Locale; + +import com.fr.base.FRContext; +import com.fr.stable.StringUtils; +import com.fr.stable.script.Function; + +public class FunctionNAD extends AbstractNameAndDescription { + private Function fn; + + FunctionNAD(Function fn) { + this.fn = fn; + } + + public String getName() { + return fn == null ? StringUtils.EMPTY : fn.getClass().getSimpleName(); + } + + public String getDesc() { + if (fn == null) { + return StringUtils.EMPTY; + } else { + if (Locale.CHINA.equals(FRContext.getLocale())) { + return fn.getCN(); + } else { + return fn.getEN(); + } + } + } + + @Override + public String searchResult(String keyWord, boolean findDescription) { + String functionName = getName(); + String des = getDesc(); + if (findDescription && des.contains(keyWord)) { + return functionName; + } else { + return super.searchResult(keyWord, findDescription); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/JavaEditorPane.java b/designer_base/src/com/fr/design/formula/JavaEditorPane.java new file mode 100644 index 0000000000..0ba32641cd --- /dev/null +++ b/designer_base/src/com/fr/design/formula/JavaEditorPane.java @@ -0,0 +1,287 @@ +package com.fr.design.formula; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.FRLogger; +import com.fr.general.Inter; +import com.fr.stable.EncodeConstants; +import com.fr.stable.JavaCompileInfo; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.stable.project.ProjectConstants; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.util.ArrayList; +import java.util.concurrent.ExecutionException; + + +public class JavaEditorPane extends BasicPane { + private RSyntaxTextArea javaText; + private String className; + private java.util.List actionListeners = new ArrayList(); + + public JavaEditorPane(String className, String defaultText) { + this.className = className; + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + javaText = new RSyntaxTextArea(); + configRSyntax(javaText); + if (StringUtils.isNotEmpty(className)) { + javaText.setText("//Loading source code from server..."); + new SwingWorker(){ + + @Override + protected String doInBackground() throws Exception { + InputStream in = getJavaSourceInputStream(); + if (in == null) { + return null; + } else { + try { + return StableUtils.inputStream2String(in, EncodeConstants.ENCODING_UTF_8); + } catch (IOException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + return null; + } + + @Override + public void done() { + try { + String source = get(); + if (StringUtils.isNotEmpty(source)) { + javaText.setText(source); + } else { + javaText.setText("//Didn't find java source match the class"); + } + } catch (Exception e) { + FRLogger.getLogger().error(e.getMessage(), e); + javaText.setText("//Loading source code from server error"); + } + } + + }.execute(); + } else { + javaText.setText(defaultText); + } + + UIScrollPane jt = new UIScrollPane(javaText); + JPanel toolbarPane = new JPanel(new FlowLayout(FlowLayout.LEFT)); + UIButton saveButton = new UIButton(Inter.getLocText("Save")); + saveButton.setAction(new SaveAction()); + UIButton compileButton = new UIButton(Inter.getLocText("Compile")); + compileButton.setAction(new CompilerAction()); + toolbarPane.add(saveButton); + toolbarPane.add(compileButton); + + this.add(toolbarPane, BorderLayout.NORTH); + this.add(jt, BorderLayout.CENTER); + UILabel label = new UILabel(); + label.setText("" + + Inter.getLocText(new String[]{"Attention", "Compile_Success_And_Then_Save"}, new String[]{":", "!"}) + + ""); + label.setPreferredSize(new Dimension(label.getWidth(),label.getHeight() + 20)); + this.add(label, BorderLayout.SOUTH); + } + + public void addSaveActionListener(ActionListener listener) { + actionListeners.add(listener); + } + + private void fireSaveActionListener() { + for (ActionListener listener : actionListeners) { + listener.actionPerformed(null); + } + } + + public String getClassText() { + return this.className; + } + + private InputStream getJavaSourceInputStream() { + String javaPath = getJavaPath(); + try { + return FRContext.getCurrentEnv().readBean(javaPath, ProjectConstants.CLASSES_NAME); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return null; + } + + private String getJavaPath() { + String[] dirs = className.split("\\."); + String path = StableUtils.pathJoin(dirs); + return path + ".java"; + } + + private void configRSyntax(RSyntaxTextArea javaText) { + javaText.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + javaText.setAnimateBracketMatching(true); + javaText.setAntiAliasingEnabled(true); + javaText.setAutoIndentEnabled(true); + javaText.setCodeFoldingEnabled(true); + javaText.setUseSelectedTextColor(true); + javaText.setCloseCurlyBraces(true); + javaText.setBracketMatchingEnabled(true); + javaText.setAntiAliasingEnabled(true); + javaText.setCloseMarkupTags(true); + } + + private class SaveAction extends AbstractAction { //新建文件命令 + public SaveAction() { + super(Inter.getLocText("Save")); + } + public void actionPerformed(ActionEvent e) { + saveTextToFile(javaText.getText()); + } + } + + private void saveTextToFile(String text) { + if (StringUtils.isEmpty(text)) { + return; + } + if (StringUtils.isEmpty(className)) { + return; + } + try { + OutputStream out = FRContext.getCurrentEnv().writeBean(getJavaPath(), ProjectConstants.CLASSES_NAME); + Writer writer = new BufferedWriter(new OutputStreamWriter(out, EncodeConstants.ENCODING_UTF_8)); + writer.write(text); + writer.flush(); + writer.close(); + JOptionPane.showMessageDialog(null, Inter.getLocText(new String[]{"Save", "Successfully"}) + "!"); + fireSaveActionListener(); + } catch (Exception e) { + FRLogger.getLogger().error(e.getMessage(), e); + JOptionPane.showMessageDialog(null, Inter.getLocText(new String[]{"Save", "Failed"}) + "!"); + } + + } + + private class CompilerAction extends AbstractAction { + public CompilerAction() { + super(Inter.getLocText("Compile")); + } + public void actionPerformed(ActionEvent e) { + new SwingWorker() { + + @Override + protected JavaCompileInfo doInBackground() throws Exception { + Env env = FRContext.getCurrentEnv(); + return env.compilerSourceCode(javaText.getText()); + } + + public void done() { + try { + JavaCompileInfo info = get(); + className = info.getIntactClassName(); + String message = info.getCompileMessage(); + if (StringUtils.isEmpty(message)) { + message = Inter.getLocText("Compile_Success") + "!"; + } + JOptionPane.showMessageDialog(null, message); + } catch (InterruptedException e1) { + FRLogger.getLogger().error(e1.getMessage(), e1); + } catch (ExecutionException e1) { + FRLogger.getLogger().error(e1.getMessage(), e1); + } + } + }.execute(); + } + } + + protected String title4PopupWindow() { + return Inter.getLocText("FormulaD-Custom_Function"); + } + + public static final String DEFAULT_TABLEDATA_STRING = "package com.fr.data;\n" + + "\n" + + "\n" + + "import com.fr.data.AbstractTableData;\n" + + "import com.fr.general.data.TableDataException;\n" + + "\n" + + "public class CustomTableData extends AbstractTableData {\n" + + " public CustomTableData() {\n" + + " \n" + + " }\n" + + "\n" + + " /**\n" + + " * 获取数据集的列数\n" + + " * @return 数据集的列\n" + + " * @throws TableDataException\n" + + " */\n" + + " public int getColumnCount() throws TableDataException {\n" + + " return 0;\n" + + " }\n" + + "\n" + + " /**\n" + + " * 获取数据集指定列的列名\n" + + " * @param columnIndex 指定列的索引\n" + + " * @return 指定列的列名\n" + + " * @throws TableDataException\n" + + " */\n" + + " public String getColumnName(int columnIndex) throws TableDataException {\n" + + " return null;\n" + + " }\n" + + "\n" + + " /**\n" + + " * 获取数据集的行数\n" + + " * @return 数据集数据行数\n" + + " * @throws TableDataException\n" + + " */\n" + + " public int getRowCount() throws TableDataException {\n" + + " return 0;\n" + + " }\n" + + "\n" + + " /**\n" + + " * 获取数据集指定位置上的值\n" + + " * @param rowIndex 指定的行索引\n" + + " * @param columnIndex 指定的列索引\n" + + " * @return 指定位置的值\n" + + " */\n" + + " public Object getValueAt(int rowIndex, int columnIndex) {\n" + + " return null;\n" + + " }\n" + + "}\n"; + + public static final String DEFAULT_FUNCTION_STRING = "package com.fr.function;\n" + + "\n" + + "import com.fr.script.AbstractFunction;\n" + + "\n" + + "/**\n" + + " * 自定义函数\n" + + " */\n" + + "public class CustomFun extends AbstractFunction {\n" + + " /**\n" + + " * @param args 函数的参数,是经过了算子处理了其中特殊参数的\n" + + " * @return 经过函数处理的值,用于参与最终计算\n" + + " */\n" + + " public Object run(Object[] args) {\n" + + " return null;\n" + + " }\n" + + "}\n"; + + public static final String DEFAULT_SUBMIT_JOB = "package com.fr.data;\n" + + "\n" + + "import com.fr.script.Calculator;\n" + + "import com.fr.data.DefinedSubmitJob;\n" + + "\n" + + "public class CustomSubmitJob extends DefinedSubmitJob {\n" + + "\n" + + "\n" + + " public void doJob(Calculator calculator) throws Exception {\n" + + "\n" + + " }\n" + + "}\n"; + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/NameAndDescription.java b/designer_base/src/com/fr/design/formula/NameAndDescription.java new file mode 100644 index 0000000000..f58d0fc564 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/NameAndDescription.java @@ -0,0 +1,10 @@ +package com.fr.design.formula; + +public interface NameAndDescription { + + String getName(); + + String getDesc(); + + String searchResult(String keyWord, boolean findDescription); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/NameAndFunctionList.java b/designer_base/src/com/fr/design/formula/NameAndFunctionList.java new file mode 100644 index 0000000000..4c0fa3f651 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/NameAndFunctionList.java @@ -0,0 +1,31 @@ +package com.fr.design.formula; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.fr.stable.script.Function; + +public class NameAndFunctionList implements FunctionGroup { + protected String name; + protected java.util.List fnList = new ArrayList(); + + public NameAndFunctionList(String name, Function[] fns) { + this.name = name; + fnList.addAll(Arrays.asList(fns)); + } + + @Override + public String getGroupName() { + return this.name; + } + + @Override + public NameAndDescription[] getDescriptions() { + NameAndDescription[] nads = new NameAndDescription[fnList.size()]; + for (int i = 0; i < nads.length; i++) { + nads[i] = new FunctionNAD(fnList.get(i)); + } + + return nads; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/NameAndTypeAndFunctionList.java b/designer_base/src/com/fr/design/formula/NameAndTypeAndFunctionList.java new file mode 100644 index 0000000000..6be2223ae1 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/NameAndTypeAndFunctionList.java @@ -0,0 +1,21 @@ +package com.fr.design.formula; + +import com.fr.stable.script.Function; + +public class NameAndTypeAndFunctionList extends NameAndFunctionList { + private Function.Type type; + + public NameAndTypeAndFunctionList(String name, Function.Type type) { + super(name, new Function[0]); + + this.type = type; + } + + public boolean test(Function fn) { + if (fn != null && fn.getType() == this.type) { + return fnList.add(fn); + } + + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/SortFormulaPane.java b/designer_base/src/com/fr/design/formula/SortFormulaPane.java new file mode 100644 index 0000000000..5e3398ec5e --- /dev/null +++ b/designer_base/src/com/fr/design/formula/SortFormulaPane.java @@ -0,0 +1,84 @@ +package com.fr.design.formula; + + +import com.fr.base.Formula; +import com.fr.data.util.SortOrder; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icombobox.SortOrderComboBox; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public abstract class SortFormulaPane extends JPanel { + protected static final String InsetText = " "; + + protected SortOrderComboBox sortOrderComboBox; + protected UITextField sortFormulaTextField; + // 屏蔽掉“自定义比较规则”和“选择”按钮,只显示公式输入文本和公式按钮 + protected UIButton sortFormulaTextFieldButton; + + public SortFormulaPane() { + this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + sortOrderComboBox = new SortOrderComboBox(); + sortOrderComboBox.setSortOrder(new SortOrder(SortOrder.ORIGINAL)); + sortOrderComboBox.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent evt) { + checkSortButtonEnabled(); + } + }); + + sortFormulaTextField = new UITextField(16); + //Lance:添加一公式编辑器按钮 + sortFormulaTextFieldButton = new UIButton("..."); + sortFormulaTextFieldButton.setToolTipText(Inter.getLocText("Formula") + "..."); + sortFormulaTextFieldButton.setPreferredSize(new Dimension(25, sortFormulaTextFieldButton.getPreferredSize().height)); + sortFormulaTextFieldButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + formulaAction(); + } + }); + + this.add(GUICoreUtils.createFlowPane(new JComponent[]{new UILabel(InsetText), //new UILabel(Inter.getLocText("Select_sort_order") + ":"), + sortOrderComboBox, new UILabel(InsetText), + new UILabel(Inter.getLocText("Formula") + ":="), sortFormulaTextField, //selectButton, + sortFormulaTextFieldButton}, FlowLayout.LEFT)); + } + + public abstract void formulaAction(); + + public void showFormulaDialog(String[] displayNames) { + String text = sortFormulaTextField.getText(); + final UIFormula formulaPane = FormulaFactory.createFormulaPaneWhenReserveFormula(); + + formulaPane.populate(new Formula(text), new CustomVariableResolver(displayNames, true)); + formulaPane.showLargeWindow(SwingUtilities.getWindowAncestor(SortFormulaPane.this), + new DialogActionAdapter() { + public void doOk() { + Formula fm = formulaPane.update(); + if (fm.getContent().length() <= 1) { + sortFormulaTextField.setText(""); + } else { + sortFormulaTextField.setText(fm.getContent().substring(1)); + } + } + }).setVisible(true); + } + + private void checkSortButtonEnabled() { + if (this.sortOrderComboBox.getSortOrder().getOrder() == SortOrder.ORIGINAL) { + sortFormulaTextField.setEnabled(false); + sortFormulaTextFieldButton.setEnabled(false); + } else { + sortFormulaTextField.setEnabled(true); + sortFormulaTextFieldButton.setEnabled(true); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/TinyFormulaPane.java b/designer_base/src/com/fr/design/formula/TinyFormulaPane.java new file mode 100644 index 0000000000..16c897bc12 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/TinyFormulaPane.java @@ -0,0 +1,140 @@ +package com.fr.design.formula; + +import com.fr.base.BaseUtils; +import com.fr.base.Formula; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.constants.LayoutConstants; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * + * @author zhou + * @since 2012-6-1下午3:50:37 + */ +public class TinyFormulaPane extends BasicBeanPane implements UIObserver{ + + private static final long serialVersionUID = 1L; + protected UITextField formulaTextField; + protected UIButton formulaTextFieldButton; + + public TinyFormulaPane() { + this.initComponents(); + } + + protected void initComponents() { + + formulaTextField = new UITextField(); + formulaTextField.setGlobalName(Inter.getLocText("ExpandD-Sort_After_Expand")); + + // 添加一公式编辑器按钮 + formulaTextFieldButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/m_insert/formula.png")); + formulaTextFieldButton.setToolTipText(Inter.getLocText("Formula") + "..."); + formulaTextFieldButton.setPreferredSize(new Dimension(24, 20)); + formulaTextFieldButton.setOpaque(false); + formulaTextFieldButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); + formulaTextFieldButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + String text = formulaTextField.getText(); + + final UIFormula formulaPane = FormulaFactory.createFormulaPane(); + formulaPane.populate(new Formula(text)); + formulaPane.showLargeWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + @Override + public void doOk() { + Formula fm = formulaPane.update(); + if (fm.getContent().length() <= 1) { + formulaTextField.setText("$$$"); + } else { + formulaTextField.setText(fm.getContent()); + } + okEvent(); + } + }).setVisible(true); + } + }); + initLayout(); + } + + protected void initLayout() { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] columnSize = {f }; + double[] rowSize = { p }; + + Component[] components1 = new Component[]{ + formulaTextFieldButton + } ; + JPanel pane = new JPanel(new BorderLayout(0,0)); + pane.add(formulaTextField,BorderLayout.CENTER); + pane.add(GUICoreUtils.createFlowPane(components1,FlowLayout.LEFT, LayoutConstants.HGAP_LARGE),BorderLayout.EAST); + + Component[][] components2 = new Component[][]{ + new Component[]{pane} + }; + + JPanel panel= TableLayoutHelper.createTableLayoutPane(components2,rowSize,columnSize) ; + this.setLayout(new BorderLayout()); + this.add(panel,BorderLayout.CENTER) ; + } + + /** + * 公式窗口点击确定后的事件接口 + */ + public void okEvent() { + + } + + public UITextField getUITextField() { + return formulaTextField; + } + + @Override + public void populateBean(String ob) { + this.formulaTextField.setText(ob); + } + + @Override + public String updateBean() { + return formulaTextField.getText().trim(); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Present-Formula_Present"); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, 20); + } + + @Override + public void registerChangeListener(UIObserverListener listener) { + if(formulaTextField != null) { + formulaTextField.registerChangeListener(listener); + } + if(formulaTextFieldButton != null) { + formulaTextFieldButton.registerChangeListener(listener); + } + } + + @Override + public boolean shouldResponseChangeListener() { + return true; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/UIFormula.java b/designer_base/src/com/fr/design/formula/UIFormula.java new file mode 100644 index 0000000000..fa6c75c3a6 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/UIFormula.java @@ -0,0 +1,42 @@ +package com.fr.design.formula; + +import com.fr.base.Formula; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionListener; + +import java.awt.*; + +/** + * @author richie + * @date 2015-06-24 + * @since 8.0 + */ +public interface UIFormula { + + /** + * 从已有的公式还原公式面板 + * @param formula 公式 + */ + void populate(Formula formula); + + /** + * 根据指定的变量处理和公式还原公式面板 + * @param formula 公式 + * @param variableResolver 变量处理器 + */ + void populate(Formula formula, VariableResolver variableResolver); + + /** + * 获取公式面板的参数 + * @return 公式 + */ + Formula update(); + + /** + * 显示窗口 + * @param window 窗口 + * @param l 对话框监听器 + * @return 对话框 + */ + BasicDialog showLargeWindow(Window window, DialogActionListener l); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/VariableResolver.java b/designer_base/src/com/fr/design/formula/VariableResolver.java new file mode 100644 index 0000000000..58f5c71408 --- /dev/null +++ b/designer_base/src/com/fr/design/formula/VariableResolver.java @@ -0,0 +1,30 @@ +package com.fr.design.formula; + + +public interface VariableResolver { + + String[] resolveColumnNames(); + + boolean isBindCell(); + + String[] resolveCurReportVariables(); + + String[] resolveTableDataParameterVariables(); + + String[] resolveReportParameterVariables(); + + String[] resolveGlobalParameterVariables(); + + VariableResolver DEFAULT = new VariableResolverAdapter() { + + @Override + public String[] resolveColumnNames() { + return new String[0]; + } + + @Override + public boolean isBindCell() { + return false; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/formula/VariableResolverAdapter.java b/designer_base/src/com/fr/design/formula/VariableResolverAdapter.java new file mode 100644 index 0000000000..2489c6ff4f --- /dev/null +++ b/designer_base/src/com/fr/design/formula/VariableResolverAdapter.java @@ -0,0 +1,96 @@ +package com.fr.design.formula; + +import com.fr.base.ConfigManager; +import com.fr.base.Parameter; +import com.fr.design.DesignModelAdapter; +import com.fr.base.ConfigManagerProvider; +import com.fr.script.ScriptConstants; +import com.fr.stable.Constants; +import com.fr.stable.script.CalculatorProvider; + +import java.util.ArrayList; +import java.util.List; + +public abstract class VariableResolverAdapter implements VariableResolver { + private static final int TABLE_DATA_PARA = 0; + private static final int REPORT_DATA_PARA = 1; + + /** + * 获取模板内置的一些参数 + * + * @return 内置参数 + */ + public String[] resolveCurReportVariables() { + return new String[] { ScriptConstants.SUMMARY_TAG + "page_number", + ScriptConstants.SUMMARY_TAG + "totalPage_number", + // 下面是权限相关的参数 + ScriptConstants.DETAIL_TAG + Constants.P.PRIVILEGE_USERNAME, ScriptConstants.DETAIL_TAG + Constants.P.PRIVILEGE_AUTHORITY, + ScriptConstants.DETAIL_TAG + Constants.P.PRIVILEGE_DEPARTMETN_AND_POST, + // 空值参数 + "NULL", "NOFILTER", + // request变量 + CalculatorProvider.REPORT_NAME, CalculatorProvider.SERVLET_URL, CalculatorProvider.SERVER_SCHEMA, CalculatorProvider.SERVER_NAME, + CalculatorProvider.SERVER_PORT, CalculatorProvider.SERVER_URL, CalculatorProvider.CONTEXT_PATH, CalculatorProvider.SESSION_ID + }; + } + + private Parameter[] getCurrentModeParameters(int type) { + Parameter[] parameters = null; + if(DesignModelAdapter.getCurrentModelAdapter() == null) { + parameters = new Parameter[0]; + } else { + if(type == TABLE_DATA_PARA) { + parameters = DesignModelAdapter.getCurrentModelAdapter().getTableDataParameters(); + } else if(type == REPORT_DATA_PARA){ + parameters = DesignModelAdapter.getCurrentModelAdapter().getReportParameters(); + } + } + return parameters; + } + + /** + * 获取数据集参数 + * + * @return 所有参数 + */ + public String[] resolveTableDataParameterVariables() { + Parameter[] parameters = getCurrentModeParameters(TABLE_DATA_PARA); + String[] parameterNames = new String[parameters.length]; + for (int i = 0; i < parameters.length; i++) { + parameterNames[i] = ScriptConstants.DETAIL_TAG + parameters[i].getName(); + } + return parameterNames; + } + + /** + * 获取模板参数 + * + * @return 所有参数 + */ + public String[] resolveReportParameterVariables() { + Parameter[] parameters = getCurrentModeParameters(REPORT_DATA_PARA); + String[] parameterNames = new String[parameters.length]; + for (int i = 0; i < parameters.length; i++) { + parameterNames[i] = ScriptConstants.DETAIL_TAG + parameters[i].getName(); + } + return parameterNames; + } + + /** + * 获取全局参数 + * + * @return 所有参数 + */ + public String[] resolveGlobalParameterVariables() { + // 加上全局的参数 + ConfigManagerProvider reportServerManager = ConfigManager.getProviderInstance(); + Parameter[] globalParameters = reportServerManager.getGlobal_Parameters(); + + List variablesList = new ArrayList(); + for (int i = 0; i < (globalParameters == null ? 0 : globalParameters.length); i++) { + variablesList.add(ScriptConstants.DETAIL_TAG + (globalParameters[i]).getName()); + } + + return variablesList.toArray(new String[variablesList.size()]); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/CellAttributeProvider.java b/designer_base/src/com/fr/design/fun/CellAttributeProvider.java new file mode 100644 index 0000000000..d3822da437 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/CellAttributeProvider.java @@ -0,0 +1,20 @@ +package com.fr.design.fun; + +import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; +import com.fr.stable.fun.Level; + +/** + * Created by zhouping on 2015/11/11. + */ +public interface CellAttributeProvider extends Level{ + String MARK_STRING = "CellAttributeProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 构造单元格属性面板 + * @return 面板类 + */ + AbstractAttrNoScrollPane createCellAttributePane(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/CellWidgetOptionProvider.java b/designer_base/src/com/fr/design/fun/CellWidgetOptionProvider.java new file mode 100644 index 0000000000..6fd51f71fd --- /dev/null +++ b/designer_base/src/com/fr/design/fun/CellWidgetOptionProvider.java @@ -0,0 +1,23 @@ +package com.fr.design.fun; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.form.ui.Widget; +import com.fr.stable.fun.Level; + +/** + * @author richie + * @date 2015-01-29 + * @since 8.0 + * 格子中的自定义控件接口 + */ +public interface CellWidgetOptionProvider extends ParameterWidgetOptionProvider, Level { + + String XML_TAG = "CellWidgetOptionProvider"; + + /** + * 自定义格子控件的设计界面类 + * @return 控件设计界面类 + */ + Class> appearanceForWidget(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/ConnectionProvider.java b/designer_base/src/com/fr/design/fun/ConnectionProvider.java new file mode 100644 index 0000000000..24c0f31c1e --- /dev/null +++ b/designer_base/src/com/fr/design/fun/ConnectionProvider.java @@ -0,0 +1,40 @@ +package com.fr.design.fun; + +import com.fr.data.impl.Connection; +import com.fr.design.beans.BasicBeanPane; +import com.fr.stable.fun.Level; + +/** + * @author : richie + * @since : 8.0 + */ +public interface ConnectionProvider extends Level { + + public static final String XML_TAG = "ConnectionProvider"; + + int CURRENT_LEVEL = 1; + + /** + * 数据连接弹出菜单的名字 + * @return 名字 + */ + public String nameForConnection(); + + /** + * 数据连接弹出菜单的图标 + * @return 图标路径 + */ + public String iconPathForConnection(); + + /** + * 数据连接的类型 + * @return 连接类型 + */ + public Class classForConnection(); + + /** + * 数据连接的设计界面 + * @return 设计界面 + */ + public Class> appearanceForConnection(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/ExportToolBarProvider.java b/designer_base/src/com/fr/design/fun/ExportToolBarProvider.java new file mode 100644 index 0000000000..d09817401e --- /dev/null +++ b/designer_base/src/com/fr/design/fun/ExportToolBarProvider.java @@ -0,0 +1,43 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.Level; + +import javax.swing.*; + +/** + * 导出菜单设计器端拓展,用于控制该菜单是否在web端显示 + * @author focus + * @date Jul 2, 2015 + * @since 8.0 + */ +public interface ExportToolBarProvider extends Level{ + + String XML_TAG = "ExportToolBarProvider"; + + int CURRENT_LEVEL = 1; + + + + /** + * + * 用于添加 控制web端是否显示该菜单的checkbox的面板 + * + * @param pane 面板 + * @return 该面板 + */ + JPanel updateCenterPane(JPanel pane); + + /** + * 根据xml里面存的web段按钮显示状态更新对应的checkbox + * + */ + void populate(); + + /** + * 根据checkbox控制web段菜单是否显示 + * + * @return + */ + void update(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/Feedback.java b/designer_base/src/com/fr/design/fun/Feedback.java new file mode 100644 index 0000000000..f1e3c7971e --- /dev/null +++ b/designer_base/src/com/fr/design/fun/Feedback.java @@ -0,0 +1,19 @@ +package com.fr.design.fun; + +/** + * @author richie + * @date 2015-03-31 + * @since 8.0 + */ +public interface Feedback { + String MARK_STRING = "FineReport_Feedback"; + + void didFeedback(); + + Feedback EMPTY = new Feedback() { + @Override + public void didFeedback() { + + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/FormElementCaseEditorProcessor.java b/designer_base/src/com/fr/design/fun/FormElementCaseEditorProcessor.java new file mode 100644 index 0000000000..346fdb2b05 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/FormElementCaseEditorProcessor.java @@ -0,0 +1,24 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.Level; + +import java.beans.PropertyDescriptor; + +/** + * Created by zhouping on 2015/9/10. + */ +public interface FormElementCaseEditorProcessor extends Level{ + + String MARK_STRING = "PropertyEditor"; + + int CURRENT_LEVEL = 1; + + + /** + * 生成属性表 + * @param temp 传入当前操作的class + * @return 返回属性表 + */ + PropertyDescriptor[] createPropertyDescriptor(Class temp); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/FormWidgetOptionProvider.java b/designer_base/src/com/fr/design/fun/FormWidgetOptionProvider.java new file mode 100644 index 0000000000..24a32da000 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/FormWidgetOptionProvider.java @@ -0,0 +1,21 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.Level; + +/** + * @author richie + * @date 2015-03-23 + * @since 8.0 + * 表单控件 + */ +public interface FormWidgetOptionProvider extends ParameterWidgetOptionProvider, Level { + + String XML_TAG = "FormWidgetOptionProvider"; + + /** + * 组件是否是布局容器 + * @return 是布局容器则返回true,否则返回false + */ + boolean isContainer(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/GlobalListenerProvider.java b/designer_base/src/com/fr/design/fun/GlobalListenerProvider.java new file mode 100644 index 0000000000..87e3f99ee2 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/GlobalListenerProvider.java @@ -0,0 +1,19 @@ +package com.fr.design.fun; + + +import com.fr.stable.fun.Level; + +import java.awt.event.AWTEventListener; + +/** + * Created by zack on 2015/8/17. + */ +public interface GlobalListenerProvider extends Level{ + + String XML_TAG = "GlobalListenerProvider"; + + int CURRENT_LEVEL = 1; + + + AWTEventListener listener(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/HighlightProvider.java b/designer_base/src/com/fr/design/fun/HighlightProvider.java new file mode 100644 index 0000000000..5961340737 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/HighlightProvider.java @@ -0,0 +1,32 @@ +package com.fr.design.fun; + +import com.fr.design.condition.ConditionAttrSingleConditionPane; +import com.fr.design.condition.ConditionAttributesPane; +import com.fr.stable.fun.Level; + +/** + * @author richie + * @date 2015-03-26 + * @since 8.0 + * 条件属性接口 + */ +public interface HighlightProvider extends Level{ + + String MARK_STRING = "HighlightProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 条件属性的实现类 + * @return 实现类 + */ + Class classForHighlightAction(); + + /** + * 条件属性的界面 + * @param conditionAttributesPane 条件界面 + * @return 设置界面 + */ + ConditionAttrSingleConditionPane appearanceForCondition(ConditionAttributesPane conditionAttributesPane); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/HyperlinkProvider.java b/designer_base/src/com/fr/design/fun/HyperlinkProvider.java new file mode 100644 index 0000000000..58d7a490ad --- /dev/null +++ b/designer_base/src/com/fr/design/fun/HyperlinkProvider.java @@ -0,0 +1,20 @@ +package com.fr.design.fun; + +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.stable.fun.Level; + +/** + * Created by zack on 2016/1/20. + */ +public interface HyperlinkProvider extends Level{ + String XML_TAG = "HyperlinkProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 创建一个超级连接类型 + * @return NameableCreator + */ + NameableCreator createHyperlinkCreator(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/IndentationUnitProcessor.java b/designer_base/src/com/fr/design/fun/IndentationUnitProcessor.java new file mode 100644 index 0000000000..9c4a5c854b --- /dev/null +++ b/designer_base/src/com/fr/design/fun/IndentationUnitProcessor.java @@ -0,0 +1,31 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.Level; + +/** + * Created by zhouping on 2015/9/20. + */ +public interface IndentationUnitProcessor extends Level{ + String MARK_STRING = "IndentationProcessor"; + + int CURRENT_LEVEL = 1; + + + int getIndentationUnit(); + + void setIndentationUnit(int value); + + /** + * 处理paddingunit + * @param value 输入 + * @return 输出 + */ + int paddingUnitProcessor(int value); + + /** + * 从spinner获得缩进值,并处理后变成paddingunit + * @param value 输入值 + * @return 输出 + */ + int paddingUnitGainFromSpinner(int value); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java b/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java new file mode 100644 index 0000000000..e1c570d541 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/JavaScriptActionProvider.java @@ -0,0 +1,18 @@ +package com.fr.design.fun; + +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.js.JavaScript; +import com.fr.stable.fun.Level; + +/** + * Created by zack on 2015/8/14. + */ +public interface JavaScriptActionProvider extends Level{ + + String XML_TAG = "JavaScriptActionProvider"; + + int CURRENT_LEVEL = 1; + + + FurtherBasicBeanPane getJavaScriptActionPane(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/MenuHandler.java b/designer_base/src/com/fr/design/fun/MenuHandler.java new file mode 100644 index 0000000000..53958f8562 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/MenuHandler.java @@ -0,0 +1,76 @@ +package com.fr.design.fun; + +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.menu.ShortCut; +import com.fr.stable.fun.Level; + +/** + * @author richie + * @date 2015-04-01 + * @since 8.0 + * 设计器菜单栏插件接口 + */ +public interface MenuHandler extends Level{ + + String MARK_STRING = "MenuHandler"; + + int CURRENT_LEVEL = 1; + + + int LAST = -1; + + String HELP = "help"; + String SERVER = "server"; + String FILE = "file"; + String TEMPLATE = "template"; + String INSERT = "insert"; + String CELL = "cell"; + + /** + * 插入菜单的位置 + * + * @param total 插入的位置 + * + * @return 插入位置,如果想放到最后,则返回-1 + */ + int insertPosition(int total); + + /** + * 是否在插入的菜单前插入一个分割符 + * @return 是否插入分隔符 + */ + boolean insertSeparatorBefore(); + + /** + * 是否在插入的菜单后插入一个分割符 + * @return 是否插入分隔符 + */ + boolean insertSeparatorAfter(); + + /** + * 所属的分类菜单 + * @return 分类菜单名 + */ + String category(); + + /** + * 具体的菜单项内容 + * @return 菜单项内容 + */ + ShortCut shortcut(); + + /** + * 具体的菜单项内容 + * @param plus 当前模板 + * + * @return 菜单项内容 + */ + ShortCut shortcut(ToolBarMenuDockPlus plus); + + /** + * 两个菜单项相等等情况 + * @param obj 比较对象 + * @return 相等则返回true,否则返回false + */ + boolean equals(Object obj); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/ParameterWidgetOptionProvider.java b/designer_base/src/com/fr/design/fun/ParameterWidgetOptionProvider.java new file mode 100644 index 0000000000..dfa0dda623 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/ParameterWidgetOptionProvider.java @@ -0,0 +1,41 @@ +package com.fr.design.fun; + +import com.fr.form.ui.Widget; +import com.fr.stable.fun.Level; + +/** + * @author : richie + * @since : 8.0 + * 自定义参数界面控件 + */ +public interface ParameterWidgetOptionProvider extends Level{ + + String XML_TAG = "ParameterWidgetOptionProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 自定义参数控件的实际类,该类需要继承自com.fr.form.ui.Widget + * @return 控件类 + */ + Class classForWidget(); + + /** + * 自定义参数控件的设计界面类,该类需要继承自com.fr.form.designer.creator.XWidgetCreator + * @return 控件设计界面类 + */ + Class appearanceForWidget(); + + /** + * 自定义参数控件在设计器界面上的图标路径 + * @return 图标所在的路径 + */ + String iconPathForWidget(); + + /** + * 自定义参数控件的名字 + * @return 控件名字 + */ + String nameForWidget(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/PresentKindProvider.java b/designer_base/src/com/fr/design/fun/PresentKindProvider.java new file mode 100644 index 0000000000..8e224e49cd --- /dev/null +++ b/designer_base/src/com/fr/design/fun/PresentKindProvider.java @@ -0,0 +1,42 @@ +package com.fr.design.fun; + +import com.fr.base.present.Present; +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.stable.fun.Level; + +/** + * @author richie + * @date 2015-05-22 + * @since 8.0 + * 形态类型接口 + */ +public interface PresentKindProvider extends Level{ + + int CURRENT_LEVEL = 1; + + String MARK_STRING = "PresentKindProvider"; + + /** + * 形态设置界面 + * @return 形态设置界面 + */ + FurtherBasicBeanPane appearanceForPresent(); + + /** + * 在形态设置面板上显示的名字 + * @return 名字 + */ + String title(); + + /** + * 该形态对应的类 + * @return 类 + */ + Class kindOfPresent(); + + /** + * 菜单快捷键 + * @return 快捷点对应的字符 + */ + char mnemonic(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/PreviewProvider.java b/designer_base/src/com/fr/design/fun/PreviewProvider.java new file mode 100644 index 0000000000..3536970b84 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/PreviewProvider.java @@ -0,0 +1,57 @@ +package com.fr.design.fun; + +import com.fr.design.mainframe.JTemplate; +import com.fr.stable.fun.Level; + +import java.util.Map; + +/** + * @author richie + * @date 2015-03-19 + * @since 8.0 + * 自定义预览方式接口 + */ +public interface PreviewProvider extends Level{ + + String MARK_STRING = "PreviewProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 下拉弹出菜单的名字 + * @return 弹出菜单名字 + */ + String nameForPopupItem(); + + /** + * 下拉弹出菜单的图标路径 + * @return 图标路径 + */ + String iconPathForPopupItem(); + + /** + * 大图标路径 + * @return 大图标路径 + */ + String iconPathForLarge(); + + /** + * 点击下拉菜单时触发的事件 + * @param jt 当前的模板对象 + */ + void onClick(JTemplate jt); + + /** + * 用于标记预览类型的整数 + * @return 预览类型 + */ + int previewTypeCode(); + + /** + * 该种预览方式所携带的默认参数集合 + * @return 参数集合 + */ + Map parametersForPreview(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/ServerTableDataDefineProvider.java b/designer_base/src/com/fr/design/fun/ServerTableDataDefineProvider.java new file mode 100644 index 0000000000..63d8d6221c --- /dev/null +++ b/designer_base/src/com/fr/design/fun/ServerTableDataDefineProvider.java @@ -0,0 +1,12 @@ +package com.fr.design.fun; + +/** + * @author : richie + * @since : 8.0 + * 自定义服务器数据集设计界面接口 + */ +public interface ServerTableDataDefineProvider extends TableDataDefineProvider { + + public static final String XML_TAG = "ServerTableDataDefineProvider"; + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/SubmitProvider.java b/designer_base/src/com/fr/design/fun/SubmitProvider.java new file mode 100644 index 0000000000..e499689e01 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/SubmitProvider.java @@ -0,0 +1,33 @@ +package com.fr.design.fun; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.stable.fun.Level; + +/** + * 自定义提交接口 + */ +public interface SubmitProvider extends Level{ + + String MARK_STRING = "SubmitProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 设置界面 + * @return 界面 + */ + BasicBeanPane appearanceForSubmit(); + + /** + * 下拉选项 + * @return 下拉框中的文本 + */ + String dataForSubmit(); + + /** + * 键 + * @return 提交的键 + */ + String keyForSubmit(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/TableDataCreatorProvider.java b/designer_base/src/com/fr/design/fun/TableDataCreatorProvider.java new file mode 100644 index 0000000000..db3af82fba --- /dev/null +++ b/designer_base/src/com/fr/design/fun/TableDataCreatorProvider.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.fun; + +import com.fr.design.data.datapane.TableDataNameObjectCreator; + +import java.util.Map; + +/** + * @author : richie + * @since : 8.0 + * @deprecated + * @see com.fr.design.fun.TableDataDefineProvider + * @see com.fr.design.fun.ServerTableDataDefineProvider + */ +public interface TableDataCreatorProvider { + public static final String XML_TAG = "TableDataCreatorProvider"; + + /** + * 获取报表数据集设计界面类型数组 + * @param creators 内置的数据集设计界面类型数组 + * @return 完整的报表数据集设计界面类型数组 + */ + public TableDataNameObjectCreator[] produceReportTableDataCreator(TableDataNameObjectCreator[] creators); + + /** + * 获取服务器数据集设计界面类型数组 + * @param creators 内置的数据集设计界面类型数组 + * @return 完整的服务器数据集设计界面类型数组 + */ + public TableDataNameObjectCreator[] produceServerTableDataCreator(TableDataNameObjectCreator[] creators); + + /** + * 需要将额外使用的数据集以及其设计界面做一个记录 + * @return 额外记录对应 + */ + public Map registerMap(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/TableDataDefineProvider.java b/designer_base/src/com/fr/design/fun/TableDataDefineProvider.java new file mode 100644 index 0000000000..8eb8359038 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/TableDataDefineProvider.java @@ -0,0 +1,53 @@ +package com.fr.design.fun; + +import com.fr.base.TableData; +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.stable.fun.Level; + +/** + * @author : richie + * @since : 7.1.1 + * 自定义报表数据集界面接口,单独存在的一个个数据集 + */ +public interface TableDataDefineProvider extends Level { + + public static final String XML_TAG = "TableDataDefineProvider"; + + int CURRENT_LEVEL = 1; + + /** + * 自定义的数据集设置界面所对应的数据集类型 + * @return 数据集的类型 + */ + public Class classForTableData(); + + /** + * 自定义数据集设置界面所对应的初始化数据集类型,在一种数据集有多个实现的时候有效 + * @return 数据集类型 + */ + public Class classForInitTableData(); + + /** + * 自定义的数据集设置界面所对应的界面类型 + * @return 数据集界面类型 + */ + public Class appearanceForTableData(); + + /** + * 自定义数据集设置界面在菜单上的现实名字 + * @return 名字 + */ + public String nameForTableData(); + + /** + * 自定义数据集在新建的时候名字前缀 + * @return 名字前缀 + */ + public String prefixForTableData(); + + /** + * 自定义数据集在菜单上现实的图标 + * @return 图标 + */ + public String iconPathForTableData(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/TitlePlaceProcessor.java b/designer_base/src/com/fr/design/fun/TitlePlaceProcessor.java new file mode 100644 index 0000000000..ebe0eb4e94 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/TitlePlaceProcessor.java @@ -0,0 +1,15 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.Level; + +import java.awt.*; + +public interface TitlePlaceProcessor extends Level{ + + String MARK_STRING = "TitlePlaceProcessor"; + + int CURRENT_LEVEL = 1; + + + void hold(Container container, Component loggerComponent, Component loginComponent); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/ToolbarItemProvider.java b/designer_base/src/com/fr/design/fun/ToolbarItemProvider.java new file mode 100644 index 0000000000..f5d80e8c27 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/ToolbarItemProvider.java @@ -0,0 +1,39 @@ +package com.fr.design.fun; + +import com.fr.form.ui.Widget; +import com.fr.stable.fun.Level; + +/** + * @author : focus + * @since : 8.0 + * 自定义web工具栏菜单 + */ +public interface ToolbarItemProvider extends Level{ + + String XML_TAG = "ToolbarItemProvider"; + + int CURRENT_LEVEL = 1; + + + /** + * 自定义web工具栏菜单实际类,该类可以继承自com.fr.form.ui.ToolBarMenuButton 或者 com.fr.form.ui.ToolBarButton; + * + * @return 菜单类 + */ + Class classForWidget(); + + /** + * 自定义web工具栏菜单在设计器界面上的图标路径 + * + * @return 图标所在的路径 + */ + String iconPathForWidget(); + + /** + * 自定义web工具栏菜单在设计器上显示的名字 + * + * @return 菜单名 + */ + String nameForWidget(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/UIFormulaProcessor.java b/designer_base/src/com/fr/design/fun/UIFormulaProcessor.java new file mode 100644 index 0000000000..32e6390ab6 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/UIFormulaProcessor.java @@ -0,0 +1,29 @@ +package com.fr.design.fun; + +import com.fr.design.formula.UIFormula; +import com.fr.stable.fun.Level; + +/** + * @author richie + * @date 2015-04-17 + * @since 8.0 + * 公式编辑器界面处理接口 + */ +public interface UIFormulaProcessor extends Level{ + String MARK_STRING = "UIFormulaProcessor"; + + int CURRENT_LEVEL = 1; + + + /** + * 普通的公式编辑器界面类 + * @return 公式编辑器界面类 + */ + UIFormula appearanceFormula(); + + /** + * 当需要显示“保留公式”项时的公式编辑器界面类 + * @return 公式编辑器界面类 + */ + UIFormula appearanceWhenReserveFormula(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractCellAttributeProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractCellAttributeProvider.java new file mode 100644 index 0000000000..e57fb65295 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractCellAttributeProvider.java @@ -0,0 +1,14 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.CellAttributeProvider; + +/** + * Created by zhouping on 2015/11/11. + */ +public abstract class AbstractCellAttributeProvider implements CellAttributeProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractCellWidgetOptionProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractCellWidgetOptionProvider.java new file mode 100644 index 0000000000..eb1b5d7959 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractCellWidgetOptionProvider.java @@ -0,0 +1,17 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.CellWidgetOptionProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractCellWidgetOptionProvider implements CellWidgetOptionProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractConnectionProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractConnectionProvider.java new file mode 100644 index 0000000000..3f8044ae62 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractConnectionProvider.java @@ -0,0 +1,16 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.ConnectionProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractConnectionProvider implements ConnectionProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractFormElementCaseEditorProcessor.java b/designer_base/src/com/fr/design/fun/impl/AbstractFormElementCaseEditorProcessor.java new file mode 100644 index 0000000000..d528627d64 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractFormElementCaseEditorProcessor.java @@ -0,0 +1,25 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.FormElementCaseEditorProcessor; + +import java.beans.PropertyDescriptor; + +/** + * Created by zhouping on 2015/9/10. + */ +public abstract class AbstractFormElementCaseEditorProcessor implements FormElementCaseEditorProcessor { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + + /** + * 生成属性表 + * @param temp 传入当前操作的class + * @return 返回属性表 + */ + public PropertyDescriptor[] createPropertyDescriptor(Class temp){ + return new PropertyDescriptor[0]; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractFormWidgetOptionProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractFormWidgetOptionProvider.java new file mode 100644 index 0000000000..563d544db2 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractFormWidgetOptionProvider.java @@ -0,0 +1,21 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.FormWidgetOptionProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractFormWidgetOptionProvider implements FormWidgetOptionProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + + @Override + public boolean isContainer() { + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractGlobalListenerProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractGlobalListenerProvider.java new file mode 100644 index 0000000000..2cf0232eb0 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractGlobalListenerProvider.java @@ -0,0 +1,15 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.GlobalListenerProvider; + +/** + * Created by zack on 2015/8/17. + */ +public abstract class AbstractGlobalListenerProvider implements GlobalListenerProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractHighlightProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractHighlightProvider.java new file mode 100644 index 0000000000..db03239592 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractHighlightProvider.java @@ -0,0 +1,16 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.HighlightProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractHighlightProvider implements HighlightProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractHyperlinkProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractHyperlinkProvider.java new file mode 100644 index 0000000000..ebb193e5ff --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractHyperlinkProvider.java @@ -0,0 +1,14 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.HyperlinkProvider; + +/** + * Created by zack on 2016/1/18. + */ +public abstract class AbstractHyperlinkProvider implements HyperlinkProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractIndentationUnitProcessor.java b/designer_base/src/com/fr/design/fun/impl/AbstractIndentationUnitProcessor.java new file mode 100644 index 0000000000..7dbe61f76a --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractIndentationUnitProcessor.java @@ -0,0 +1,41 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.IndentationUnitProcessor; + +/** + * Created by zhouping on 2015/9/20. + */ +public class AbstractIndentationUnitProcessor implements IndentationUnitProcessor { + private int indentationUnit = 1; + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + + public void setIndentationUnit(int value){ + this.indentationUnit = value; + } + + public int getIndentationUnit(){ + return indentationUnit; + } + + /** + * 处理paddingunit的值 + * @param value 输入 + * @return 输出 + */ + public int paddingUnitProcessor(int value){ + return value; + } + + /** + * 处理从spinner处获得的值 + * @param value 输入值 + * @return 输出 + */ + public int paddingUnitGainFromSpinner(int value){ + return value; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java new file mode 100644 index 0000000000..8074cdcc93 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractJavaScriptActionProvider.java @@ -0,0 +1,14 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.JavaScriptActionProvider; + +/** + * Created by zack on 2015/8/20. + */ +public abstract class AbstractJavaScriptActionProvider implements JavaScriptActionProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractMenuHandler.java b/designer_base/src/com/fr/design/fun/impl/AbstractMenuHandler.java new file mode 100644 index 0000000000..db911f5010 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractMenuHandler.java @@ -0,0 +1,63 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.MenuHandler; +import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; +import com.fr.design.menu.ShortCut; +import com.fr.general.ComparatorUtils; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractMenuHandler implements MenuHandler { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + + public boolean equals(Object obj) { + return obj instanceof AbstractMenuHandler + && ComparatorUtils.equals(category(), ((AbstractMenuHandler) obj).category()) + && shortCutEquals(this, (AbstractMenuHandler)obj); + } + + private boolean shortCutEquals(AbstractMenuHandler target, AbstractMenuHandler self){ + ShortCut targetShortCut = target.shortcut(); + ShortCut selfShortCut = self.shortcut(); + + if (targetShortCut == null && selfShortCut == null){ + return true; + } + + if (targetShortCut != null && selfShortCut != null){ + return ComparatorUtils.equals(targetShortCut.getClass(), selfShortCut.getClass()); + } + + return false; + } + + /** + * 获取当前菜单对应的Action + * 不需要选中对象, (文件, 服务器, 关于) + * + * @return 菜单Action + * + */ + public ShortCut shortcut(){ + return null; + } + + /** + * 获取当前菜单对应的Action + * + * @param plus 当前选中的对象(模板) + * + * @return 菜单Action + * + */ + public ShortCut shortcut(ToolBarMenuDockPlus plus){ + return null; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractParameterWidgetOptionProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractParameterWidgetOptionProvider.java new file mode 100644 index 0000000000..da2ce5d28b --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractParameterWidgetOptionProvider.java @@ -0,0 +1,16 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.ParameterWidgetOptionProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractParameterWidgetOptionProvider implements ParameterWidgetOptionProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractPresentKindProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractPresentKindProvider.java new file mode 100644 index 0000000000..ebe28c7095 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractPresentKindProvider.java @@ -0,0 +1,17 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.PresentKindProvider; + +/** + * @author richie + * @date 2015-05-22 + * @since 8.0 + */ +public abstract class AbstractPresentKindProvider implements PresentKindProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractPreviewProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractPreviewProvider.java new file mode 100644 index 0000000000..d5a67a451f --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractPreviewProvider.java @@ -0,0 +1,41 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.PreviewProvider; +import com.fr.design.mainframe.JTemplate; +import com.fr.general.ComparatorUtils; + +import java.util.Collections; +import java.util.Map; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractPreviewProvider implements PreviewProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + + @Override + public void onClick(JTemplate jt) { + jt.previewMenuActionPerformed(this); + } + + @Override + public Map parametersForPreview() { + return Collections.emptyMap(); + } + + public boolean equals(Object obj) { + return obj instanceof AbstractPreviewProvider + && ComparatorUtils.equals(nameForPopupItem(), ((AbstractPreviewProvider) obj).nameForPopupItem()); + } + + @Override + public int hashCode() { + return nameForPopupItem().hashCode(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractServerTableDataDefineProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractServerTableDataDefineProvider.java new file mode 100644 index 0000000000..57d1dffef6 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractServerTableDataDefineProvider.java @@ -0,0 +1,12 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.ServerTableDataDefineProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractServerTableDataDefineProvider implements ServerTableDataDefineProvider { + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractSubmitProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractSubmitProvider.java new file mode 100644 index 0000000000..451526cfa4 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractSubmitProvider.java @@ -0,0 +1,12 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.SubmitProvider; + +public abstract class AbstractSubmitProvider implements SubmitProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractTableDataDefineProvider.java b/designer_base/src/com/fr/design/fun/impl/AbstractTableDataDefineProvider.java new file mode 100644 index 0000000000..62f77abd65 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractTableDataDefineProvider.java @@ -0,0 +1,16 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.TableDataDefineProvider; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractTableDataDefineProvider implements TableDataDefineProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractTitleProcessor.java b/designer_base/src/com/fr/design/fun/impl/AbstractTitleProcessor.java new file mode 100644 index 0000000000..455c7dc78f --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractTitleProcessor.java @@ -0,0 +1,12 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.TitlePlaceProcessor; + +public abstract class AbstractTitleProcessor implements TitlePlaceProcessor { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractToolbarItem.java b/designer_base/src/com/fr/design/fun/impl/AbstractToolbarItem.java new file mode 100644 index 0000000000..e60d35d3ba --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractToolbarItem.java @@ -0,0 +1,14 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.ToolbarItemProvider; + +/** + * Created by richie on 15/12/1. + */ +public abstract class AbstractToolbarItem implements ToolbarItemProvider { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/fun/impl/AbstractUIFormulaProcessor.java b/designer_base/src/com/fr/design/fun/impl/AbstractUIFormulaProcessor.java new file mode 100644 index 0000000000..ce58a1a7f5 --- /dev/null +++ b/designer_base/src/com/fr/design/fun/impl/AbstractUIFormulaProcessor.java @@ -0,0 +1,16 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.UIFormulaProcessor; + +/** + * @author richie + * @date 2015-05-13 + * @since 8.0 + */ +public abstract class AbstractUIFormulaProcessor implements UIFormulaProcessor { + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/UIDefaultTheme.java b/designer_base/src/com/fr/design/gui/UIDefaultTheme.java new file mode 100644 index 0000000000..7c39fd8bf4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/UIDefaultTheme.java @@ -0,0 +1,199 @@ +package com.fr.design.gui; + + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.border.LineBorder; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.InsetsUIResource; +import javax.swing.plaf.metal.DefaultMetalTheme; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-31 + * Time: 下午2:14 + */ +public class UIDefaultTheme extends DefaultMetalTheme { + + + /** + * Secondary Color 1, used for the following: + * Dark border for flush 3D style. + */ + private static final ColorUIResource SECONDARY_1 = new ColorUIResource(167, 165, 163); + + /** + * Secondary Color 2, used for the following: + * Inactive internal window borders; dimmed button borders. + * Shadows; highlighting of toolbar buttons upon mouse button down. + * Dimmed text (for example, inactive menu items or labels). + */ + private static final ColorUIResource SECONDARY_2 = new ColorUIResource(167, 165, 163); + + /** + * 增加一些自定义的值到默认表中 + * + * @param table 默认表 + */ + public void addCustomEntriesToTable(UIDefaults table) { + super.addCustomEntriesToTable(table); + putMargin(table); + putTextConnection(table); + putToolTip(table); + putDisable(table); + putTreeAndList(table); + putOthers(table); + table.put("Desktop.background", new ColorUIResource(212, 210, 194)); + table.put("Separator.background", new ColorUIResource(173, 170, 153)); + table.put("Separator.foreground", new ColorUIResource(236, 233, 216)); + table.put("TitledBorder.border", new LineBorder( + new ColorUIResource(165, 163, 151))); + table.put("Panel.background", ThemeUtils.BACK_COLOR); + } + + public FontUIResource getMenuTextFont() { + return ThemeUtils.PLAIN_FONT; + } + + + private void putMargin(UIDefaults table) { + table.put("Button.margin", new InsetsUIResource(2, 12, 2, 12)); + table.put("CheckBox.margin", new InsetsUIResource(2, 2, 2, 2)); + table.put("RadioButton.margin", new InsetsUIResource(2, 2, 2, 2)); + } + + protected ColorUIResource getSecondary3() { + return ThemeUtils.BACK_COLOR; + } + + private void putOthers(UIDefaults table) { + table.put("Button.background", new ColorUIResource(231, 232, 245)); + table.put("Table.background", ThemeUtils.TEXT_BG_COLOR); + table.put("Table.selectionForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("Table.selectionBackground", new ColorUIResource(200, 221, 233)); + table.put("Table.gridColor", new ColorUIResource(200, 221, 233)); + table.put("TableHeader.background", new ColorUIResource(229, 229, 229)); + table.put("ProgressBar.foreground", ThemeUtils.PROCESS_COLOR); + table.put("ProgressBar.background", ThemeUtils.TEXT_BG_COLOR); + table.put("ProgressBar.selectionForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("ProgressBar.selectionBackground", ThemeUtils.NORMAL_FOREGROUND); + table.put("PopupMenu.background", ThemeUtils.NORMAL_BG); + table.put("TabbedPane.background", ThemeUtils.TEXT_BG_COLOR); + table.put("TabbedPane.background", ThemeUtils.NORMAL_BG); + table.put("TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 0)); + table.put("TabbedPane.tabInsets", new InsetsUIResource(1, 6, 4, 6)); + table.put("Table.gridColor", ThemeUtils.TABLE_GRID_COLOR); + table.put("MenuBar.background", new ColorUIResource(240, 240, 240)); + table.put("Menu.foreground", ThemeUtils.MENU_ITEM_FONT_COLOR); + table.put("MenuItem.foreground", ThemeUtils.MENU_ITEM_FONT_COLOR); + table.put("ToolBar.background", new ColorUIResource(239, 237, 229)); + + table.put("EditorPane.caretForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("PasswordField.caretForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("TextArea.caretForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("TextField.caretForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("FormattedTextField.caretForeground", ThemeUtils.NORMAL_FOREGROUND); + } + + private void putTextConnection(UIDefaults table) { + table.put("List.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("List.background", ThemeUtils.TEXT_BG_COLOR); + table.put("ComboBox.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("ComboBox.background", ThemeUtils.TEXT_BG_COLOR); + table.put("ComboBox.disabledBackground", ThemeUtils.TEXT_DISABLED_BG_COLOR); + table.put("EditorPane.background", ThemeUtils.TEXT_BG_COLOR); + table.put("EditorPane.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("PasswordField.background", ThemeUtils.TEXT_BG_COLOR); + table.put("PasswordField.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("PasswordField.inactiveBackground", ThemeUtils.TEXT_DISABLED_BG_COLOR); + table.put("TextArea.background", ThemeUtils.TEXT_BG_COLOR); + table.put("TextArea.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("TextArea.inactiveBackground", ThemeUtils.TEXT_DISABLED_BG_COLOR); + table.put("TextField.background", ThemeUtils.TEXT_BG_COLOR); + table.put("TextField.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("TextField.inactiveBackground", ThemeUtils.TEXT_DISABLED_BG_COLOR); + table.put("FormattedTextField.background", ThemeUtils.TEXT_BG_COLOR); + table.put("FormattedTextField.foreground", ThemeUtils.NORMAL_FOREGROUND); + table.put("FormattedTextField.inactiveBackground", ThemeUtils.TEXT_DISABLED_BG_COLOR); + table.put("TextPane.background", ThemeUtils.TEXT_BG_COLOR); + table.put("EditorPane.background", ThemeUtils.TEXT_BG_COLOR); + table.put("OptionPane.messageForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("ComboBox.selectionBackground", new ColorUIResource(43, 107, 197)); + table.put("ComboBox.selectionForeground", ThemeUtils.TEXT_BG_COLOR); + table.put("ComboBox.focusBackground", new ColorUIResource(43, 107, 197)); + table.put("PasswordField.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("PasswordField.selectionForeground", ThemeUtils.TEXT_SELECTED_TEXT_COLOR); + table.put("TextField.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("TextField.selectionForeground", ThemeUtils.TEXT_SELECTED_TEXT_COLOR); + table.put("FormattedTextField.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("FormattedTextField.selectionForeground", ThemeUtils.TEXT_SELECTED_TEXT_COLOR); + table.put("TextArea.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("TextArea.selectionForeground", ThemeUtils.TEXT_SELECTED_TEXT_COLOR); + table.put("TextPane.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("TextPane.selectionForeground", ThemeUtils.TEXT_SELECTED_TEXT_COLOR); + table.put("MenuItem.acceleratorForeground", ThemeUtils.NORMAL_FOREGROUND); + } + + private void putToolTip(UIDefaults table) { + table.put("ToolTip.background", new ColorUIResource(255, 255, 255)); + table.put("ToolTip.backgroundInactive", new ColorUIResource(236, 233, 216)); + table.put("ToolTip.foreground", new ColorUIResource(0, 0, 0)); + table.put("ToolTip.foregroundInactive", new ColorUIResource(143, 141, 139)); + } + + private void putDisable(UIDefaults table) { + + table.put("Button.disabledText", ThemeUtils.DISABLE_TEXT); + table.put("CheckBox.disabledText", ThemeUtils.DISABLE_TEXT); + table.put("RadioButton.disabledText", ThemeUtils.DISABLE_TEXT); + table.put("ToggleButton.disabledText", ThemeUtils.DISABLE_TEXT); + table.put("ToggleButton.disabledSelectedText", ThemeUtils.DISABLE_TEXT); + table.put("TextArea.inactiveForeground", ThemeUtils.DISABLE_TEXT); + table.put("TextField.inactiveForeground", ThemeUtils.DISABLE_TEXT); + table.put("FormattedTextField.inactiveForeground", ThemeUtils.DISABLE_TEXT); + table.put("TextPane.inactiveForeground", ThemeUtils.DISABLE_TEXT); + table.put("PasswordField.inactiveForeground", ThemeUtils.DISABLE_TEXT); + table.put("ComboBox.disabledForeground", ThemeUtils.DISABLE_TEXT); + table.put("Label.disabledForeground", ThemeUtils.DISABLE_TEXT); + table.put("textInactiveText", ThemeUtils.DISABLE_TEXT); + } + + private void putTreeAndList(UIDefaults table) { + table.put("List.selectionForeground", new ColorUIResource(255, 255, 255)); + table.put("List.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("Tree.background", ThemeUtils.TEXT_BG_COLOR); + table.put("Tree.textBackground", ThemeUtils.TEXT_BG_COLOR); + table.put("Tree.textForeground", ThemeUtils.NORMAL_FOREGROUND); + table.put("Tree.selectionBackground", ThemeUtils.TEXT_SELECTED_BG_COLOR); + table.put("Tree.selectionForeground", ThemeUtils.TEXT_SELECTED_TEXT_COLOR); + table.put("Tree.hash", new ColorUIResource(208, 205, 190)); + table.put("Tree.line", new ColorUIResource(208, 205, 190)); + } + + + /** + * Gets the first secondary color. + * + * @return The first secondary color. See field declaration for more details. + */ + protected ColorUIResource getSecondary1() { + return SECONDARY_1; + } + + /** + * Gets the second secondary color. + * + * @return The second secondary color. See field declaration for more details. + */ + protected ColorUIResource getSecondary2() { + return SECONDARY_2; + } + + public ColorUIResource getMenuSelectedBackground() { + return new ColorUIResource(200, 200, 255); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/UILookAndFeel.java b/designer_base/src/com/fr/design/gui/UILookAndFeel.java new file mode 100644 index 0000000000..3bdf14d31f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/UILookAndFeel.java @@ -0,0 +1,203 @@ +package com.fr.design.gui; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.borders.*; +import com.fr.design.gui.frpane.UIBasicOptionPaneUI; +import com.fr.design.gui.ibutton.UIButtonBorder; +import com.fr.design.gui.ibutton.UIRadioButtonMenuItemUI; +import com.fr.design.gui.ibutton.UIRadioButtonUI; +import com.fr.design.gui.icheckbox.UICheckBoxUI; +import com.fr.design.gui.icontainer.UIScrollPaneBorder; +import com.fr.design.gui.icontainer.UIScrollPaneUI; +import com.fr.design.gui.icontainer.UITableScrollPaneBorder; +import com.fr.design.gui.imenu.UIBasicMenuItemUI; +import com.fr.design.gui.imenu.UIBasicMenuUI; +import com.fr.design.gui.imenu.UIPopupMenuBorder; +import com.fr.design.gui.imenu.UIPopupMenuSeparatorUI; +import com.fr.design.gui.iprogressbar.UIProgressBarBorder; +import com.fr.design.gui.iprogressbar.UIProgressBarUI; +import com.fr.design.gui.ispinner.UISpinnerUI; +import com.fr.design.gui.isplitpanedivider.UISplitPaneUI; +import com.fr.design.gui.itable.UIBasicTableUI; +import com.fr.design.gui.itoolbar.UIToolBarBorder; +import com.fr.design.gui.itoolbar.UIToolBarSeparatorUI; +import com.fr.design.gui.itooltip.UIToolTipBorder; +import com.fr.design.gui.itree.UITreeUI; +import com.fr.design.gui.iscrollbar.UIBasicScrollBarUI; +import com.fr.design.gui.icombobox.UIBasicComboBoxUI; +import com.fr.design.gui.ibutton.UIBasicButtonUI; +import com.fr.general.FRLogger; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.basic.BasicBorders; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.awt.*; +import java.net.URL; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-31 + * Time: 上午9:38 + */ +public class UILookAndFeel extends MetalLookAndFeel { + + public static boolean CONTROL_PANEL_INSTANTIATED = false; + + + protected void createDefaultTheme() { + setCurrentTheme(new UIDefaultTheme()); + } + + + /** + * Initializes the uiClassID to BasicComponentUI mapping. + * The JComponent classes define their own uiClassID constants. This table + * must map those constants to a BasicComponentUI class of the appropriate + * type. + * + * @param table The ui defaults table. + */ + protected void initClassDefaults(UIDefaults table) { + super.initClassDefaults(table); + + table.putDefaults(new Object[]{ + "TreeUI", UITreeUI.class.getName(), + "PopupMenuSeparatorUI", UIPopupMenuSeparatorUI.class.getName(), + "SplitPaneUI", UISplitPaneUI.class.getName(), + "SpinnerUI", UISpinnerUI.class.getName(), + "ScrollPaneUI", UIScrollPaneUI.class.getName(), + "RadioButtonUI", UIRadioButtonUI.class.getName(), + "CheckBoxUI", UICheckBoxUI.class.getName(), + "ToolBarSeparatorUI", UIToolBarSeparatorUI.class.getName(), + "ScrollBarUI", UIBasicScrollBarUI.class.getName(), + "ComboBoxUI", UIBasicComboBoxUI.class.getName(), + "ButtonUI", UIBasicButtonUI.class.getName(), + "ToggleButtonUI", UIBasicButtonUI.class.getName(), + "TableUI", UIBasicTableUI.class.getName(), + "ProgressBarUI", UIProgressBarUI.class.getName(), + "MenuUI", UIBasicMenuUI.class.getName(), + "MenuItemUI", UIBasicMenuItemUI.class.getName(), + "RadioButtonMenuItemUI", UIRadioButtonMenuItemUI.class.getName(), + "OptionPaneUI",UIBasicOptionPaneUI.class.getName(), + }); + } + + + /** + * Initializes the default values for many ui widgets and puts them in the + * given ui defaults table. T + * Here is the place where borders can be changed. + * + * @param table The ui defaults table. + */ + protected void initComponentDefaults(UIDefaults table) { + super.initComponentDefaults(table); + table.put("Button.border", + new BorderUIResource.CompoundBorderUIResource( + new UIButtonBorder(), + new BasicBorders.MarginBorder())); + Border border = new EmptyBorder(2, 4, 2, 4); + table.put("Menu.border", border); + table.put("CheckBoxMenuItem.border", border); + table.put("MenuItem.border", border); + table.put("RadioButtonMenuItem.border", border); + table.put("ToolTip.border", new BorderUIResource(new UIToolTipBorder(true))); + table.put("ToolTip.borderInactive", new BorderUIResource(new UIToolTipBorder(false))); + table.put("Tree.expandedIcon", BaseUtils.readIcon("/com/fr/design/images/tree/open.png")); + table.put("Tree.collapsedIcon", BaseUtils.readIcon("/com/fr/design/images/tree/close.png")); + table.put("PopupMenu.border", new UIPopupMenuBorder()); + table.put("PopupMenu.foreground", new ColorUIResource(255, 0, 0)); + table.put("SplitPane.dividerSize", new Integer(7)); + table.put("ToolBar.border", new UIToolBarBorder()); + table.put("Table.scrollPaneBorder", new UITableScrollPaneBorder()); + + border = new UIInternalFrameBorder(); + table.put("InternalFrame.border", border); + table.put("InternalFrame.paletteBorder", border); + table.put("InternalFrame.optionDialogBorder", border); + table.put("Table.scrollPaneBorder", new UITableScrollPaneBorder()); + + + table.put("TabbedPane.tabInsets", new Insets(1, 6, 4, 6)); + table.put("TabbedPane.selectedTabPadInsets", new Insets(2, 2, 1, 2)); + table.put("TabbedPane.unselected", new ColorUIResource(0, 0, 0)); + table.put("TabbedPane.tabAreaInsets", new Insets(6, 2, 0, 0)); + table.put("TabbedPane.contentBorderInsets", new Insets(1, 1, 3, 3)); + initOtherComponents(table); + + } + + private void initOtherComponents(UIDefaults table) { + table.put("RootPane.colorChooserDialogBorder", UIFrameBorder.getInstance()); + table.put("RootPane.errorDialogBorder", UIFrameBorder.getInstance()); + table.put("RootPane.fileChooserDialogBorder", UIFrameBorder.getInstance()); + table.put("RootPane.frameBorder", UIFrameBorder.getInstance()); + table.put("RootPane.informationDialogBorder", UIFrameBorder.getInstance()); + table.put("RootPane.plainDialogBorder", UIFrameBorder.getInstance()); + table.put("RootPane.questionDialogBorder", UIFrameBorder.getInstance()); + table.put("RootPane.warningDialogBorder", UIFrameBorder.getInstance()); + table.put("TableHeader.cellBorder", new UITableHeaderBorder()); + table.put("TableHeader.cellRolloverBorder", new UITableHeaderRolloverBorder()); + + table.put("Tree.expandedIcon", loadIcon("TreeMinusIcon.png", this)); + table.put("Tree.collapsedIcon", loadIcon("TreePlusIcon.png", this)); + table.put("Tree.openIcon", loadIcon("TreeFolderOpenedIcon.png", this)); + table.put("Tree.closedIcon", loadIcon("TreeFolderClosedIcon.png", this)); + table.put("Tree.leafIcon", loadIcon("TreeLeafIcon.png", this)); + table.put("FileView.directoryIcon", loadIcon("DirectoryIcon.png", this)); + table.put("FileView.computerIcon", loadIcon("ComputerIcon.png", this)); + table.put("FileView.fileIcon", loadIcon("FileIcon.png", this)); + table.put("FileView.floppyDriveIcon", loadIcon("FloppyIcon.png", this)); + table.put("FileView.hardDriveIcon", loadIcon("HarddiskIcon.png", this)); + table.put("FileChooser.detailsViewIcon", loadIcon("FileDetailsIcon.png", this)); + table.put("FileChooser.homeFolderIcon", loadIcon("HomeFolderIcon.png", this)); + table.put("FileChooser.listViewIcon", loadIcon("FileListIcon.png", this)); + table.put("FileChooser.newFolderIcon", loadIcon("NewFolderIcon.png", this)); + table.put("FileChooser.upFolderIcon", loadIcon("ParentDirectoryIcon.png", this)); + table.put("OptionPane.errorIcon", loadIcon("ErrorIcon.png", this)); + table.put("OptionPane.informationIcon", loadIcon("InformationIcon.png", this)); + table.put("OptionPane.warningIcon", loadIcon("WarningIcon.png", this)); + table.put("OptionPane.questionIcon", loadIcon("QuestionIcon.png", this)); + table.put("ScrollPane.border", new UIScrollPaneBorder()); + table.put("ProgressBar.border", new UIProgressBarBorder()); + table.put("Spinner.border", new UITextFieldBorder(new Insets(2, 2, 2, 2))); + table.put("FormattedTextField.border", new UITextFieldBorder()); + table.put("TextField.border", new UITextFieldBorder()); + table.put("PasswordField.border", new UITextFieldBorder()); + } + + + /** + * 加载图片 + * + * @param fileName 文件名 + * @param invoker 参数 + * @return 加载的图片 + */ + public static ImageIcon loadIcon(final String fileName, final Object invoker) { + // This should work for both applications and applets + URL url = Thread.currentThread().getContextClassLoader().getResource( + "com/fr/design/images/lookandfeel/" + fileName); + + if (url == null) { + // Another try + url = UILookAndFeel.class.getResource( + "com/fr/design/images/lookandfeel/" + fileName); + + if (url == null) { + FRLogger.getLogger().error("Icon directory could not be resolved."); + return null; + } + } + + return new ImageIcon(url); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletion.java new file mode 100644 index 0000000000..50661c16ca --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletion.java @@ -0,0 +1,153 @@ +/* + * 12/21/2008 + * + * AbstractCompletion.java - Base class for possible completions. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import javax.swing.Icon; +import javax.swing.text.JTextComponent; + + +/** + * Base class for possible completions. Most, if not all, {@link Completion} + * implementations can extend this class. It remembers the + * CompletionProvider that returns this completion, and also implements + * Comparable, allowing such completions to be compared + * lexicographically (ignoring case).

+ * + * This implementation assumes the input text and replacement text are the + * same value. It also returns the input text from its {@link #toString()} + * method (which is what DefaultListCellRenderer uses to render + * objects). Subclasses that wish to override any of this behavior can simply + * override the corresponding method(s) needed to do so. + * + * @author Robert Futrell + * @version 1.0 + */ +public abstract class AbstractCompletion implements Completion { + + /** + * The provider that created this completion; + */ + private CompletionProvider provider; + + /** + * The relevance of this completion. Completion instances with higher + * "relevance" values are inserted higher into the list of possible + * completions than those with lower values. Completion instances with + * equal relevance values are sorted alphabetically. + */ + private int relevance; + + + /** + * Constructor. + * + * @param provider The provider that created this completion. + */ + public AbstractCompletion(CompletionProvider provider) { + this.provider = provider; + } + + + /** + * {@inheritDoc} + */ + public int compareTo(Completion c2) { + if (c2==this) { + return 0; + } + else if (c2!=null) { + return toString().compareToIgnoreCase(c2.toString()); + } + return -1; + } + + + /** + * {@inheritDoc} + */ + public String getAlreadyEntered(JTextComponent comp) { + return provider.getAlreadyEnteredText(comp); + } + + + /** + * The default implementation returns null. Subclasses + * who wish to display an icon can override this method. + * + * @return The icon for this completion. + */ + public Icon getIcon() { + return null; + } + + + /** + * Returns the text the user has to (start) typing for this completion + * to be offered. The default implementation simply returns + * {@link #getReplacementText()}. + * + * @return The text the user has to (start) typing for this completion. + * @see #getReplacementText() + */ + public String getInputText() { + return getReplacementText(); + } + + + /** + * {@inheritDoc} + */ + public CompletionProvider getProvider() { + return provider; + } + + + /** + * {@inheritDoc} + */ + public int getRelevance() { + return relevance; + } + + + /** + * The default implementation returns null. Subclasses + * can override this method. + * + * @return The tool tip text. + */ + public String getToolTipText() { + return null; + } + + + /** + * Sets the relevance of this completion. + * + * @param relevance The new relevance of this completion. + * @see #getRelevance() + */ + public void setRelevance(int relevance) { + this.relevance = relevance; + } + + + /** + * Returns a string representation of this completion. The default + * implementation returns {@link #getInputText()}. + * + * @return A string representation of this completion. + */ + @Override + public String toString() { + return getInputText(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java b/designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java new file mode 100644 index 0000000000..47a72643f5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/AbstractCompletionProvider.java @@ -0,0 +1,245 @@ +/* + * 12/21/2008 + * + * AbstractCompletionProvider.java - Base class for completion providers. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.swing.text.JTextComponent; + + +/** + * A base class for completion providers. {@link Completion}s are kept in + * a sorted list. To get the list of completions that match a given input, + * a binary search is done to find the first matching completion, then all + * succeeding completions that also match are also returned. + * + * @author Robert Futrell + * @version 1.0 + */ +public abstract class AbstractCompletionProvider + extends CompletionProviderBase { + + /** + * The completions this provider is aware of. Subclasses should ensure + * that this list is sorted alphabetically (case-insensitively). + */ + protected List completions; + + /** + * Compares a {@link Completion} against a String. + */ + protected CaseInsensitiveComparator comparator; + + + /** + * Constructor. + */ + public AbstractCompletionProvider() { + comparator = new CaseInsensitiveComparator(); + clearParameterizedCompletionParams(); + } + + + /** + * Adds a single completion to this provider. If you are adding multiple + * completions to this provider, for efficiency reasons please consider + * using {@link #addCompletions(List)} instead. + * + * @param c The completion to add. + * @throws IllegalArgumentException If the completion's provider isn't + * this CompletionProvider. + * @see #addCompletions(List) + * @see #removeCompletion(Completion) + * @see #clear() + */ + public void addCompletion(Completion c) { + checkProviderAndAdd(c); + Collections.sort(completions); + } + + + /** + * Adds {@link Completion}s to this provider. + * + * @param completions The completions to add. This cannot be + * null. + * @throws IllegalArgumentException If a completion's provider isn't + * this CompletionProvider. + * @see #addCompletion(Completion) + * @see #removeCompletion(Completion) + * @see #clear() + */ + public void addCompletions(List completions) { + //this.completions.addAll(completions); + for (Completion c : completions) { + checkProviderAndAdd(c); + } + Collections.sort(this.completions); + } + + + /** + * Adds simple completions for a list of words. + * + * @param words The words. + * @see BasicCompletion + */ + protected void addWordCompletions(String[] words) { + int count = words==null ? 0 : words.length; + for (int i=0; iCompletionProvider, if there is one. + * + * @see #addCompletion(Completion) + * @see #addCompletions(List) + * @see #removeCompletion(Completion) + */ + public void clear() { + completions.clear(); + } + + + /** + * Returns a list of Completions in this provider with the + * specified input text. + * + * @param inputText The input text to search for. + * @return A list of {@link Completion}s, or null if there + * are no matching Completions. + */ + @SuppressWarnings("unchecked") + public List getCompletionByInputText(String inputText) { + + // Find any entry that matches this input text (there may be > 1). + int end = Collections.binarySearch(completions, inputText, comparator); + if (end<0) { + return null; + } + + // There might be multiple entries with the same input text. + int start = end; + while (start>0 && + comparator.compare(completions.get(start-1), inputText)==0) { + start--; + } + int count = completions.size(); + while (++end getCompletionsImpl(JTextComponent comp) { + + List retVal = new ArrayList(); + String text = getAlreadyEnteredText(comp); + + if (text!=null) { + + int index = Collections.binarySearch(completions, text, comparator); + if (index<0) { // No exact match + index = -index - 1; + } + else { + // If there are several overloads for the function being + // completed, Collections.binarySearch() will return the index + // of one of those overloads, but we must return all of them, + // so search backward until we find the first one. + int pos = index - 1; + while (pos>0 && + comparator.compare(completions.get(pos), text)==0) { + retVal.add(completions.get(pos)); + pos--; + } + } + + while (indextrue if this provider contained the specified + * completion. + * @see #clear() + * @see #addCompletion(Completion) + * @see #addCompletions(List) + */ + public boolean removeCompletion(Completion c) { + // Don't just call completions.remove(c) as it'll be a linear search. + int index = Collections.binarySearch(completions, c); + if (index<0) { + return false; + } + completions.remove(index); + return true; + } + + + /** + * A comparator that compares the input text of a {@link Completion} + * against a String lexicographically, ignoring case. + */ + @SuppressWarnings("rawtypes") + protected static class CaseInsensitiveComparator implements Comparator, + Serializable { + + public int compare(Object o1, Object o2) { + Completion c = (Completion)o1; + // o2.toString() needed to help compile with 1.5+. + return String.CASE_INSENSITIVE_ORDER.compare( + c.getInputText(), o2.toString()); + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDemo.java b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDemo.java new file mode 100644 index 0000000000..7dba1690ff --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDemo.java @@ -0,0 +1,142 @@ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; +import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; + +import javax.swing.*; +import java.awt.*; + +/** + * An example showing a simple usage of the AutoComplete package to add support + * for auto-completion of keywords and other things.

+ *

+ * This example uses RSyntaxTextArea 2.0.1.

+ *

+ * Project Home: http://fifesoft.com/rsyntaxtextarea
+ * Downloads: https://sourceforge.net/projects/rsyntaxtextarea + */ +public class AutoCompleteDemo extends JFrame { + + private static final long serialVersionUID = 1L; + + public AutoCompleteDemo() { + + JPanel contentPane = new JPanel(new BorderLayout()); + RSyntaxTextArea textArea = new RSyntaxTextArea(20, 60); + textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + textArea.setCodeFoldingEnabled(true); + textArea.setAntiAliasingEnabled(true); + contentPane.add(new RTextScrollPane(textArea)); + + // A CompletionProvider is what knows of all possible completions, and + // analyzes the contents of the text area at the caret position to + // determine what completion choices should be presented. Most + // instances of CompletionProvider (such as DefaultCompletionProvider) + // are designed so that they can be shared among multiple text + // components. + CompletionProvider provider = createCompletionProvider(); + + // An AutoCompletion acts as a "middle-man" between a text component + // and a CompletionProvider. It manages any options associated with + // the auto-completion (the popup trigger key, whether to display a + // documentation window along with completion choices, etc.). Unlike + // CompletionProviders, instances of AutoCompletion cannot be shared + // among multiple text components. + AutoCompletion ac = new AutoCompletion(provider); + //ac.setTriggerKey(KeyStroke.getKeyStroke(KeyEvent.VK_SLASH, InputEvent.ALT_DOWN_MASK)); + ac.install(textArea); + + setContentPane(contentPane); + setTitle("AutoComplete Demo"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + pack(); + setLocationRelativeTo(null); + + } + + /** + * Create a simple provider that adds some Java-related completions. + * + * @return The completion provider. + */ + private CompletionProvider createCompletionProvider() { + + // A DefaultCompletionProvider is the simplest concrete implementation + // of CompletionProvider. This provider has no understanding of + // language semantics. It simply checks the text entered up to the + // caret position for a match against known completions. This is all + // that is needed in the majority of cases. + DefaultCompletionProvider provider = new DefaultCompletionProvider(); + + // Add completions for all Java keywords. A BasicCompletion is just + // a straightforward word completion. + provider.addCompletion(new BasicCompletion(provider, "abstract")); + provider.addCompletion(new BasicCompletion(provider, "assert")); + provider.addCompletion(new BasicCompletion(provider, "break")); + provider.addCompletion(new BasicCompletion(provider, "case")); + provider.addCompletion(new BasicCompletion(provider, "catch")); + provider.addCompletion(new BasicCompletion(provider, "class")); + provider.addCompletion(new BasicCompletion(provider, "const")); + provider.addCompletion(new BasicCompletion(provider, "continue")); + provider.addCompletion(new BasicCompletion(provider, "default")); + provider.addCompletion(new BasicCompletion(provider, "do")); + provider.addCompletion(new BasicCompletion(provider, "else")); + provider.addCompletion(new BasicCompletion(provider, "enum")); + provider.addCompletion(new BasicCompletion(provider, "extends")); + provider.addCompletion(new BasicCompletion(provider, "final")); + provider.addCompletion(new BasicCompletion(provider, "finally")); + provider.addCompletion(new BasicCompletion(provider, "for")); + provider.addCompletion(new BasicCompletion(provider, "goto")); + provider.addCompletion(new BasicCompletion(provider, "if")); + provider.addCompletion(new BasicCompletion(provider, "implements")); + provider.addCompletion(new BasicCompletion(provider, "import")); + provider.addCompletion(new BasicCompletion(provider, "instanceof")); + provider.addCompletion(new BasicCompletion(provider, "interface")); + provider.addCompletion(new BasicCompletion(provider, "native")); + provider.addCompletion(new BasicCompletion(provider, "new")); + provider.addCompletion(new BasicCompletion(provider, "package")); + provider.addCompletion(new BasicCompletion(provider, "private")); + provider.addCompletion(new BasicCompletion(provider, "protected")); + provider.addCompletion(new BasicCompletion(provider, "public")); + provider.addCompletion(new BasicCompletion(provider, "return")); + provider.addCompletion(new BasicCompletion(provider, "static")); + provider.addCompletion(new BasicCompletion(provider, "strictfp")); + provider.addCompletion(new BasicCompletion(provider, "super")); + provider.addCompletion(new BasicCompletion(provider, "switch")); + provider.addCompletion(new BasicCompletion(provider, "synchronized")); + provider.addCompletion(new BasicCompletion(provider, "this")); + provider.addCompletion(new BasicCompletion(provider, "throw")); + provider.addCompletion(new BasicCompletion(provider, "throws")); + provider.addCompletion(new BasicCompletion(provider, "transient")); + provider.addCompletion(new BasicCompletion(provider, "try")); + provider.addCompletion(new BasicCompletion(provider, "void")); + provider.addCompletion(new BasicCompletion(provider, "volatile")); + provider.addCompletion(new BasicCompletion(provider, "while")); + + // Add a couple of "shorthand" completions. These completions don't + // require the input text to be the same thing as the replacement text. + provider.addCompletion(new ShorthandCompletion(provider, "sysout", + "System.out.println(", "System.out.println(")); + provider.addCompletion(new ShorthandCompletion(provider, "syserr", + "System.err.println(", "System.err.println(")); + + return provider; + + } + + public static void main(String[] args) { + // Instantiate GUI on the EDT. + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + String laf = UIManager.getSystemLookAndFeelClassName(); + UIManager.setLookAndFeel(laf); + } catch (Exception e) { + } + new AutoCompleteDemo().setVisible(true); + } + }); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDescWindow.java b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDescWindow.java new file mode 100644 index 0000000000..6d109d474b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompleteDescWindow.java @@ -0,0 +1,591 @@ +/* + * 12/21/2008 + * + * AutoCompleteDescWindow.java - A window containing a description of the + * currently selected completion. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.ResourceBundle; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JEditorPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JToolBar; +import javax.swing.JWindow; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; + + + +/** + * The optional "description" window that describes the currently selected + * item in the auto-completion window. + * + * @author Robert Futrell + * @version 1.0 + */ +class AutoCompleteDescWindow extends JWindow implements HyperlinkListener, + DescWindowCallback { + + /** + * The parent AutoCompletion instance. + */ + private AutoCompletion ac; + + /** + * Renders the HTML description. + */ + private JEditorPane descArea; + + /** + * The scroll pane that {@link #descArea} is in. + */ + private JScrollPane scrollPane; + + /** + * The bottom panel, containing the toolbar and size grip. + */ + private JPanel bottomPanel; + + /** + * The toolbar with "back" and "forward" buttons. + */ + private JToolBar descWindowNavBar; + + /** + * Action that goes to the previous description displayed. + */ + private Action backAction; + + /** + * Action that goes to the next description displayed. + */ + private Action forwardAction; + + /** + * History of descriptions displayed. + */ + private List history; + + /** + * The current position in {@link #history}. + */ + private int historyPos; + + /** + * Provides a slight delay between asking to set a description and actually + * displaying it, so that if the user is scrolling quickly through + * completions, those with slow-to-calculate summaries won't bog down the + * scrolling. + */ + private Timer timer; + + /** + * The action that listens for the timer to fire. + */ + private TimerAction timerAction; + + /** + * The resource bundle for this window. + */ + private ResourceBundle bundle; + + /** + * The amount of time to wait after the user changes the selected + * completion to refresh the description. This delay is in place to help + * performance for {@link Completion}s that may be slow to compute their + * summary text. + */ + private static final int INITIAL_TIMER_DELAY = 120; + + /** + * The resource bundle name. + */ + private static final String MSG = + "com.fr.design.gui.autocomplete.AutoCompleteDescWindow"; + + + /** + * Constructor. + * + * @param owner The parent window. + * @param ac The parent auto-completion. + */ + public AutoCompleteDescWindow(Window owner, AutoCompletion ac) { + + super(owner); + this.ac = ac; + + ComponentOrientation o = ac.getTextComponentOrientation(); + + JPanel cp = new JPanel(new BorderLayout()); + cp.setBorder(TipUtil.getToolTipBorder()); + + descArea = new JEditorPane("text/html", null); + TipUtil.tweakTipEditorPane(descArea); + descArea.addHyperlinkListener(this); + scrollPane = new JScrollPane(descArea); + Border b = BorderFactory.createEmptyBorder(); + scrollPane.setBorder(b); + scrollPane.setViewportBorder(b); + scrollPane.setBackground(descArea.getBackground()); + scrollPane.getViewport().setBackground(descArea.getBackground()); + cp.add(scrollPane); + + descWindowNavBar = new JToolBar(); + backAction = new ToolBarBackAction(o.isLeftToRight()); + forwardAction = new ToolBarForwardAction(o.isLeftToRight()); + descWindowNavBar.setFloatable(false); + descWindowNavBar.add(new JButton(backAction)); + descWindowNavBar.add(new JButton(forwardAction)); + + bottomPanel = new JPanel(new BorderLayout()); + b = new AbstractBorder() { + @Override + public Insets getBorderInsets(Component c) { + return new Insets(1, 0, 0, 0); + } + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + g.setColor(UIManager.getColor("controlDkShadow")); + g.drawLine(x,y, x+w-1,y); + } + }; + bottomPanel.setBorder(b); + SizeGrip rp = new SizeGrip(); + bottomPanel.add(descWindowNavBar, BorderLayout.LINE_START); + bottomPanel.add(rp, BorderLayout.LINE_END); + cp.add(bottomPanel, BorderLayout.SOUTH); + setContentPane(cp); + + applyComponentOrientation(o); + setFocusableWindowState(false); + + // Give apps a chance to decorate us with drop shadows, etc. + if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) { + PopupWindowDecorator decorator = PopupWindowDecorator.get(); + if (decorator!=null) { + decorator.decorate(this); + } + } + + history = new ArrayList(1); // Usually small + historyPos = -1; + + timerAction = new TimerAction(); + timer = new Timer(INITIAL_TIMER_DELAY, timerAction); + timer.setRepeats(false); + + } + + + /** + * Sets the currently displayed description and updates the history. + * + * @param historyItem The item to add to the history. + */ + private void addToHistory(HistoryEntry historyItem) { + history.add(++historyPos, historyItem); + clearHistoryAfterCurrentPos(); + setActionStates(); + } + + + /** + * Clears the history of viewed descriptions. + */ + private void clearHistory() { + history.clear(); // Try to free some memory. + historyPos = -1; + if (descWindowNavBar!=null) { + setActionStates(); + } + } + + + /** + * Makes the current history page the last one in the history. + */ + private void clearHistoryAfterCurrentPos() { + for (int i=history.size()-1; i>historyPos; i--) { + history.remove(i); + } + setActionStates(); + } + + + /** + * Copies from the description text area, if it is visible and there is + * a selection. + * + * @return Whether a copy occurred. + */ + public boolean copy() { + if (isVisible() && + descArea.getSelectionStart()!=descArea.getSelectionEnd()) { + descArea.copy(); + return true; + } + return false; + } + + + /** + * Returns the localized message for the specified key. + * + * @param key The key. + * @return The localized message. + */ + private String getString(String key) { + if (bundle==null) { + bundle = ResourceBundle.getBundle(MSG); + } + return bundle.getString(key); + } + + + /** + * Called when a hyperlink is clicked. + * + * @param e The event. + */ + public void hyperlinkUpdate(HyperlinkEvent e) { + + HyperlinkEvent.EventType type = e.getEventType(); + if (!type.equals(HyperlinkEvent.EventType.ACTIVATED)) { + return; + } + + // Users can redirect URL's, perhaps to a local copy of documentation. + URL url = e.getURL(); + if (url!=null) { + LinkRedirector redirector = AutoCompletion.getLinkRedirector(); + if (redirector!=null) { + URL newUrl = redirector.possiblyRedirect(url); + if (newUrl!=null && newUrl!=url) { + url = newUrl; + e = new HyperlinkEvent(e.getSource(), e.getEventType(), + newUrl, e.getDescription(), e.getSourceElement()); + } + } + } + + // Custom hyperlink handler for this completion type + ExternalURLHandler handler = ac.getExternalURLHandler(); + if (handler!=null) { + HistoryEntry current = history.get(historyPos); + handler.urlClicked(e, current.completion, this); + return; + } + + // No custom handler... + if (url!=null) { + // Try loading in external browser (Java 6+ only). + try { + Util.browse(new URI(url.toString())); + } catch (/*IO*/URISyntaxException ioe) { + UIManager.getLookAndFeel().provideErrorFeedback(descArea); + } + } + else { // Assume simple function name text, like in c.xml + // FIXME: This is really a hack, and we assume we can find the + // linked-to item in the same CompletionProvider. + AutoCompletePopupWindow parent = + (AutoCompletePopupWindow)getParent(); + CompletionProvider p = parent.getSelection().getProvider(); + if (p instanceof AbstractCompletionProvider) { + String name = e.getDescription(); + List l = ((AbstractCompletionProvider)p). + getCompletionByInputText(name); + if (l!=null && !l.isEmpty()) { + // Just use the 1st one if there's more than 1 + Completion c = l.get(0); + setDescriptionFor(c, true); + } + else { + UIManager.getLookAndFeel().provideErrorFeedback(descArea); + } + } + } + + } + + + /** + * Enables or disables the back and forward actions as appropriate. + */ + private void setActionStates() { + // TODO: Localize this text! + String desc = null; + if (historyPos>0) { + backAction.setEnabled(true); + desc = "Back to " + history.get(historyPos-1); + } + else { + backAction.setEnabled(false); + } + backAction.putValue(Action.SHORT_DESCRIPTION, desc); + if (historyPos>-1 && historyPosnull if none. + * @param addToHistory Whether to add this page to the page history + * (as opposed to clearing it and starting anew). + */ + protected void setDescriptionFor(Completion item, String anchor, + boolean addToHistory) { + timer.stop(); + timerAction.setCompletion(item, anchor, addToHistory); + timer.start(); + } + + + private void setDisplayedDesc(Completion completion, final String anchor, + boolean addToHistory) { + + String desc = completion==null ? null : completion.getSummary(); + if (desc==null) { + desc = "" + getString("NoDescAvailable") + ""; + } + descArea.setText(desc); + if (anchor!=null) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + descArea.scrollToReference(anchor); + } + }); + } + else { + descArea.setCaretPosition(0); // In case of scrolling + } + + if (!addToHistory) { + // Remove everything first if this is going to be the only + // thing in history. + clearHistory(); + } + addToHistory(new HistoryEntry(completion, desc, null)); + + } + + + /** + * {@inheritDoc} + */ + @Override + public void setVisible(boolean visible) { + if (!visible) { + clearHistory(); + } + super.setVisible(visible); + } + + + /** + * Callback for custom ExternalURLHandlers. + * + * @param completion The completion to display. + * @param anchor The anchor in the HTML to jump to, or null + * if none. + */ + public void showSummaryFor(Completion completion, String anchor) { + setDescriptionFor(completion, anchor, true); + } + + + /** + * Called by the parent completion popup window the LookAndFeel is updated. + */ + public void updateUI() { + SwingUtilities.updateComponentTreeUI(this); + // Update editor pane for new font, bg, selection colors, etc. + TipUtil.tweakTipEditorPane(descArea); + scrollPane.setBackground(descArea.getBackground()); + scrollPane.getViewport().setBackground(descArea.getBackground()); + ((JPanel)getContentPane()).setBorder(TipUtil.getToolTipBorder()); + } + + + /** + * A completion and its cached summary text. + */ + private static class HistoryEntry { + + public Completion completion; + public String summary; + public String anchor; + + public HistoryEntry(Completion completion, String summary, + String anchor) { + this.completion = completion; + this.summary = summary; + this.anchor = anchor; + } + + /** + * Overridden to display a short name for the completion, since it's + * used in the tool tips for the "back" and "forward" buttons. + * + * @return A string representation of this history entry. + */ + @Override + public String toString() { + return completion.getInputText(); + } + + } + + + /** + * Action that actually updates the summary text displayed. + */ + private class TimerAction extends AbstractAction { + + private Completion completion; + private String anchor; + private boolean addToHistory; + + /** + * Called when the timer is fired. + */ + public void actionPerformed(ActionEvent e) { + setDisplayedDesc(completion, anchor, addToHistory); + } + + public void setCompletion(Completion c, String anchor, + boolean addToHistory) { + this.completion = c; + this.anchor = anchor; + this.addToHistory = addToHistory; + } + + } + + + /** + * Action that moves to the previous description displayed. + */ + class ToolBarBackAction extends AbstractAction { + + public ToolBarBackAction(boolean ltr) { + String img = "org/fife/ui/autocomplete/arrow_" + + (ltr ? "left.png" : "right.png"); + ClassLoader cl = getClass().getClassLoader(); + Icon icon = new ImageIcon(cl.getResource(img)); + putValue(Action.SMALL_ICON, icon); + } + + public void actionPerformed(ActionEvent e) { + if (historyPos>0) { + HistoryEntry pair = history.get(--historyPos); + descArea.setText(pair.summary); + if (pair.anchor!=null) { + //System.out.println("Scrolling to: " + pair.anchor); + descArea.scrollToReference(pair.anchor); + } + else { + descArea.setCaretPosition(0); + } + setActionStates(); + } + } + + } + + + /** + * Action that moves to the previous description displayed. + */ + class ToolBarForwardAction extends AbstractAction { + + public ToolBarForwardAction(boolean ltr) { + String img = "org/fife/ui/autocomplete/arrow_" + + (ltr ? "right.png" : "left.png"); + ClassLoader cl = getClass().getClassLoader(); + Icon icon = new ImageIcon(cl.getResource(img)); + putValue(Action.SMALL_ICON, icon); + } + + public void actionPerformed(ActionEvent e) { + if (history!=null && historyPosnull if nothing is selected. + * + * @return The selected value. + */ + public Completion getSelection() { + return isShowing() ? (Completion) list.getSelectedValue() : lastSelection; + } + + + /** + * Inserts the currently selected completion. + * + * @see #getSelection() + */ + private void insertSelectedCompletion() { + Completion comp = getSelection(); + ac.insertCompletion(comp); + } + + + /** + * Registers keyboard actions to listen for in the text component and + * intercept. + * + * @see #uninstallKeyBindings() + */ + private void installKeyBindings() { + + if (AutoCompletion.getDebug()) { + System.out.println("PopupWindow: Installing keybindings"); + } + + if (escapeKap == null) { // Lazily create actions. + createKeyActionPairs(); + } + + JTextComponent comp = ac.getTextComponent(); + InputMap im = comp.getInputMap(); + ActionMap am = comp.getActionMap(); + + replaceAction(im, am, KeyEvent.VK_ESCAPE, escapeKap, oldEscape); + if (AutoCompletion.getDebug() && oldEscape.action == escapeKap.action) { + Thread.dumpStack(); + } + replaceAction(im, am, KeyEvent.VK_UP, upKap, oldUp); + replaceAction(im, am, KeyEvent.VK_LEFT, leftKap, oldLeft); + replaceAction(im, am, KeyEvent.VK_DOWN, downKap, oldDown); + replaceAction(im, am, KeyEvent.VK_RIGHT, rightKap, oldRight); + replaceAction(im, am, KeyEvent.VK_ENTER, enterKap, oldEnter); + replaceAction(im, am, KeyEvent.VK_TAB, tabKap, oldTab); + replaceAction(im, am, KeyEvent.VK_HOME, homeKap, oldHome); + replaceAction(im, am, KeyEvent.VK_END, endKap, oldEnd); + replaceAction(im, am, KeyEvent.VK_PAGE_UP, pageUpKap, oldPageUp); + replaceAction(im, am, KeyEvent.VK_PAGE_DOWN, pageDownKap, oldPageDown); + + // Make Ctrl+C copy from description window. This isn't done + // automagically because the desc. window is not focusable, and copying + // from text components can only be done from focused components. + KeyStroke ks = getCopyKeyStroke(); + oldCtrlC.key = im.get(ks); + im.put(ks, ctrlCKap.key); + oldCtrlC.action = am.get(ctrlCKap.key); + am.put(ctrlCKap.key, ctrlCKap.action); + + comp.addCaretListener(this); + + } + + + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + insertSelectedCompletion(); + } + } + + + public void mouseEntered(MouseEvent e) { + } + + + public void mouseExited(MouseEvent e) { + } + + + public void mousePressed(MouseEvent e) { + } + + + public void mouseReleased(MouseEvent e) { + } + + + /** + * Positions the description window relative to the completion choices + * window. We assume there is room on one side of the other for this + * entire window to fit. + */ + private void positionDescWindow() { + + boolean showDescWindow = descWindow != null && ac.getShowDescWindow(); + if (!showDescWindow) { + return; + } + + // Don't use getLocationOnScreen() as this throws an exception if + // window isn't visible yet, but getLocation() doesn't, and is in + // screen coordinates! + Point p = getLocation(); + Rectangle screenBounds = Util.getScreenBoundsForPoint(p.x, p.y); + //Dimension screenSize = getToolkit().getScreenSize(); + //int totalH = Math.max(getHeight(), descWindow.getHeight()); + + // Try to position to the right first (LTR) + int x; + if (ac.getTextComponentOrientation().isLeftToRight()) { + x = getX() + getWidth() + 5; + if (x + descWindow.getWidth() > screenBounds.x + screenBounds.width) { // doesn't fit + x = getX() - 5 - descWindow.getWidth(); + } + } else { // RTL + x = getX() - 5 - descWindow.getWidth(); + if (x < screenBounds.x) { // Doesn't fit + x = getX() + getWidth() + 5; + } + } + + int y = getY(); + if (aboveCaret) { + y = y + getHeight() - descWindow.getHeight(); + } + + if (x != descWindow.getX() || y != descWindow.getY()) { + descWindow.setLocation(x, y); + } + + } + + + /** + * "Puts back" the original key/Action pair for a keystroke. This is used + * when this popup is hidden. + * + * @param im The input map. + * @param am The action map. + * @param key The keystroke whose key/Action pair to change. + * @param kap The (original) key/Action pair. + * @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair) + */ + private void putBackAction(InputMap im, ActionMap am, int key, + KeyActionPair kap) { + KeyStroke ks = KeyStroke.getKeyStroke(key, 0); + am.put(im.get(ks), kap.action); // Original action for the "new" key + im.put(ks, kap.key); // Original key for the keystroke. + } + + + /** + * Replaces a key/Action pair in an InputMap and ActionMap with a new + * pair. + * + * @param im The input map. + * @param am The action map. + * @param key The keystroke whose information to replace. + * @param kap The new key/Action pair for key. + * @param old A buffer in which to place the old key/Action pair. + * @see #putBackAction(InputMap, ActionMap, int, KeyActionPair) + */ + private void replaceAction(InputMap im, ActionMap am, int key, + KeyActionPair kap, KeyActionPair old) { + KeyStroke ks = KeyStroke.getKeyStroke(key, 0); + old.key = im.get(ks); + im.put(ks, kap.key); + old.action = am.get(kap.key); + am.put(kap.key, kap.action); + } + + + /** + * Selects the first item in the completion list. + * + * @see #selectLastItem() + */ + private void selectFirstItem() { + if (model.getSize() > 0) { + list.setSelectedIndex(0); + list.ensureIndexIsVisible(0); + } + } + + + /** + * Selects the last item in the completion list. + * + * @see #selectFirstItem() + */ + private void selectLastItem() { + int index = model.getSize() - 1; + if (index > -1) { + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + } + + + /** + * Selects the next item in the completion list. + * + * @see #selectPreviousItem() + */ + private void selectNextItem() { + int index = list.getSelectedIndex(); + if (index > -1) { + index = (index + 1) % model.getSize(); + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + } + + + /** + * Selects the completion item one "page down" from the currently selected + * one. + * + * @see #selectPageUpItem() + */ + private void selectPageDownItem() { + int visibleRowCount = list.getVisibleRowCount(); + int i = Math.min(list.getModel().getSize() - 1, + list.getSelectedIndex() + visibleRowCount); + list.setSelectedIndex(i); + list.ensureIndexIsVisible(i); + } + + + /** + * Selects the completion item one "page up" from the currently selected + * one. + * + * @see #selectPageDownItem() + */ + private void selectPageUpItem() { + int visibleRowCount = list.getVisibleRowCount(); + int i = Math.max(0, list.getSelectedIndex() - visibleRowCount); + list.setSelectedIndex(i); + list.ensureIndexIsVisible(i); + } + + + /** + * Selects the previous item in the completion list. + * + * @see #selectNextItem() + */ + private void selectPreviousItem() { + int index = list.getSelectedIndex(); + switch (index) { + case 0: + index = list.getModel().getSize() - 1; + break; + case -1: // Check for an empty list (would be an error) + index = list.getModel().getSize() - 1; + if (index == -1) { + return; + } + break; + default: + index = index - 1; + break; + } + list.setSelectedIndex(index); + list.ensureIndexIsVisible(index); + } + + + /** + * Sets the completions to display in the choices list. The first + * completion is selected. + * + * @param completions The completions to display. + */ + public void setCompletions(List completions) { + model.setContents(completions); + selectFirstItem(); + } + + + /** + * Sets the size of the description window. + * + * @param size The new size. This cannot be null. + */ + public void setDescriptionWindowSize(Dimension size) { + if (descWindow != null) { + descWindow.setSize(size); + } else { + preferredDescWindowSize = size; + } + } + + + /** + * Sets the default list cell renderer to use when a completion provider + * does not supply its own. + * + * @param renderer The renderer to use. If this is null, + * a default renderer is used. + * @see #getListCellRenderer() + */ + public void setListCellRenderer(ListCellRenderer renderer) { + DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. + getCellRenderer(); + dcr.setFallbackCellRenderer(renderer); + } + + + /** + * Sets the location of this window to be "good" relative to the specified + * rectangle. That rectangle should be the location of the text + * component's caret, in screen coordinates. + * + * @param r The text component's caret position, in screen coordinates. + */ + public void setLocationRelativeTo(Rectangle r) { + + // Multi-monitor support - make sure the completion window (and + // description window, if applicable) both fit in the same window in + // a multi-monitor environment. To do this, we decide which monitor + // the rectangle "r" is in, and use that one (just pick top-left corner + // as the defining point). + Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y); + //Dimension screenSize = getToolkit().getScreenSize(); + + boolean showDescWindow = descWindow != null && ac.getShowDescWindow(); + int totalH = getHeight(); + if (showDescWindow) { + totalH = Math.max(totalH, descWindow.getHeight()); + } + + // Try putting our stuff "below" the caret first. We assume that the + // entire height of our stuff fits on the screen one way or the other. + aboveCaret = false; + int y = r.y + r.height + VERTICAL_SPACE; + if (y + totalH > screenBounds.height) { + y = r.y - VERTICAL_SPACE - getHeight(); + aboveCaret = true; + } + + // Get x-coordinate of completions. Try to align left edge with the + // caret first. + int x = r.x; + if (!ac.getTextComponentOrientation().isLeftToRight()) { + x -= getWidth(); // RTL => align right edge + } + if (x < screenBounds.x) { + x = screenBounds.x; + } else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit + x = screenBounds.x + screenBounds.width - getWidth(); + } + + setLocation(x, y); + + // Position the description window, if necessary. + if (showDescWindow) { + positionDescWindow(); + } + + } + + + /** + * Toggles the visibility of this popup window. + * + * @param visible Whether this window should be visible. + */ + @Override + public void setVisible(boolean visible) { + + if (visible != isVisible()) { + + if (visible) { + installKeyBindings(); + lastLine = ac.getLineOfCaret(); + selectFirstItem(); + if (descWindow == null && ac.getShowDescWindow()) { + descWindow = createDescriptionWindow(); + positionDescWindow(); + } + // descWindow needs a kick-start the first time it's displayed. + // Also, the newly-selected item in the choices list is + // probably different from the previous one anyway. + if (descWindow != null) { + Completion c = (Completion) list.getSelectedValue(); + if (c != null) { + descWindow.setDescriptionFor(c); + } + } + } else { + uninstallKeyBindings(); + } + + super.setVisible(visible); + + // Some languages, such as Java, can use quite a lot of memory + // when displaying hundreds of completion choices. We pro-actively + // clear our list model here to make them available for GC. + // Otherwise, they stick around, and consider the following: a + // user starts code-completion for Java 5 SDK classes, then hides + // the dialog, then changes the "class path" to use a Java 6 SDK + // instead. On pressing Ctrl+space, a new array of Completions is + // created. If this window holds on to the previous Completions, + // you're getting roughly 2x the necessary Completions in memory + // until the Completions are actually passed to this window. + if (!visible) { // Do after super.setVisible(false) + lastSelection = (Completion) list.getSelectedValue(); + model.clear(); + } + + // Must set descWindow's visibility one way or the other each time, + // because of the way child JWindows' visibility is handled - in + // some ways it's dependent on the parent, in other ways it's not. + if (descWindow != null) { + descWindow.setVisible(visible && ac.getShowDescWindow()); + } + + } + + } + + + /** + * Stops intercepting certain keystrokes from the text component. + * + * @see #installKeyBindings() + */ + private void uninstallKeyBindings() { + + if (AutoCompletion.getDebug()) { + System.out.println("PopupWindow: Removing keybindings"); + } + + JTextComponent comp = ac.getTextComponent(); + InputMap im = comp.getInputMap(); + ActionMap am = comp.getActionMap(); + + putBackAction(im, am, KeyEvent.VK_ESCAPE, oldEscape); + putBackAction(im, am, KeyEvent.VK_UP, oldUp); + putBackAction(im, am, KeyEvent.VK_DOWN, oldDown); + putBackAction(im, am, KeyEvent.VK_LEFT, oldLeft); + putBackAction(im, am, KeyEvent.VK_RIGHT, oldRight); + putBackAction(im, am, KeyEvent.VK_ENTER, oldEnter); + putBackAction(im, am, KeyEvent.VK_TAB, oldTab); + putBackAction(im, am, KeyEvent.VK_HOME, oldHome); + putBackAction(im, am, KeyEvent.VK_END, oldEnd); + putBackAction(im, am, KeyEvent.VK_PAGE_UP, oldPageUp); + putBackAction(im, am, KeyEvent.VK_PAGE_DOWN, oldPageDown); + + // Ctrl+C + KeyStroke ks = getCopyKeyStroke(); + am.put(im.get(ks), oldCtrlC.action); // Original action + im.put(ks, oldCtrlC.key); // Original key + + comp.removeCaretListener(this); + + } + + + /** + * Updates the LookAndFeel of this window and the description + * window. + */ + public void updateUI() { + SwingUtilities.updateComponentTreeUI(this); + if (descWindow != null) { + descWindow.updateUI(); + } + } + + + /** + * Called when a new item is selected in the popup list. + * + * @param e The event. + */ + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + Object value = list.getSelectedValue(); + if (value != null && descWindow != null) { + descWindow.setDescriptionFor((Completion) value); + positionDescWindow(); + } + } + } + + + class CopyAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + boolean doNormalCopy = false; + if (descWindow != null && descWindow.isVisible()) { + doNormalCopy = !descWindow.copy(); + } + if (doNormalCopy) { + ac.getTextComponent().copy(); + } + } + + } + + + class DownAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectNextItem(); + } + } + + } + + + class EndAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectLastItem(); + } + } + + } + + + class EnterAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + insertSelectedCompletion(); + } + } + + } + + + class EscapeAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + setVisible(false); + } + } + + } + + + class HomeAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectFirstItem(); + } + } + + } + + + /** + * A mapping from a key (an Object) to an Action. + */ + private static class KeyActionPair { + + public Object key; + public Action action; + + public KeyActionPair() { + } + + public KeyActionPair(Object key, Action a) { + this.key = key; + this.action = a; + } + + } + + + class LeftAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + JTextComponent comp = ac.getTextComponent(); + Caret c = comp.getCaret(); + int dot = c.getDot(); + if (dot > 0) { + c.setDot(--dot); + // Ensure moving left hasn't moved us up a line, thus + // hiding the popup window. + if (comp.isVisible()) { + if (lastLine != -1) { + doAutocomplete(); + } + } + } + } + } + + } + + + class PageDownAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectPageDownItem(); + } + } + + } + + + class PageUpAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectPageUpItem(); + } + } + + } + + + /** + * The actual list of completion choices in this popup window. + */ + private class PopupList extends JList { + + public PopupList(CompletionListModel model) { + super(model); + } + + @Override + public void setUI(ListUI ui) { + if (Util.getUseSubstanceRenderers() && + SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) { + // Substance requires its special ListUI be installed for + // its renderers to actually render (!), but long completion + // lists (e.g. PHPCompletionProvider in RSTALanguageSupport) + // will simply populate too slowly on initial display (when + // calculating preferred size of all items), so in this case + // we give a prototype cell value. + CompletionProvider p = ac.getCompletionProvider(); + BasicCompletion bc = new BasicCompletion(p, "Hello world"); + setPrototypeCellValue(bc); + } else { + // Our custom UI that is faster for long HTML completion lists. + ui = new FastListUI(); + setPrototypeCellValue(null); + } + super.setUI(ui); + } + + } + + + class RightAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + JTextComponent comp = ac.getTextComponent(); + Caret c = comp.getCaret(); + int dot = c.getDot(); + if (dot < comp.getDocument().getLength()) { + c.setDot(++dot); + // Ensure moving right hasn't moved us up a line, thus + // hiding the popup window. + if (comp.isVisible()) { + if (lastLine != -1) { + doAutocomplete(); + } + } + } + } + } + + } + + + class UpAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isVisible()) { + selectPreviousItem(); + } + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/AutoCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompletion.java new file mode 100644 index 0000000000..83047ad71b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompletion.java @@ -0,0 +1,1344 @@ +/* + * 12/21/2008 + * + * AutoCompletion.java - Handles auto-completion for a text component. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; +import javax.swing.*; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.*; + + +/** + * Adds auto-completion to a text component. Provides a popup window with a + * list of auto-complete choices on a given keystroke, such as Crtrl+Space.

+ * + * Depending on the {@link CompletionProvider} installed, the following + * auto-completion features may be enabled: + * + *

    + *
  • An auto-complete choices list made visible via e.g. Ctrl+Space
  • + *
  • A "description" window displayed alongside the choices list that + * provides documentation on the currently selected completion choice + * (as seen in Eclipse and NetBeans).
  • + *
  • Parameter assistance. If this is enabled, if the user enters a + * "parameterized" completion, such as a method or a function, then + * they will receive a tool tip describing the arguments they have to + * enter to the completion. Also, the arguments can be navigated via + * tab and shift+tab (a la Eclipse and NetBeans).
  • + *
+ * + * @author Robert Futrell + * @version 1.0 + */ +/* + * This class handles intercepting window and hierarchy events from the text + * component, so the popup window is only visible when it should be visible. + * It also handles communication between the CompletionProvider and the actual + * popup Window. + */ +public class AutoCompletion { + + /** + * The text component we're providing completion for. + */ + private JTextComponent textComponent; + + /** + * The parent window of {@link #textComponent}. + */ + private Window parentWindow; + + /** + * The popup window containing completion choices. + */ + private AutoCompletePopupWindow popupWindow; + + /** + * The preferred size of the completion choices window. This field exists + * because the user will likely set the preferred size of the window + * before it is actually created. + */ + private Dimension preferredChoicesWindowSize; + + /** + * The preferred size of the optional description window. This field + * only exists because the user may (and usually will) set the size of + * the description window before it exists (it must be parented to a + * Window). + */ + private Dimension preferredDescWindowSize; + + /** + * Manages any parameterized completions that are inserted. + */ + private ParameterizedCompletionContext pcc; + + /** + * Provides the completion options relevant to the current caret position. + */ + private CompletionProvider provider; + + /** + * The renderer to use for the completion choices. If this is + * null, then a default renderer is used. + */ + private ListCellRenderer renderer; + + /** + * The handler to use when an external URL is clicked in the help + * documentation. + */ + private ExternalURLHandler externalURLHandler; + + /** + * An optional redirector that converts URL's to some other location before + * being handed over to externalURLHandler. + */ + private static LinkRedirector linkRedirector; + + /** + * Whether the description window should be displayed along with the + * completion choice window. + */ + private boolean showDescWindow; + + /** + * Whether auto-complete is enabled. + */ + private boolean autoCompleteEnabled; + + /** + * Whether the auto-activation of auto-complete (after a delay, after the + * user types an appropriate character) is enabled. + */ + private boolean autoActivationEnabled; + + /** + * Whether or not, when there is only a single auto-complete option + * that matches the text at the current text position, that text should + * be auto-inserted, instead of the completion window displaying. + */ + private boolean autoCompleteSingleChoices; + + /** + * Whether parameter assistance is enabled. + */ + private boolean parameterAssistanceEnabled; + + /** + * A renderer used for {@link Completion}s in the optional parameter + * choices popup window (displayed when a {@link ParameterizedCompletion} + * is code-completed). If this isn't set, a default renderer is used. + */ + private ListCellRenderer paramChoicesRenderer; + + /** + * The keystroke that triggers the completion window. + */ + private KeyStroke trigger; + + /** + * The previous key in the text component's InputMap for the + * trigger key. + */ + private Object oldTriggerKey; + + /** + * The action previously assigned to {@link #trigger}, so we can reset it + * if the user disables auto-completion. + */ + private Action oldTriggerAction; + + /** + * The previous key in the text component's InputMap for the + * parameter completion trigger key. + */ + private Object oldParenKey; + + /** + * The action previously assigned to the parameter completion key, so we + * can reset it when we uninstall. + */ + private Action oldParenAction; + + /** + * Listens for events in the parent window that affect the visibility of + * the popup windows. + */ + private ParentWindowListener parentWindowListener; + + /** + * Listens for events from the text component that affect the visibility + * of the popup windows. + */ + private TextComponentListener textComponentListener; + + /** + * Listens for events in the text component that cause the popup windows + * to automatically activate. + */ + private AutoActivationListener autoActivationListener; + + /** + * Listens for LAF changes so the auto-complete windows automatically + * update themselves accordingly. + */ + private LookAndFeelChangeListener lafListener; + + /** + * The key used in the input map for the AutoComplete action. + */ + private static final String PARAM_TRIGGER_KEY = "AutoComplete"; + + /** + * Key used in the input map for the parameter completion action. + */ + private static final String PARAM_COMPLETE_KEY = "AutoCompletion.FunctionStart"; + + /** + * Stores how to render auto-completion-specific highlights in text + * components. + */ + private static final AutoCompletionStyleContext styleContext = + new AutoCompletionStyleContext(); + + /** + * Whether debug messages should be printed to stdout as AutoCompletion + * runs. + */ + private static final boolean DEBUG = initDebug(); + + + /** + * Constructor. + * + * @param provider The completion provider. This cannot be + * null. + */ + public AutoCompletion(CompletionProvider provider) { + + setChoicesWindowSize(350, 200); + setDescriptionWindowSize(350, 250); + + setCompletionProvider(provider); + setTriggerKey(getDefaultTriggerKey()); + setAutoCompleteEnabled(true); + setAutoCompleteSingleChoices(true); + setAutoActivationEnabled(false); + setShowDescWindow(false); + parentWindowListener = new ParentWindowListener(); + textComponentListener = new TextComponentListener(); + autoActivationListener = new AutoActivationListener(); + lafListener = new LookAndFeelChangeListener(); + + } + + + /** + * Displays the popup window. Hosting applications can call this method + * to programmatically begin an auto-completion operation. + */ + public void doCompletion() { + refreshPopupWindow(); + } + + + /** + * Returns the delay between when the user types a character and when the + * code completion popup should automatically appear (if applicable). + * + * @return The delay, in milliseconds. + * @see #setAutoActivationDelay(int) + */ + public int getAutoActivationDelay() { + return autoActivationListener.timer.getDelay(); + } + + + /** + * Returns whether, if a single auto-complete choice is available, it + * should be automatically inserted, without displaying the popup menu. + * + * @return Whether to auto-complete single choices. + * @see #setAutoCompleteSingleChoices(boolean) + */ + public boolean getAutoCompleteSingleChoices() { + return autoCompleteSingleChoices; + } + + + /** + * Returns the completion provider. + * + * @return The completion provider. + */ + public CompletionProvider getCompletionProvider() { + return provider; + } + + + /** + * Returns whether debug is enabled for AutoCompletion. + * + * @return Whether debug is enabled. + */ + static boolean getDebug() { + return DEBUG; + } + + + /** + * Returns the default auto-complete "trigger key" for this OS. For + * Windows, for example, it is Ctrl+Space. + * + * @return The default auto-complete trigger key. + */ + public static KeyStroke getDefaultTriggerKey() { + // Default to CTRL, even on Mac, since Ctrl+Space activates Spotlight + int mask = InputEvent.CTRL_MASK; + return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, mask); + } + + + /** + * Returns the handler to use when an external URL is clicked in the + * description window. + * + * @return The handler. + * @see #setExternalURLHandler(ExternalURLHandler) + * @see #getLinkRedirector() + */ + public ExternalURLHandler getExternalURLHandler() { + return externalURLHandler; + } + + + int getLineOfCaret() { + Document doc = textComponent.getDocument(); + Element root = doc.getDefaultRootElement(); + return root.getElementIndex(textComponent.getCaretPosition()); + } + + + /** + * Returns the link redirector, if any. + * + * @return The link redirector, or null if none. + * @see #setLinkRedirector(LinkRedirector) + */ + public static LinkRedirector getLinkRedirector() { + return linkRedirector; + } + + + /** + * Returns the default list cell renderer used when a completion provider + * does not supply its own. + * + * @return The default list cell renderer. + * @see #setListCellRenderer(ListCellRenderer) + */ + public ListCellRenderer getListCellRenderer() { + return renderer; + } + + + /** + * Returns the renderer to use for {@link Completion}s in the optional + * parameter choices popup window (displayed when a + * {@link ParameterizedCompletion} is code-completed). If this returns + * null, a default renderer is used. + * + * @return The renderer to use. + * @see #setParamChoicesRenderer(ListCellRenderer) + * @see #isParameterAssistanceEnabled() + */ + public ListCellRenderer getParamChoicesRenderer() { + return paramChoicesRenderer; + } + + + /** + * Returns the text to replace with in the document. This is a + * "last-chance" hook for subclasses to make special modifications to the + * completion text inserted. The default implementation simply returns + * c.getReplacementText(). You usually will not need to modify + * this method. + * + * @param c The completion being inserted. + * @param doc The document being modified. + * @param start The start of the text being replaced. + * @param len The length of the text being replaced. + * @return The text to replace with. + */ + protected String getReplacementText(Completion c, Document doc, int start, + int len) { + return c.getReplacementText(); + } + + + /** + * Returns whether the "description window" should be shown alongside + * the completion window. + * + * @return Whether the description window should be shown. + * @see #setShowDescWindow(boolean) + */ + public boolean getShowDescWindow() { + return showDescWindow; + } + + + /** + * Returns the style context describing how auto-completion related + * highlights in the editor are rendered. + * + * @return The style context. + */ + public static AutoCompletionStyleContext getStyleContext() { + return styleContext; + } + + + /** + * Returns the text component for which auto-completion is enabled. + * + * @return The text component, or null if this + * {@link AutoCompletion} is not installed on any text component. + * @see #install(JTextComponent) + */ + public JTextComponent getTextComponent() { + return textComponent; + } + + + /** + * Returns the orientation of the text component we're installed to. + * + * @return The orientation of the text component, or null if + * we are not installed on one. + */ + ComponentOrientation getTextComponentOrientation() { + return textComponent==null ? null : + textComponent.getComponentOrientation(); + } + + + /** + * Returns the "trigger key" used for auto-complete. + * + * @return The trigger key. + * @see #setTriggerKey(KeyStroke) + */ + public KeyStroke getTriggerKey() { + return trigger; + } + + + /** + * Hides any child windows being displayed by the auto-completion system. + * + * @return Whether any windows were visible. + */ + public boolean hideChildWindows() { + //return hidePopupWindow() || hideToolTipWindow(); + boolean res = hidePopupWindow(); + res |= hideParameterCompletionPopups(); + return res; + } + + + /** + * Hides and disposes of any parameter completion-related popups. + * + * @return Whether any such windows were visible (and thus hidden). + */ + private boolean hideParameterCompletionPopups() { + if (pcc!=null) { + pcc.deactivate(); + pcc = null; + return true; + } + return false; + } + + + /** + * Hides the popup window, if it is visible. + * + * @return Whether the popup window was visible. + */ + private boolean hidePopupWindow() { + if (popupWindow!=null) { + if (popupWindow.isVisible()) { + popupWindow.setVisible(false); + return true; + } + } + return false; + } + + + /** + * Determines whether debug should be enabled for the AutoCompletion + * library. This method checks a system property, but takes care of + * {@link SecurityException}s in case we're in an applet or WebStart. + * + * @return Whether debug should be enabled. + */ + private static final boolean initDebug() { + boolean debug = false; + try { + debug = Boolean.getBoolean("AutoCompletion.debug"); + } catch (SecurityException se) { // We're in an applet or WebStart. + debug = false; + } + return debug; + } + + + /** + * Inserts a completion. Any time a code completion event occurs, the + * actual text insertion happens through this method. + * + * @param c A completion to insert. This cannot be null. + */ + protected final void insertCompletion(Completion c) { + insertCompletion(c, false); + } + + + /** + * Inserts a completion. Any time a code completion event occurs, the + * actual text insertion happens through this method. + * + * @param c A completion to insert. This cannot be null. + * @param typedParamListStartChar Whether the parameterized completion + * start character was typed (typically '('). + */ + protected void insertCompletion(Completion c, + boolean typedParamListStartChar) { + + JTextComponent textComp = getTextComponent(); + String alreadyEntered = c.getAlreadyEntered(textComp); + hidePopupWindow(); + Caret caret = textComp.getCaret(); + + int dot = caret.getDot(); + int len = alreadyEntered.length(); + int start = dot-len; + String replacement = getReplacementText(c, textComp.getDocument(), + start, len); + + caret.setDot(start); + caret.moveDot(dot); + textComp.replaceSelection(replacement); + + if (isParameterAssistanceEnabled() && + (c instanceof ParameterizedCompletion)) { + ParameterizedCompletion pc = (ParameterizedCompletion)c; + startParameterizedCompletionAssistance(pc, typedParamListStartChar); + } + + } + + + /** + * Installs this auto-completion on a text component. If this + * {@link AutoCompletion} is already installed on another text component, + * it is uninstalled first. + * + * @param c The text component. + * @see #uninstall() + */ + public void install(JTextComponent c) { + + if (textComponent!=null) { + uninstall(); + } + + this.textComponent = c; + installTriggerKey(getTriggerKey()); + + // Install the function completion key, if there is one. + // NOTE: We cannot do this if the start char is ' ' (e.g. just a space + // between the function name and parameters) because it overrides + // RSTA's special space action. It seems KeyStorke.getKeyStroke(' ') + // hoses ctrl+space, shift+space, etc., even though I think it + // shouldn't... + char start = provider.getParameterListStart(); + if (start!=0 && start!=' ') { + InputMap im = c.getInputMap(); + ActionMap am = c.getActionMap(); + KeyStroke ks = KeyStroke.getKeyStroke(start); + oldParenKey = im.get(ks); + im.put(ks, PARAM_COMPLETE_KEY); + oldParenAction = am.get(PARAM_COMPLETE_KEY); + am.put(PARAM_COMPLETE_KEY, + new ParameterizedCompletionStartAction(start)); + } + + textComponentListener.addTo(this.textComponent); + // In case textComponent is already in a window... + textComponentListener.hierarchyChanged(null); + + if (isAutoActivationEnabled()) { + autoActivationListener.addTo(this.textComponent); + } + + UIManager.addPropertyChangeListener(lafListener); + updateUI(); // In case there have been changes since we uninstalled + + } + + + /** + * Installs a "trigger key" action onto the current text component. + * + * @param ks The keystroke that should trigger the action. + * @see #uninstallTriggerKey() + */ + private void installTriggerKey(KeyStroke ks) { + InputMap im = textComponent.getInputMap(); + oldTriggerKey = im.get(ks); + im.put(ks, PARAM_TRIGGER_KEY); + ActionMap am = textComponent.getActionMap(); + oldTriggerAction = am.get(PARAM_TRIGGER_KEY); + am.put(PARAM_TRIGGER_KEY, new AutoCompleteAction()); + } + + + /** + * Returns whether auto-activation is enabled (that is, whether the + * completion popup will automatically appear after a delay when the user + * types an appropriate character). Note that this parameter will be + * ignored if auto-completion is disabled. + * + * @return Whether auto-activation is enabled. + * @see #setAutoActivationEnabled(boolean) + * @see #getAutoActivationDelay() + * @see #isAutoCompleteEnabled() + */ + public boolean isAutoActivationEnabled() { + return autoActivationEnabled; + } + + + /** + * Returns whether auto-completion is enabled. + * + * @return Whether auto-completion is enabled. + * @see #setAutoCompleteEnabled(boolean) + */ + public boolean isAutoCompleteEnabled() { + return autoCompleteEnabled; + } + + + /** + * Returns whether parameter assistance is enabled. + * + * @return Whether parameter assistance is enabled. + * @see #setParameterAssistanceEnabled(boolean) + */ + public boolean isParameterAssistanceEnabled() { + return parameterAssistanceEnabled; + } + + + /** + * Returns whether the completion popup window is visible. + * + * @return Whether the completion popup window is visible. + */ + public boolean isPopupVisible() { + return popupWindow!=null && popupWindow.isVisible(); + } + + + /** + * Refreshes the popup window. First, this method gets the possible + * completions for the current caret position. If there are none, and the + * popup is visible, it is hidden. If there are some completions and the + * popup is hidden, it is made visible and made to display the completions. + * If there are some completions and the popup is visible, its list is + * updated to the current set of completions. + * + * @return The current line number of the caret. + */ + protected int refreshPopupWindow() { + + // A return value of null => don't suggest completions + String text = provider.getAlreadyEnteredText(textComponent); + if (text==null && !isPopupVisible()) { + return getLineOfCaret(); + } + + // If the popup is currently visible, and they type a space (or any + // character that resets the completion list to "all completions"), + // the popup window should be hidden instead of being reset to show + // everything. + int textLen = text==null ? 0 : text.length(); + if (textLen==0) { + if (isPopupVisible()) { + hidePopupWindow(); + return getLineOfCaret(); + } + } + + final List completions = provider. + getCompletions(textComponent); + int count = completions.size(); + + if (count>1 || (count==1 && (isPopupVisible() || textLen==0)) || + (count==1 && !getAutoCompleteSingleChoices())) { + + if (popupWindow==null) { + popupWindow = new AutoCompletePopupWindow(parentWindow, this); + // Completion is usually done for code, which is always done + // LTR, so make completion stuff RTL only if text component is + // also RTL. + popupWindow.applyComponentOrientation( + getTextComponentOrientation()); + if (renderer!=null) { + popupWindow.setListCellRenderer(renderer); + } + if (preferredChoicesWindowSize!=null) { + popupWindow.setSize(preferredChoicesWindowSize); + } + if (preferredDescWindowSize!=null) { + popupWindow.setDescriptionWindowSize( + preferredDescWindowSize); + } + } + + popupWindow.setCompletions(completions); + + if (!popupWindow.isVisible()) { + Rectangle r = null; + try { + r = textComponent.modelToView(textComponent. + getCaretPosition()); + } catch (BadLocationException ble) { + + return -1; + } + Point p = new Point(r.x, r.y); + SwingUtilities.convertPointToScreen(p, textComponent); + r.x = p.x; + r.y = p.y; + popupWindow.setLocationRelativeTo(r); + popupWindow.setVisible(true); + } + + } + + else if (count==1) { // !isPopupVisible && autoCompleteSingleChoices + SwingUtilities.invokeLater(new Runnable() { + public void run() { + insertCompletion(completions.get(0)); + } + }); + } + + else { + hidePopupWindow(); + } + + return getLineOfCaret(); + + } + + + /** + * Sets the delay between when the user types a character and when the + * code completion popup should automatically appear (if applicable). + * + * @param ms The delay, in milliseconds. This should be greater than zero. + * @see #getAutoActivationDelay() + */ + public void setAutoActivationDelay(int ms) { + ms = Math.max(0, ms); + autoActivationListener.timer.stop(); + autoActivationListener.timer.setInitialDelay(ms); + } + + + /** + * Toggles whether auto-activation is enabled. Note that auto-activation + * also depends on auto-completion itself being enabled. + * + * @param enabled Whether auto-activation is enabled. + * @see #isAutoActivationEnabled() + * @see #setAutoActivationDelay(int) + */ + public void setAutoActivationEnabled(boolean enabled) { + if (enabled!=autoActivationEnabled) { + autoActivationEnabled = enabled; + if (textComponent!=null) { + if (autoActivationEnabled) { + autoActivationListener.addTo(textComponent); + } + else { + autoActivationListener.removeFrom(textComponent); + } + } + } + } + + + /** + * Sets whether auto-completion is enabled. + * + * @param enabled Whether auto-completion is enabled. + * @see #isAutoCompleteEnabled() + */ + public void setAutoCompleteEnabled(boolean enabled) { + if (enabled!=autoCompleteEnabled) { + autoCompleteEnabled = enabled; + hidePopupWindow(); + } + } + + + /** + * Sets whether, if a single auto-complete choice is available, it should + * be automatically inserted, without displaying the popup menu. + * + * @param autoComplete Whether to auto-complete single choices. + * @see #getAutoCompleteSingleChoices() + */ + public void setAutoCompleteSingleChoices(boolean autoComplete) { + autoCompleteSingleChoices = autoComplete; + } + + + /** + * Sets the completion provider being used. + * + * @param provider The new completion provider. This cannot be + * null. + * @throws IllegalArgumentException If provider is + * null. + */ + public void setCompletionProvider(CompletionProvider provider) { + if (provider==null) { + throw new IllegalArgumentException("provider cannot be null"); + } + this.provider = provider; + hidePopupWindow(); // In case new choices should be displayed. + } + + + /** + * Sets the size of the completion choices window. + * + * @param w The new width. + * @param h The new height. + * @see #setDescriptionWindowSize(int, int) + */ + public void setChoicesWindowSize(int w, int h) { + preferredChoicesWindowSize = new Dimension(w, h); + if (popupWindow!=null) { + popupWindow.setSize(preferredChoicesWindowSize); + } + } + + + /** + * Sets the size of the description window. + * + * @param w The new width. + * @param h The new height. + * @see #setChoicesWindowSize(int, int) + */ + public void setDescriptionWindowSize(int w, int h) { + preferredDescWindowSize = new Dimension(w, h); + if (popupWindow!=null) { + popupWindow.setDescriptionWindowSize(preferredDescWindowSize); + } + } + + + /** + * Sets the handler to use when an external URL is clicked in the + * description window. This handler can perform some action, such as + * open the URL in a web browser. The default implementation will open + * the URL in a browser, but only if running in Java 6. If you want + * browser support for Java 5 and below, or otherwise want to respond to + * hyperlink clicks, you will have to install your own handler to do so. + * + * @param handler The new handler. + * @see #getExternalURLHandler() + */ + public void setExternalURLHandler(ExternalURLHandler handler) { + this.externalURLHandler = handler; + } + + + /** + * Sets the redirector for external URL's found in code completion + * documentation. When a non-local link in completion popups is clicked, + * this redirector is given the chance to modify the URL fetched and + * displayed. + * + * @param linkRedirector The link redirector, or null for + * none. + * @see #getLinkRedirector() + */ + public static void setLinkRedirector(LinkRedirector linkRedirector) { + AutoCompletion.linkRedirector = linkRedirector; + } + + + /** + * Sets the default list cell renderer to use when a completion provider + * does not supply its own. + * + * @param renderer The renderer to use. If this is null, + * a default renderer is used. + * @see #getListCellRenderer() + */ + public void setListCellRenderer(ListCellRenderer renderer) { + this.renderer = renderer; + if (popupWindow!=null) { + popupWindow.setListCellRenderer(renderer); + hidePopupWindow(); + } + } + + + /** + * Sets the renderer to use for {@link Completion}s in the optional + * parameter choices popup window (displayed when a + * {@link ParameterizedCompletion} is code-completed). If this isn't set, + * a default renderer is used. + * + * @param r The renderer to use. + * @see #getParamChoicesRenderer() + * @see #setParameterAssistanceEnabled(boolean) + */ + public void setParamChoicesRenderer(ListCellRenderer r) { + paramChoicesRenderer = r; + } + + + /** + * Sets whether parameter assistance is enabled. If parameter assistance + * is enabled, and a "parameterized" completion (such as a function or + * method) is inserted, the user will get "assistance" in inserting the + * parameters in the form of a popup window with documentation and easy + * tabbing through the arguments (as seen in Eclipse and NetBeans). + * + * @param enabled Whether parameter assistance should be enabled. + * @see #isParameterAssistanceEnabled() + */ + public void setParameterAssistanceEnabled(boolean enabled) { + parameterAssistanceEnabled = enabled; + } + + + /** + * Sets whether the "description window" should be shown beside the + * completion window. + * + * @param show Whether to show the description window. + * @see #getShowDescWindow() + */ + public void setShowDescWindow(boolean show) { + hidePopupWindow(); // Needed to force it to take effect + showDescWindow = show; + } + + + /** + * Sets the keystroke that should be used to trigger the auto-complete + * popup window. + * + * @param ks The keystroke. + * @throws IllegalArgumentException If ks is null. + * @see #getTriggerKey() + */ + public void setTriggerKey(KeyStroke ks) { + if (ks==null) { + throw new IllegalArgumentException("trigger key cannot be null"); + } + if (!ks.equals(trigger)) { + if (textComponent!=null) { + // Put old trigger action back. + uninstallTriggerKey(); + // Grab current action for new trigger and replace it. + installTriggerKey(ks); + } + trigger = ks; + } + } + + + /** + * Displays a "tool tip" detailing the inputs to the function just entered. + * + * @param pc The completion. + * @param typedParamListStartChar Whether the parameterized completion list + * starting character was typed. + */ + private void startParameterizedCompletionAssistance( + ParameterizedCompletion pc, boolean typedParamListStartChar) { + + // Get rid of the previous tool tip window, if there is one. + hideParameterCompletionPopups(); + + // Don't bother with a tool tip if there are no parameters, but if + // they typed e.g. the opening '(', make them overtype the ')'. + if (pc.getParamCount()==0 && !(pc instanceof TemplateCompletion)) { + CompletionProvider p = pc.getProvider(); + char end = p.getParameterListEnd(); // Might be '\0' + String text = end=='\0' ? "" : Character.toString(end); + if (typedParamListStartChar) { + String template = "${}" + text + "${cursor}"; + textComponent.replaceSelection(Character.toString(p.getParameterListStart())); + TemplateCompletion tc = new TemplateCompletion(p, null, null, template); + pc = tc; + } + else { + text = p.getParameterListStart() + text; + textComponent.replaceSelection(text); + return; + } + } + + pcc = new ParameterizedCompletionContext(parentWindow, this, pc); + pcc.activate(); + + } + + + /** + * Uninstalls this auto-completion from its text component. If it is not + * installed on any text component, nothing happens. + * + * @see #install(JTextComponent) + */ + public void uninstall() { + + if (textComponent!=null) { + + hidePopupWindow(); // Unregisters listeners, actions, etc. + + uninstallTriggerKey(); + + // Uninstall the function completion key. + char start = provider.getParameterListStart(); + if (start!=0) { + KeyStroke ks = KeyStroke.getKeyStroke(start); + InputMap im = textComponent.getInputMap(); + im.put(ks, oldParenKey); + ActionMap am = textComponent.getActionMap(); + am.put(PARAM_COMPLETE_KEY, oldParenAction); + } + + textComponentListener.removeFrom(textComponent); + if (parentWindow!=null) { + parentWindowListener.removeFrom(parentWindow); + } + + if (isAutoActivationEnabled()) { + autoActivationListener.removeFrom(textComponent); + } + + UIManager.removePropertyChangeListener(lafListener); + + textComponent = null; + popupWindow = null; + + } + + } + + + /** + * Replaces the "trigger key" action with the one that was there + * before auto-completion was installed. + * + * @see #installTriggerKey(KeyStroke) + */ + private void uninstallTriggerKey() { + InputMap im = textComponent.getInputMap(); + im.put(trigger, oldTriggerKey); + ActionMap am = textComponent.getActionMap(); + am.put(PARAM_TRIGGER_KEY, oldTriggerAction); + } + + + /** + * Updates the LookAndFeel of the popup window. Applications can call + * this method as appropriate if they support changing the LookAndFeel + * at runtime. + */ + private void updateUI() { + if (popupWindow!=null) { + popupWindow.updateUI(); + } + if (pcc!=null) { + pcc.updateUI(); + } + // Will practically always be a JComponent (a JLabel) + if (paramChoicesRenderer instanceof JComponent) { + ((JComponent)paramChoicesRenderer).updateUI(); + } + } + + + /** + * Listens for events in the text component to auto-activate the code + * completion popup. + */ + private class AutoActivationListener extends FocusAdapter + implements DocumentListener, CaretListener, ActionListener { + + private Timer timer; + private boolean justInserted; + + public AutoActivationListener() { + timer = new Timer(200, this); + timer.setRepeats(false); + } + + public void actionPerformed(ActionEvent e) { + doCompletion(); + } + + public void addTo(JTextComponent tc) { + tc.addFocusListener(this); + tc.getDocument().addDocumentListener(this); + tc.addCaretListener(this); + } + + public void caretUpdate(CaretEvent e) { + if (justInserted) { + justInserted = false; + } + else { + timer.stop(); + } + } + + public void changedUpdate(DocumentEvent e) { + // Ignore + } + + @Override + public void focusLost(FocusEvent e) { + timer.stop(); + //hideChildWindows(); Other listener will do this + } + + public void insertUpdate(DocumentEvent e) { + justInserted = false; + if (isAutoCompleteEnabled() && isAutoActivationEnabled() && + e.getLength()==1) { + if (provider.isAutoActivateOkay(textComponent)) { + timer.restart(); + justInserted = true; + } + else { + timer.stop(); + } + } + else { + timer.stop(); + } + } + + public void removeFrom(JTextComponent tc) { + tc.removeFocusListener(this); + tc.getDocument().removeDocumentListener(this); + tc.removeCaretListener(this); + timer.stop(); + justInserted = false; + } + + public void removeUpdate(DocumentEvent e) { + timer.stop(); + } + + } + + + /** + * The Action that displays the popup window if + * auto-completion is enabled. + */ + private class AutoCompleteAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (isAutoCompleteEnabled()) { + refreshPopupWindow(); + } + else if (oldTriggerAction!=null) { + oldTriggerAction.actionPerformed(e); + } + } + + } + + + /** + * Listens for LookAndFeel changes and updates the various popup windows + * involved in auto-completion accordingly. + */ + private class LookAndFeelChangeListener implements PropertyChangeListener { + + public void propertyChange(PropertyChangeEvent e) { + String name = e.getPropertyName(); + if ("lookAndFeel".equals(name)) { + updateUI(); + } + } + + } + + + /** + * Action that starts a parameterized completion, e.g. after '(' is + * typed. + */ + private class ParameterizedCompletionStartAction extends AbstractAction { + + private String start; + + public ParameterizedCompletionStartAction(char ch) { + this.start = Character.toString(ch); + } + + public void actionPerformed(ActionEvent e) { + + // Prevents keystrokes from messing up + boolean wasVisible = hidePopupWindow(); + + // Only proceed if they were selecting a completion + if (!wasVisible || !isParameterAssistanceEnabled()) { + textComponent.replaceSelection(start); + return; + } + + Completion c = popupWindow.getSelection(); + if (c instanceof ParameterizedCompletion) { // Should always be true + // Fixes capitalization of the entered text. + insertCompletion(c, true); + } + + } + + } + + + /** + * Listens for events in the parent window of the text component with + * auto-completion enabled. + */ + private class ParentWindowListener extends ComponentAdapter + implements WindowFocusListener { + + public void addTo(Window w) { + w.addComponentListener(this); + w.addWindowFocusListener(this); + } + + @Override + public void componentHidden(ComponentEvent e) { + hideChildWindows(); + } + + @Override + public void componentMoved(ComponentEvent e) { + hideChildWindows(); + } + + @Override + public void componentResized(ComponentEvent e) { + hideChildWindows(); + } + + public void removeFrom(Window w) { + w.removeComponentListener(this); + w.removeWindowFocusListener(this); + } + + public void windowGainedFocus(WindowEvent e) { + } + + public void windowLostFocus(WindowEvent e) { + hideChildWindows(); + } + + } + + + /** + * Listens for events from the text component we're installed on. + */ + private class TextComponentListener extends FocusAdapter + implements HierarchyListener { + + void addTo(JTextComponent tc) { + tc.addFocusListener(this); + tc.addHierarchyListener(this); + } + + /** + * Hide the auto-completion windows when the text component loses + * focus. + */ + @Override + public void focusLost(FocusEvent e) { + hideChildWindows(); + } + + /** + * Called when the component hierarchy for our text component changes. + * When the text component is added to a new {@link Window}, this + * method registers listeners on that Window. + * + * @param e The event. + */ + public void hierarchyChanged(HierarchyEvent e) { + + // NOTE: e many be null as we call this method at other times. + //System.out.println("Hierarchy changed! " + e); + + Window oldParentWindow = parentWindow; + parentWindow = SwingUtilities.getWindowAncestor(textComponent); + if (parentWindow!=oldParentWindow) { + if (oldParentWindow!=null) { + parentWindowListener.removeFrom(oldParentWindow); + } + if (parentWindow!=null) { + parentWindowListener.addTo(parentWindow); + } + } + + } + + public void removeFrom(JTextComponent tc) { + tc.removeFocusListener(this); + tc.removeHierarchyListener(this); + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/AutoCompletionStyleContext.java b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompletionStyleContext.java new file mode 100644 index 0000000000..5aab27359e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/AutoCompletionStyleContext.java @@ -0,0 +1,120 @@ +/* + * 06/24/2012 + * + * AutoCompletionStyleContext.java - Manages styles related to auto-completion. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Color; + + +/** + * Manages the colors shared across the library. + * + * @author Robert Futrell + * @version 1.0 + */ +public class AutoCompletionStyleContext { + + /** + * The color used to denote the ending caret position for parameterized + * completions. + */ + private Color parameterizedCompletionCursorPositionColor; + + /** + * The color used to highlight copies of editable parameters in + * parameterized completions. + */ + private Color parameterCopyColor; + + /** + * The color of the outline highlight used to denote editable parameters + * in parameterized completions. + */ + private Color parameterOutlineColor; + + + public AutoCompletionStyleContext() { + setParameterOutlineColor(Color.gray); + setParameterCopyColor(new Color(0xb4d7ff)); + setParameterizedCompletionCursorPositionColor(new Color(0x00b400)); + } + + + /** + * Returns the color of the highlight painted on copies of editable + * parameters in parameterized completions. + * + * @return The color used. + * @see #setParameterCopyColor(Color) + */ + public Color getParameterCopyColor() { + return parameterCopyColor; + } + + + /** + * Returns the color used to denote the ending caret position for + * parameterized completions. + * + * @return The color used. + * @see #setParameterizedCompletionCursorPositionColor(Color) + */ + public Color getParameterizedCompletionCursorPositionColor() { + return parameterizedCompletionCursorPositionColor; + } + + + /** + * Returns the color of the outline highlight used to denote editable + * parameters in parameterized completions. + * + * @return The color used. + * @see #setParameterOutlineColor(Color) + */ + public Color getParameterOutlineColor() { + return parameterOutlineColor; + } + + + /** + * Sets the color of the highlight painted on copies of editable + * parameters in parameterized completions. + * + * @param color The color to use. + * @see #setParameterCopyColor(Color) + */ + public void setParameterCopyColor(Color color) { + this.parameterCopyColor = color; + } + + + /** + * Sets the color used to denote the ending caret position for + * parameterized completions. + * + * @param color The color to use. + * @see #getParameterizedCompletionCursorPositionColor() + */ + public void setParameterizedCompletionCursorPositionColor(Color color) { + this.parameterizedCompletionCursorPositionColor = color; + } + + + /** + * Sets the color of the outline highlight used to denote editable + * parameters in parameterized completions. + * + * @param color The color to use. + * @see #getParameterOutlineColor() + */ + public void setParameterOutlineColor(Color color) { + this.parameterOutlineColor = color; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/BasicCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/BasicCompletion.java new file mode 100644 index 0000000000..2a71506e04 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/BasicCompletion.java @@ -0,0 +1,144 @@ +/* + * 01/03/2009 + * + * BasicCompletion.java - A straightforward Completion implementation. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + + +/** + * A straightforward {@link Completion} implementation. This implementation + * can be used if you have a relatively short number of static completions + * with no (or short) summaries.

+ * + * This implementation uses the replacement text as the input text. It also + * includes a "short description" field, which (if non-null), is + * used in the completion choices list. + * + * @author Robert Futrell + * @version 1.0 + */ +public class BasicCompletion extends AbstractCompletion { + + private String replacementText; + private String shortDesc; + private String summary; + + + /** + * Constructor. + * + * @param provider The parent completion provider. + * @param replacementText The text to replace. + */ + public BasicCompletion(CompletionProvider provider, String replacementText){ + this(provider, replacementText, null); + } + + + /** + * Constructor. + * + * @param provider The parent completion provider. + * @param replacementText The text to replace. + * @param shortDesc A short description of the completion. This will be + * displayed in the completion list. This may be null. + */ + public BasicCompletion(CompletionProvider provider, String replacementText, + String shortDesc) { + this(provider, replacementText, shortDesc, null); + } + + + /** + * Constructor. + * + * @param provider The parent completion provider. + * @param replacementText The text to replace. + * @param shortDesc A short description of the completion. This will be + * displayed in the completion list. This may be null. + * @param summary The summary of this completion. This should be HTML. + * This may be null. + */ + public BasicCompletion(CompletionProvider provider, String replacementText, + String shortDesc, String summary) { + super(provider); + this.replacementText = replacementText; + this.shortDesc = shortDesc; + this.summary = summary; + } + + + /** + * {@inheritDoc} + */ + public String getReplacementText() { + return replacementText; + } + + + /** + * Returns the short description of this completion, usually used in + * the completion choices list. + * + * @return The short description, or null if there is none. + * @see #setShortDescription(String) + */ + public String getShortDescription() { + return shortDesc; + } + + + /** + * {@inheritDoc} + */ + public String getSummary() { + return summary; + } + + + /** + * Sets the short description of this completion. + * + * @param shortDesc The short description of this completion. + * @see #getShortDescription() + */ + public void setShortDescription(String shortDesc) { + this.shortDesc = shortDesc; + } + + + /** + * Sets the summary for this completion. + * + * @param summary The summary for this completion. + * @see #getSummary() + */ + public void setSummary(String summary) { + this.summary = summary; + } + + + /** + * Returns a string representation of this completion. If the short + * description is not null, this method will return: + * + * getInputText() + " - " + shortDesc + * + * otherwise, it will return getInputText(). + * + * @return A string representation of this completion. + */ + @Override + public String toString() { + if (shortDesc==null) { + return getInputText(); + } + return getInputText() + " - " + shortDesc; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/Completion.java b/designer_base/src/com/fr/design/gui/autocomplete/Completion.java new file mode 100644 index 0000000000..d65c9f727a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/Completion.java @@ -0,0 +1,153 @@ +/* + * 12/21/2008 + * + * Completion.java - Represents a single completion choice. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import javax.swing.Icon; +import javax.swing.text.JTextComponent; + + +/** + * Represents a completion choice. A {@link CompletionProvider} returns lists + * of objects implementing this interface. A Completion contains the + * following information: + * + *

    + *
  • The text the user must (begin to) input for this to be a completion + * choice. + *
  • The text that will be filled in if the user chooses this completion. + * Note that often, this is the same as the text the user must (begin to) + * enter, but this doesn't have to be the case. + *
  • Summary HTML that describes this completion. This is information that + * can be displayed in a helper "tooltip"-style window beside the + * completion list. This may be null. It may also be + * lazily generated to cut down on memory usage. + *
  • The CompletionProvider that returned this completion. + *
  • Tool tip text that can be displayed when a mouse hovers over this + * completion in a text component. + *
+ * + * @author Robert Futrell + * @version 1.0 + * @see AbstractCompletion + */ +public interface Completion extends Comparable { + + + /** + * Compares this completion to another one lexicographically, ignoring + * case. + * + * @param other Another completion instance. + * @return How this completion compares to the other one. + */ + public int compareTo(Completion other); + + + /** + * Returns the portion of this completion that has already been entered + * into the text component. The match is case-insensitive.

+ * + * This is a convenience method for: + * getProvider().getAlreadyEnteredText(comp). + * + * @param comp The text component. + * @return The already-entered portion of this completion. + */ + public String getAlreadyEntered(JTextComponent comp); + + + /** + * Returns the icon to use for this completion. + * + * @return The icon, or null for none. + */ + public Icon getIcon(); + + + /** + * Returns the text that the user has to (start) typing for this completion + * to be offered. Note that this will usually be the same value as + * {@link #getReplacementText()}, but not always (a completion could be + * a way to implement shorthand, for example, "sysout" mapping + * to "System.out.println("). + * + * @return The text the user has to (start) typing for this completion to + * be offered. + * @see #getReplacementText() + */ + public String getInputText(); + + + /** + * Returns the provider that returned this completion. + * + * @return The provider. + */ + public CompletionProvider getProvider(); + + + /** + * Returns the "relevance" of this completion. This is used when sorting + * completions by their relevance. It is an abstract concept that may + * mean different things to different languages, and may depend on the + * context of the completion.

+ * + * By default, all completions have a relevance of 0. The + * higher the value returned by this method, the higher up in the list + * this completion will be; the lower the value returned, the lower it will + * be. Completions with equal relevance values will be + * sorted alphabetically. + * + * @return The relevance of this completion. + */ + public int getRelevance(); + + + /** + * Returns the text to insert as the result of this auto-completion. This + * is the "complete" text, including any text that replaces what the user + * has already typed. + * + * @return The replacement text. + * @see #getInputText() + */ + public String getReplacementText(); + + + /** + * Returns the description of this auto-complete choice. This can be + * used in a popup "description window." + * + * @return This item's description. This should be HTML. It may be + * null if there is no description for this + * completion. + */ + public String getSummary(); + + + /** + * Returns the tool tip text to display for mouse hovers over this + * completion.

+ * + * Note that for this functionality to be enabled, a + * JTextComponent must be registered with the + * ToolTipManager, and the text component must know to search + * for this value. In the case of an + * RSyntaxTextArea, this + * can be done with a org.fife.ui.rtextarea.ToolTipSupplier that + * calls into + * {@link CompletionProvider#getCompletionsAt(JTextComponent, java.awt.Point)}. + * + * @return The tool tip text for this completion, or null if + * none. + */ + public String getToolTipText(); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/CompletionCellRenderer.java b/designer_base/src/com/fr/design/gui/autocomplete/CompletionCellRenderer.java new file mode 100644 index 0000000000..47d09b64cb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/CompletionCellRenderer.java @@ -0,0 +1,625 @@ +/* + * 12/23/2008 + * + * CompletionCellRenderer.java - Cell renderer that can render the standard + * completion types like Eclipse or NetBeans does. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Rectangle; +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.JList; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicHTML; +import javax.swing.text.View; + + +/** + * A cell renderer that adds some pizazz when rendering the standard + * {@link Completion} types, like Eclipse and NetBeans do. Specifically, + * this renderer handles: + * + *

    + *
  • {@link FunctionCompletion}s
  • + *
  • {@link VariableCompletion}s
  • + *
  • {@link MarkupTagCompletion}s
  • + *
  • {@link ShorthandCompletion}s
  • + *
  • {@link TemplateCompletion}s
  • + *
+ * + * @author Robert Futrell + * @version 1.0 + */ +public class CompletionCellRenderer extends DefaultListCellRenderer { + + /** + * The alternating background color, or null if alternating + * row colors should not be used. + */ + private static Color altBG; + + /** + * The font to use when rendering items, or null if the + * list's default font should be used. + */ + private Font font; + + /** + * Whether to display the types of fields and return types of functions + * in the completion text. + */ + private boolean showTypes; + + /** + * The color to use when rendering types in completion text. + */ + private String typeColor; + + /** + * During rendering, whether the item being rendered is selected. + */ + private boolean selected; + + /** + * During rendering, this is the "real" background color of the item being + * rendered (i.e., what its background color is if it isn't selected). + */ + private Color realBG; + + /** + * The color to use for function arguments. + */ + private String paramColor; + + /** + * Used in rendering calculations. + */ + private Rectangle paintTextR; + + /** + * An optional delegate renderer (primarily for Substance). + */ + private DefaultListCellRenderer delegate; + + private static final String SUBSTANCE_RENDERER_CLASS_NAME = + "org.pushingpixels.substance.api.renderers.SubstanceDefaultListCellRenderer"; + + /** + * Keeps the HTML descriptions from "wrapping" in the list, which cuts off + * words. + */ + private static final String PREFIX = ""; + + + /** + * Constructor. + */ + public CompletionCellRenderer() { + init(); + } + + + /** + * Constructor. This is primarily a hook for Substance, or any other + * Look and Feel whose renderers look drastically different than standard + * DefaultListCellRenderers. Everything except for the text + * rendering will be done by the delegate. In almost all scenarios, you + * will want to use the no-argument constructor instead of this one. + * + * @param delegate The delegate renderer. + * @see #delegateToSubstanceRenderer() + */ + public CompletionCellRenderer(DefaultListCellRenderer delegate) { + setDelegateRenderer(delegate); + init(); + } + + + /** + * Returns a decent "parameter" color based on the current default + * foreground color. + * + * @return The parameter color to use. + */ + private String createParamColor() { + return Util.isLightForeground(getForeground()) ? + Util.getHexString(Util.getHyperlinkForeground()): "#aa0077"; + } + + + /** + * Returns a decent "type" color based on the current default foreground + * color. + * + * @return The type color to use. + */ + private String createTypeColor() { + return "#808080"; + } + + + /** + * Attempts to delegate rendering to a Substance cell renderer. This + * should only be called if Substance is known to be on the classpath. + * + * @throws Exception If Substance is not on the classpath, or some other + * error occurs creating the Substance cell renderer. + * @see Util#getUseSubstanceRenderers() + * @see #setDelegateRenderer(DefaultListCellRenderer) + */ + public void delegateToSubstanceRenderer() throws Exception { + Class clazz = Class.forName(SUBSTANCE_RENDERER_CLASS_NAME); + DefaultListCellRenderer delegate = + (DefaultListCellRenderer)clazz.newInstance(); + setDelegateRenderer(delegate); + } + + + /** + * Returns the background color to use on alternating lines. + * + * @return The alternate background color. If this is null, + * alternating colors are not used. + * @see #setAlternateBackground(Color) + */ + public static Color getAlternateBackground() { + return altBG; + } + + + /** + * Returns the delegate renderer, or null if there is none. + * + * @return The delegate renderer. + * @see #setDelegateRenderer(DefaultListCellRenderer) + */ + public DefaultListCellRenderer getDelegateRenderer() { + return delegate; + } + + + /** + * Returns the font used when rendering completions. + * + * @return The font. If this is null, then the default list + * font is used. + * @see #setDisplayFont(Font) + */ + public Font getDisplayFont() { + return font; + } + + + /** + * Returns the renderer. + * + * @param list The list of choices being rendered. + * @param value The {@link Completion} being rendered. + * @param index The index into list being rendered. + * @param selected Whether the item is selected. + * @param hasFocus Whether the item has focus. + */ + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean selected, boolean hasFocus) { + + super.getListCellRendererComponent(list,value,index,selected,hasFocus); + if (font!=null) { + setFont(font); // Overrides super's setFont(list.getFont()). + } + this.selected = selected; + this.realBG = altBG!=null && (index&1)==1 ? altBG : list.getBackground(); + + Completion c = (Completion)value; + setIcon(c.getIcon()); + + if (c instanceof FunctionCompletion) { + FunctionCompletion fc = (FunctionCompletion)value; + prepareForFunctionCompletion(list, fc, index, selected, hasFocus); + } + else if (c instanceof VariableCompletion) { + VariableCompletion vc = (VariableCompletion)value; + prepareForVariableCompletion(list, vc, index, selected, hasFocus); + } + else if (c instanceof TemplateCompletion) { + TemplateCompletion tc = (TemplateCompletion)value; + prepareForTemplateCompletion(list, tc, index, selected, hasFocus); + } + else if (c instanceof MarkupTagCompletion) { + MarkupTagCompletion mtc = (MarkupTagCompletion)value; + prepareForMarkupTagCompletion(list, mtc, index, selected, hasFocus); + } + else { + prepareForOtherCompletion(list, c, index, selected, hasFocus); + } + + // A delegate renderer might do its own alternate row striping + // (Substance does). + if (delegate!=null) { + delegate.getListCellRendererComponent(list, getText(), index, + selected, hasFocus); + delegate.setFont(getFont()); + delegate.setIcon(getIcon()); + return delegate; + } + + if (!selected && (index&1)==1 && altBG!=null) { + setBackground(altBG); + } + + return this; + + } + + + /** + * Returns whether the types of fields and return types of methods are + * shown in the completion text. + * + * @return Whether to show the types. + * @see #setShowTypes(boolean) + */ + public boolean getShowTypes() { + return showTypes; + } + + + private void init() { + //setDisplayFont(new Font("Monospaced", Font.PLAIN, 12)); + setShowTypes(true); + typeColor = createTypeColor(); + paramColor = createParamColor(); + paintTextR = new Rectangle(); + } + + + @Override + protected void paintComponent(Graphics g) { + + //super.paintComponent(g); + + g.setColor(realBG); + int iconW = 0; + if (getIcon()!=null) { + iconW = getIcon().getIconWidth(); + } + if (selected && iconW>0) { // The icon area is never in the "selection" + g.fillRect(0, 0, iconW, getHeight()); + g.setColor(getBackground()); + g.fillRect(iconW,0, getWidth()-iconW,getHeight()); + } + else { + g.setColor(getBackground()); + g.fillRect(0, 0, getWidth(), getHeight()); + } + if (getIcon()!=null) { + getIcon().paintIcon(this, g, 0, 0); + } + + String text = getText(); + if (text != null) { + paintTextR.setBounds(iconW,0, getWidth()-iconW,getHeight()); + paintTextR.x += 3; // Force a slight margin + int space = paintTextR.height - g.getFontMetrics().getHeight(); + View v = (View)getClientProperty(BasicHTML.propertyKey); + if (v != null) { + // HTML rendering doesn't auto-center vertically, for some + // reason + paintTextR.y += space/2; + paintTextR.height -= space; + v.paint(g, paintTextR); + } + else { + int textX = paintTextR.x; + int textY = paintTextR.y;// + g.getFontMetrics().getAscent(); + //System.out.println(g.getFontMetrics().getAscent()); + g.drawString(text, textX, textY); + } + } + + } + + + /** + * Prepares this renderer to display a function completion. + * + * @param list The list of choices being rendered. + * @param fc The completion to render. + * @param index The index into list being rendered. + * @param selected Whether the item is selected. + * @param hasFocus Whether the item has focus. + */ + protected void prepareForFunctionCompletion(JList list, + FunctionCompletion fc, int index, boolean selected, boolean hasFocus) { + + StringBuilder sb = new StringBuilder(PREFIX); + sb.append(fc.getName()); + + char paramListStart = fc.getProvider().getParameterListStart(); + if (paramListStart!=0) { // 0 => no start char + sb.append(paramListStart); + } + + int paramCount = fc.getParamCount(); + for (int i=0; i"); + } + sb.append(type); + if (!selected) { + sb.append(""); + } + if (name!=null) { + sb.append(' '); + } + } + if (name!=null) { + sb.append(name); + } + if (i No parameter list end char + sb.append(paramListEnd); + } + + if (getShowTypes() && fc.getType()!=null) { + sb.append(" : "); + if (!selected) { + sb.append(""); + } + sb.append(fc.getType()); + if (!selected) { + sb.append(""); + } + } + + setText(sb.toString()); + + } + + + /** + * Prepares this renderer to display a markup tag completion. + * + * @param list The list of choices being rendered. + * @param mc The completion to render. + * @param index The index into list being rendered. + * @param selected Whether the item is selected. + * @param hasFocus Whether the item has focus. + */ + protected void prepareForMarkupTagCompletion(JList list, + MarkupTagCompletion mc, int index, boolean selected, boolean hasFocus) { + + StringBuilder sb = new StringBuilder(PREFIX); + sb.append(mc.getName()); + + setText(sb.toString()); + + } + + + /** + * Prepares this renderer to display a completion not specifically handled + * elsewhere. + * + * @param list The list of choices being rendered. + * @param c The completion to render. + * @param index The index into list being rendered. + * @param selected Whether the item is selected. + * @param hasFocus Whether the item has focus. + */ + protected void prepareForOtherCompletion(JList list, + Completion c, int index, boolean selected, boolean hasFocus) { + + StringBuilder sb = new StringBuilder(PREFIX); + sb.append(c.getInputText()); + + if (c instanceof BasicCompletion) { + String definition = ((BasicCompletion)c).getShortDescription(); + if (definition!=null) { + sb.append(" - "); + if (!selected) { + sb.append(""); + } + sb.append(definition); + if (!selected) { + sb.append(""); + } + } + } + + setText(sb.toString()); + + } + + + /** + * Prepares this renderer to display a template completion. + * + * @param list The list of choices being rendered. + * @param tc The completion to render. + * @param index The index into list being rendered. + * @param selected Whether the item is selected. + * @param hasFocus Whether the item has focus. + */ + protected void prepareForTemplateCompletion(JList list, + TemplateCompletion tc, int index, boolean selected, boolean hasFocus) { + + StringBuilder sb = new StringBuilder(PREFIX); + sb.append(tc.getInputText()); + + String definition = tc.getShortDescription(); + if (definition!=null) { + sb.append(" - "); + if (!selected) { + sb.append(""); + } + sb.append(definition); + if (!selected) { + sb.append(""); + } + } + + setText(sb.toString()); + + } + + + /** + * Prepares this renderer to display a variable completion. + * + * @param list The list of choices being rendered. + * @param vc The completion to render. + * @param index The index into list being rendered. + * @param selected Whether the item is selected. + * @param hasFocus Whether the item has focus. + */ + protected void prepareForVariableCompletion(JList list, + VariableCompletion vc, int index, boolean selected, boolean hasFocus) { + + StringBuilder sb = new StringBuilder(PREFIX); + sb.append(vc.getName()); + + if (getShowTypes() && vc.getType()!=null) { + sb.append(" : "); + if (!selected) { + sb.append(""); + } + sb.append(vc.getType()); + if (!selected) { + sb.append(""); + } + } + + setText(sb.toString()); + + } + + + /** + * Sets the background color to use on alternating lines. + * + * @param altBG The new alternate background color. If this is + * null, alternating lines will not use different + * background colors. + * @see #getAlternateBackground() + */ + public static void setAlternateBackground(Color altBG) { + CompletionCellRenderer.altBG = altBG; + } + + + /** + * Sets the delegate renderer. Most users will never use this method; it + * is primarily a hook for Substance and other Look and Feels whose + * renderers look drastically different from the standard + * DefaultListCellRenderer. + * + * @param delegate The new delegate renderer. If this is null, + * the default rendering of this component is used. + * @see #getDelegateRenderer() + * @see #delegateToSubstanceRenderer() + */ + public void setDelegateRenderer(DefaultListCellRenderer delegate) { + this.delegate = delegate; + } + + + /** + * Sets the font to use when rendering completion items. + * + * @param font The font to use. If this is null, then + * the default list font is used. + * @see #getDisplayFont() + */ + public void setDisplayFont(Font font) { + this.font = font; + } + + + /** + * Sets the icon to display based off of a completion, falling back to a + * default icon if the completion has no icon. + * + * @param completion The completion to check. + * @param defaultIcon The icon to use if completion does not + * specify an icon. + */ + protected void setIconWithDefault(Completion completion, Icon defaultIcon) { + Icon icon = completion.getIcon(); + setIcon(icon!=null ? icon : defaultIcon); + } + + + /** + * Sets the color to use for function arguments. + * + * @param color The color to use. This is ignored if null. + * @see #setTypeColor(Color) + */ + public void setParamColor(Color color) { + if (color!=null) { + paramColor = Util.getHexString(color); + } + } + + + /** + * Sets whether the types of fields and return types of methods are + * shown in the completion text. + * + * @param show Whether to show the types. + * @see #getShowTypes() + */ + public void setShowTypes(boolean show) { + this.showTypes = show; + } + + + /** + * Sets the color to use for function/field types. Note that if + * {@link #getShowTypes()} returns false, this property + * effectively does nothing. + * + * @param color The color to use for types. This is ignored if + * null. + * @see #setShowTypes(boolean) + * @see #setParamColor(Color) + */ + public void setTypeColor(Color color) { + if (color!=null) { + typeColor = Util.getHexString(color); + } + } + + + /** + * Overridden to update our delegate, if necessary. + */ + @Override + public void updateUI() { + super.updateUI(); + if (delegate!=null) { + SwingUtilities.updateComponentTreeUI(delegate); + } + paramColor = createParamColor(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/CompletionListModel.java b/designer_base/src/com/fr/design/gui/autocomplete/CompletionListModel.java new file mode 100644 index 0000000000..b6ed1e2996 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/CompletionListModel.java @@ -0,0 +1,88 @@ +/* + * 12/22/2008 + * + * CompletionListModel.java - A model that allows bulk addition of elements. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.swing.AbstractListModel; + + +/** + * A list model implementation that allows the bulk addition of elements. + * This is the only feature missing from DefaultListModel that + * we need. + * + * @author Robert Futrell + * @version 1.0 + */ +class CompletionListModel extends AbstractListModel { + + /** + * Container for items in this model. + */ + private List delegate; + + + /** + * Constructor. + */ + public CompletionListModel() { + delegate = new ArrayList(); + } + + + /** + * Removes all of the elements from this list. The list will + * be empty after this call returns (unless it throws an exception). + * + * @see #setContents(Collection) + */ + public void clear() { + int end = delegate.size()-1; + delegate.clear(); + if (end >= 0) { + fireIntervalRemoved(this, 0, end); + } + } + + + /** + * {@inheritDoc} + */ + public Object getElementAt(int index) { + return delegate.get(index); + } + + + /** + * {@inheritDoc} + */ + public int getSize() { + return delegate.size(); + } + + + /** + * Sets the contents of this model. All previous contents are removed. + * + * @param contents The new contents of this model. + */ + public void setContents(Collection contents) { + clear(); + int count = contents.size(); + if (count>0) { + delegate.addAll(contents); + fireIntervalAdded(this, 0, count-1); // endpoints included (!) + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/CompletionProvider.java b/designer_base/src/com/fr/design/gui/autocomplete/CompletionProvider.java new file mode 100644 index 0000000000..e886d741fb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/CompletionProvider.java @@ -0,0 +1,213 @@ +/* + * 12/21/2008 + * + * CompletionProvider.java - Provides autocompletion values based on the + * text currently in a text component. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Point; +import java.util.List; + +import javax.swing.ListCellRenderer; +import javax.swing.text.JTextComponent; + + +/** + * Provides autocompletion values to an {@link AutoCompletion}.

+ * + * Completion providers can have an optional parent. Parents are searched for + * completions when their children are. This allows for chaining of completion + * providers. + * + * @author Robert Futrell + * @version 1.0 + */ +public interface CompletionProvider { + + + /** + * Clears the values used to identify and insert "parameterized completions" + * (e.g. functions or methods). After this method is called, functions and + * methods will not have their parameters auto-completed. + * + * @see #setParameterizedCompletionParams(char, String, char) + */ + public void clearParameterizedCompletionParams(); + + + /** + * Returns the text just before the current caret position that could be + * the start of something auto-completable. + * + * @param comp The text component. + * @return The text. A return value of null means nothing + * should be auto-completed; a value of an empty string + * ("") means auto-completion should still be + * considered (i.e., all possible choices are valid). + */ + public String getAlreadyEnteredText(JTextComponent comp); + + + /** + * Gets the possible completions for the text component at the current + * caret position. + * + * @param comp The text component. + * @return The list of {@link Completion}s. If no completions are + * available, this may be null. + */ + public List getCompletions(JTextComponent comp); + + + /** + * Returns the completions that have been entered at the specified visual + * location. This can be used for tool tips when the user hovers the + * mouse over completed text. + * + * @param comp The text component. + * @param p The position, usually from a MouseEvent. + * @return The completions, or an empty list if there are none. + */ + public List getCompletionsAt(JTextComponent comp, Point p); + + + /** + * Returns the cell renderer for completions returned from this provider. + * + * @return The cell renderer, or null if the default should + * be used. + * @see #setListCellRenderer(ListCellRenderer) + */ + public ListCellRenderer getListCellRenderer(); + + + /** + * Returns an object that can return a list of completion choices for + * parameters. This is used when a user code-completes a parameterized + * completion, such as a function or method. For any parameter to the + * function/method, this object can return possible completions. + * + * @return The parameter choices provider, or null if + * none is installed. + */ + public ParameterChoicesProvider getParameterChoicesProvider(); + + + /** + * Returns a list of parameterized completions that have been entered + * at the current caret position of a text component (and thus can have + * their completion choices displayed). + * + * @param tc The text component. + * @return The list of {@link ParameterizedCompletion}s. If no completions + * are available, this may be null. + */ + public List getParameterizedCompletions(JTextComponent tc); + + + /** + * Returns the text that marks the end of a list of parameters to a + * function or method. + * + * @return The text for a parameter list end, for example, + * ')'. + * @see #getParameterListStart() + * @see #getParameterListSeparator() + * @see #setParameterizedCompletionParams(char, String, char) + */ + public char getParameterListEnd(); + + + /** + * Returns the text that separates parameters to a function or method. + * + * @return The text that separates parameters, for example, + * ", ". + * @see #getParameterListStart() + * @see #getParameterListEnd() + * @see #setParameterizedCompletionParams(char, String, char) + */ + public String getParameterListSeparator(); + + + /** + * Returns the text that marks the start of a list of parameters to a + * function or method. + * + * @return The text for a parameter list start, for example, + * "(". + * @see #getParameterListEnd() + * @see #getParameterListSeparator() + * @see #setParameterizedCompletionParams(char, String, char) + */ + public char getParameterListStart(); + + + /** + * Returns the parent completion provider. + * + * @return The parent completion provider. + * @see #setParent(CompletionProvider) + */ + public CompletionProvider getParent(); + + + /** + * This method is called if auto-activation is enabled in the parent + * {@link AutoCompletion} after the user types a single character. This + * provider should check the text at the current caret position of the + * text component, and decide whether auto-activation would be appropriate + * here. For example, a CompletionProvider for Java might + * want to return true for this method only if the last + * character typed was a '.'. + * + * @param tc The text component. + * @return Whether auto-activation would be appropriate. + */ + public boolean isAutoActivateOkay(JTextComponent tc); + + + /** + * Sets the renderer to use when displaying completion choices. + * + * @param r The renderer to use. + * @see #getListCellRenderer() + */ + public void setListCellRenderer(ListCellRenderer r); + + + /** + * Sets the values used to identify and insert "parameterized completions" + * (e.g. functions or methods). If this method isn't called, functions + * and methods will not have their parameters auto-completed. + * + * @param listStart The character that marks the beginning of a list of + * parameters, such as '(' in C or Java. + * @param separator Text that should separate parameters in a parameter + * list when one is inserted. For example, ", ". + * @param listEnd The character that marks the end of a list of parameters, + * such as ')' in C or Java. + * @throws IllegalArgumentException If either listStart or + * listEnd is not printable ASCII, or if + * separator is null or an empty string. + * @see #clearParameterizedCompletionParams() + */ + public void setParameterizedCompletionParams(char listStart, + String separator, char listEnd); + + + /** + * Sets the parent completion provider. + * + * @param parent The parent provider. null means there will + * be no parent provider. + * @see #getParent() + */ + public void setParent(CompletionProvider parent); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/CompletionProviderBase.java b/designer_base/src/com/fr/design/gui/autocomplete/CompletionProviderBase.java new file mode 100644 index 0000000000..82c369902f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/CompletionProviderBase.java @@ -0,0 +1,261 @@ +/* + * 02/06/2010 + * + * CompletionProviderBase.java - Base completion provider implementation. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.swing.ListCellRenderer; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; +import javax.swing.text.Segment; + + +/** + * A base class for all standard completion providers. This class implements + * functionality that should be sharable across all CompletionProvider + * implementations. + * + * @author Robert Futrell + * @version 1.0 + * @see AbstractCompletionProvider + */ +public abstract class CompletionProviderBase implements CompletionProvider { + + /** + * The parent completion provider. + */ + private CompletionProvider parent; + + /** + * The renderer to use for completions from this provider. If this is + * null, a default renderer is used. + */ + private ListCellRenderer listCellRenderer; + + /** + * Text that marks the beginning of a parameter list, for example, '('. + */ + private char paramListStart; + + /** + * Text that marks the end of a parameter list, for example, ')'. + */ + private char paramListEnd; + + /** + * Text that separates items in a parameter list, for example, ", ". + */ + private String paramListSeparator; + + /** + * Whether auto-activation should occur after letters. + */ + private boolean autoActivateAfterLetters; + + /** + * Non-letter chars that should cause auto-activation to occur. + */ + private String autoActivateChars; + + /** + * Provides completion choices for a parameterized completion's parameters. + */ + private ParameterChoicesProvider paramChoicesProvider; + + /** + * A segment to use for fast char access. + */ + private Segment s = new Segment(); + + protected static final String EMPTY_STRING = ""; + + /** + * Comparator used to sort completions by their relevance before sorting + * them lexicographically. + */ + private static final Comparator sortByRelevanceComparator = + new SortByRelevanceComparator(); + + + /** + * {@inheritDoc} + */ + public void clearParameterizedCompletionParams() { + paramListEnd = paramListStart = 0; + paramListSeparator = null; + } + + + /** + * {@inheritDoc} + */ + public List getCompletions(JTextComponent comp) { + + List completions = getCompletionsImpl(comp); + if (parent!=null) { + completions.addAll(parent.getCompletions(comp)); + Collections.sort(completions); + } + + // NOTE: We can't sort by relevance prior to this; we need to have + // things alphabetical so we can easily narrow down completions to + // those starting with what was already typed. + if (/*sortByRelevance*/true) { + Collections.sort(completions, sortByRelevanceComparator); + } + + return completions; + + } + + + /** + * Does the dirty work of creating a list of completions. + * + * @param comp The text component to look in. + * @return The list of possible completions, or an empty list if there + * are none. + */ + protected abstract List getCompletionsImpl(JTextComponent comp); + + + /** + * {@inheritDoc} + */ + public ListCellRenderer getListCellRenderer() { + return listCellRenderer; + } + + + /** + * {@inheritDoc} + */ + public ParameterChoicesProvider getParameterChoicesProvider() { + return paramChoicesProvider; + } + + + /** + * {@inheritDoc} + */ + public char getParameterListEnd() { + return paramListEnd; + } + + + /** + * {@inheritDoc} + */ + public String getParameterListSeparator() { + return paramListSeparator; + } + + + /** + * {@inheritDoc} + */ + public char getParameterListStart() { + return paramListStart; + } + + + /** + * {@inheritDoc} + */ + public CompletionProvider getParent() { + return parent; + } + + + /** + * {@inheritDoc} + */ + public boolean isAutoActivateOkay(JTextComponent tc) { + Document doc = tc.getDocument(); + char ch = 0; + try { + doc.getText(tc.getCaretPosition(), 1, s); + ch = s.first(); + } catch (BadLocationException ble) { // Never happens + + } + return (autoActivateAfterLetters && Character.isLetter(ch)) || + (autoActivateChars!=null && autoActivateChars.indexOf(ch)>-1); + } + + + /** + * Sets the characters that auto-activation should occur after. A Java + * completion provider, for example, might want to set others + * to ".", to allow auto-activation for members of an object. + * + * @param letters Whether auto-activation should occur after any letter. + * @param others A string of (non-letter) chars that auto-activation should + * occur after. This may be null. + */ + public void setAutoActivationRules(boolean letters, String others) { + autoActivateAfterLetters = letters; + autoActivateChars = others; + } + + + /** + * Sets the param choices provider. This is used when a user + * code-completes a parameterized completion, such as a function or method. + * For any parameter to the function/method, this object can return + * possible completions. + * + * @param pcp The parameter choices provider, or null for + * none. + * @see #getParameterChoicesProvider() + */ + public void setParameterChoicesProvider(ParameterChoicesProvider pcp) { + paramChoicesProvider = pcp; + } + + + /** + * {@inheritDoc} + */ + public void setListCellRenderer(ListCellRenderer r) { + listCellRenderer = r; + } + + + /** + * {@inheritDoc} + */ + public void setParameterizedCompletionParams(char listStart, + String separator, char listEnd) { + if (listStart<0x20 || listStart==0x7F) { + throw new IllegalArgumentException("Invalid listStart"); + } + if (listEnd<0x20 || listEnd==0x7F) { + throw new IllegalArgumentException("Invalid listEnd"); + } + if (separator==null || separator.length()==0) { + throw new IllegalArgumentException("Invalid separator"); + } + paramListStart = listStart; + paramListSeparator = separator; + paramListEnd = listEnd; + } + + + /** + * {@inheritDoc} + */ + public void setParent(CompletionProvider parent) { + this.parent = parent; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/CompletionXMLParser.java b/designer_base/src/com/fr/design/gui/autocomplete/CompletionXMLParser.java new file mode 100644 index 0000000000..f64ee63f01 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/CompletionXMLParser.java @@ -0,0 +1,446 @@ +/* + * 02/06/2010 + * + * CompletionXMLParser.java - Parses XML representing code completion for a + * C-like language. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + + +/** + * Parser for an XML file describing a procedural language such as C. XML + * files will be validated against the CompletionXml.dtd DTD + * found in this package. + * + * @author Robert Futrell + * @version 1.0 + */ +public class CompletionXMLParser extends DefaultHandler { + + /** + * The completions found after parsing the XML. + */ + private List completions; + + /** + * The provider we're getting completions for. + */ + private CompletionProvider provider; + + /** + * The completion provider to use when loading classes, such as custom + * {@link FunctionCompletion}s. + */ + private ClassLoader completionCL; + + + private String name; + private String type; + private String returnType; + private StringBuilder returnValDesc; + private StringBuilder desc; + private String paramName; + private String paramType; + private StringBuilder paramDesc; + private List params; + private String definedIn; + private boolean doingKeywords; + private boolean inKeyword; + private boolean gettingReturnValDesc; + private boolean gettingDesc; + private boolean gettingParams; + private boolean inParam; + private boolean gettingParamDesc; + private boolean inCompletionTypes; + private char paramStartChar; + private char paramEndChar; + private String paramSeparator; + + /** + * If specified in the XML, this class will be used instead of + * {@link FunctionCompletion} when appropriate. This class should extend + * FunctionCompletion, or stuff will break. + */ + private String funcCompletionType; + + /** + * The class loader to use to load custom completion classes, such as + * the one defined by {@link #funcCompletionType}. If this is + * null, then a default class loader is used. This field + * will usually be null. + */ + private static ClassLoader DEFAULT_COMPLETION_CLASS_LOADER; + + + /** + * Constructor. + * + * @param provider The provider to get completions for. + * @see #reset(CompletionProvider) + */ + public CompletionXMLParser(CompletionProvider provider) { + this(provider, null); + } + + + /** + * Constructor. + * + * @param provider The provider to get completions for. + * @param cl The class loader to use, if necessary, when loading classes + * from the XML (custom {@link FunctionCompletion}s, for example). + * This may be null if the default is to be used, or + * if the XML does not define specific classes for completion types. + * @see #reset(CompletionProvider) + */ + public CompletionXMLParser(CompletionProvider provider, ClassLoader cl) { + this.provider = provider; + this.completionCL = cl; + if (completionCL==null) { + // May also be null, but that's okay. + completionCL = DEFAULT_COMPLETION_CLASS_LOADER; + } + completions = new ArrayList(); + params = new ArrayList(1); + desc = new StringBuilder(); + paramDesc = new StringBuilder(); + returnValDesc = new StringBuilder(); + paramStartChar = paramEndChar = 0; + paramSeparator = null; + } + + + /** + * Called when character data inside an element is found. + */ + @Override + public void characters(char[] ch, int start, int length) { + if (gettingDesc) { + desc.append(ch, start, length); + } + else if (gettingParamDesc) { + paramDesc.append(ch, start, length); + } + else if (gettingReturnValDesc) { + returnValDesc.append(ch, start, length); + } + } + + + private FunctionCompletion createFunctionCompletion() { + + FunctionCompletion fc = null; + if (funcCompletionType!=null) { + try { + Class clazz = null; + if (completionCL!=null) { + clazz = Class.forName(funcCompletionType, true, + completionCL); + } + else { + clazz = Class.forName(funcCompletionType); + } + Constructor c = clazz.getDeclaredConstructor( + CompletionProvider.class, String.class, String.class); + fc = (FunctionCompletion)c.newInstance(provider, name, + returnType); + } catch (RuntimeException re) { // FindBugs + throw re; + } catch (Exception e) { + + } + } + + if (fc==null) { // Fallback if completion failed for some reason + fc = new FunctionCompletion(provider, name, returnType); + } + + if (desc.length()>0) { + fc.setShortDescription(desc.toString()); + desc.setLength(0); + } + fc.setParams(params); + fc.setDefinedIn(definedIn); + if (returnValDesc.length()>0) { + fc.setReturnValueDescription(returnValDesc.toString()); + returnValDesc.setLength(0); + } + + return fc; + + } + + + private BasicCompletion createOtherCompletion() { + BasicCompletion bc = new BasicCompletion(provider, name); + if (desc.length()>0) { + bc.setSummary(desc.toString()); + desc.setLength(0); + } + return bc; + } + + + private MarkupTagCompletion createMarkupTagCompletion() { + MarkupTagCompletion mc = new MarkupTagCompletion(provider, + name); + if (desc.length()>0) { + mc.setDescription(desc.toString()); + desc.setLength(0); + } + mc.setAttributes(params); + mc.setDefinedIn(definedIn); + return mc; + } + + + private VariableCompletion createVariableCompletion() { + VariableCompletion vc = new VariableCompletion(provider, + name, returnType); + if (desc.length()>0) { + vc.setShortDescription(desc.toString()); + desc.setLength(0); + } + vc.setDefinedIn(definedIn); + return vc; + } + + + /** + * Called when an element is closed. + */ + @Override + public void endElement(String uri, String localName, String qName) { + + if ("keywords".equals(qName)) { + doingKeywords = false; + } + + else if (doingKeywords) { + + if ("keyword".equals(qName)) { + Completion c = null; + if ("function".equals(type)) { + c = createFunctionCompletion(); + } + else if ("constant".equals(type)) { + c = createVariableCompletion(); + } + else if ("tag".equals(type)) { // Markup tag, such as HTML + c = createMarkupTagCompletion(); + } + else if ("other".equals(type)) { + c = createOtherCompletion(); + } + else { + throw new InternalError("Unexpected type: " + type); + } + completions.add(c); + inKeyword = false; + } + else if (inKeyword) { + if ("returnValDesc".equals(qName)) { + gettingReturnValDesc = false; + } + else if (gettingParams) { + if ("params".equals(qName)) { + gettingParams = false; + } + else if ("param".equals(qName)) { + FunctionCompletion.Parameter param = + new FunctionCompletion.Parameter(paramType, + paramName); + if (paramDesc.length()>0) { + param.setDescription(paramDesc.toString()); + paramDesc.setLength(0); + } + params.add(param); + inParam = false; + } + else if (inParam) { + if ("desc".equals(qName)) { + gettingParamDesc = false; + } + } + } + else if ("desc".equals(qName)) { + gettingDesc = false; + } + } + + } + + else if (inCompletionTypes) { + if ("completionTypes".equals(qName)) { + inCompletionTypes = false; + } + } + + } + + + @Override + public void error(SAXParseException e) throws SAXException { + throw e; + } + + /** + * Returns the completions found after parsing the XML. + * + * @return The completions. + */ + public List getCompletions() { + return completions; + } + + + /** + * Returns the parameter end character specified. + * + * @return The character, or 0 if none was specified. + */ + public char getParamEndChar() { + return paramEndChar; + } + + + /** + * Returns the parameter end string specified. + * + * @return The string, or null if none was specified. + */ + public String getParamSeparator() { + return paramSeparator; + } + + + /** + * Returns the parameter start character specified. + * + * @return The character, or 0 if none was specified. + */ + public char getParamStartChar() { + return paramStartChar; + } + + + private static final char getSingleChar(String str) { + return str.length()==1 ? str.charAt(0) : 0; + } + + + /** + * Resets this parser to grab more completions. + * + * @param provider The new provider to get completions for. + */ + public void reset(CompletionProvider provider) { + this.provider = provider; + completions.clear(); + doingKeywords = inKeyword = gettingDesc = gettingParams = inParam = + gettingParamDesc = false; + paramStartChar = paramEndChar = 0; + paramSeparator = null; + } + + + @Override + public InputSource resolveEntity(String publicID, + String systemID) throws SAXException { + return new InputSource(getClass(). + getResourceAsStream("CompletionXml.dtd")); + } + + /** + * Sets the class loader to use when loading custom classes to use for + * various {@link Completion} types, such as {@link FunctionCompletion}s, + * from XML.

+ * + * Users should very rarely have a need to use this method. + * + * @param cl The class loader to use. If this is null, then + * a default is used. + */ + public static void setDefaultCompletionClassLoader(ClassLoader cl) { + DEFAULT_COMPLETION_CLASS_LOADER = cl; + } + + + /** + * Called when an element starts. + */ + @Override + public void startElement(String uri, String localName, String qName, + Attributes attrs) { + if ("keywords".equals(qName)) { + doingKeywords = true; + } + else if (doingKeywords) { + if ("keyword".equals(qName)) { + name = attrs.getValue("name"); + type = attrs.getValue("type"); + returnType = attrs.getValue("returnType"); + params.clear(); + definedIn = attrs.getValue("definedIn"); + inKeyword = true; + } + else if (inKeyword) { + if ("returnValDesc".equals(qName)) { + gettingReturnValDesc = true; + } + else if ("params".equals(qName)) { + gettingParams = true; + } + else if (gettingParams) { + if ("param".equals(qName)) { + paramName = attrs.getValue("name"); + paramType = attrs.getValue("type"); + inParam = true; + } + if (inParam) { + if ("desc".equals(qName)) { + gettingParamDesc = true; + } + } + } + else if ("desc".equals(qName)) { + gettingDesc = true; + } + } + } + else if ("environment".equals(qName)) { + paramStartChar = getSingleChar(attrs.getValue("paramStartChar")); + paramEndChar = getSingleChar(attrs.getValue("paramEndChar")); + paramSeparator = attrs.getValue("paramSeparator"); + //paramTerminal = attrs.getValua("terminal"); + } + else if ("completionTypes".equals(qName)) { + inCompletionTypes = true; + } + else if (inCompletionTypes) { + if ("functionCompletionType".equals(qName)) { + funcCompletionType = attrs.getValue("type"); + } + } + } + + + @Override + public void warning(SAXParseException e) throws SAXException { + throw e; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/CompletionXml.dtd b/designer_base/src/com/fr/design/gui/autocomplete/CompletionXml.dtd new file mode 100644 index 0000000000..6e6b0b618d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/CompletionXml.dtd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + diff --git a/designer_base/src/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java b/designer_base/src/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java new file mode 100644 index 0000000000..1aca8e71d1 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/DefaultCompletionProvider.java @@ -0,0 +1,374 @@ +/* + * 12/21/2008 + * + * DefaultCompletionProvider.java - A basic completion provider implementation. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Point; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.JTextComponent; +import javax.swing.text.Segment; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.SAXException; + + +/** + * A basic completion provider implementation. This provider has no + * understanding of language semantics. It simply checks the text entered up + * to the caret position for a match against known completions. This is all + * that is needed in the majority of cases. + * + * @author Robert Futrell + * @version 1.0 + */ +public class DefaultCompletionProvider extends AbstractCompletionProvider { + + protected Segment seg; + + /** + * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}. + */ + private String lastCompletionsAtText; + + /** + * Used to speed up {@link #getCompletionsAt(JTextComponent, Point)}, + * since this may be called multiple times in succession (this is usually + * called by JTextComponent.getToolTipText(), and if the user + * wiggles the mouse while a tool tip is displayed, this method gets + * repeatedly called. It can be costly so we try to speed it up a tad). + */ + private List lastParameterizedCompletionsAt; + + /** + * Constructor. The returned provider will not be aware of any completions. + * + * @see #addCompletion(Completion) + */ + public DefaultCompletionProvider() { + init(); + } + + + /** + * Creates a completion provider that provides completion for a simple + * list of words. + * + * @param words The words to offer as completion suggestions. If this is + * null, no completions will be known. + * @see BasicCompletion + */ + public DefaultCompletionProvider(String[] words) { + init(); + addWordCompletions(words); + } + + + /** + * Returns the text just before the current caret position that could be + * the start of something auto-completable.

+ * + * This method returns all characters before the caret that are matched + * by {@link #isValidChar(char)}. + * + * {@inheritDoc} + */ + public String getAlreadyEnteredText(JTextComponent comp) { + + Document doc = comp.getDocument(); + + int dot = comp.getCaretPosition(); + Element root = doc.getDefaultRootElement(); + int index = root.getElementIndex(dot); + Element elem = root.getElement(index); + int start = elem.getStartOffset(); + int len = dot-start; + try { + doc.getText(start, len, seg); + } catch (BadLocationException ble) { + + return EMPTY_STRING; + } + + int segEnd = seg.offset + len; + start = segEnd - 1; + while (start>=seg.offset && isValidChar(seg.array[start])) { + start--; + } + start++; + + len = segEnd - start; + return len==0 ? EMPTY_STRING : new String(seg.array, start, len); + + } + + + /** + * {@inheritDoc} + */ + public List getCompletionsAt(JTextComponent tc, Point p) { + + int offset = tc.viewToModel(p); + if (offset<0 || offset>=tc.getDocument().getLength()) { + lastCompletionsAtText = null; + return lastParameterizedCompletionsAt = null; + } + + Segment s = new Segment(); + Document doc = tc.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(offset); + Element elem = root.getElement(line); + int start = elem.getStartOffset(); + int end = elem.getEndOffset() - 1; + + try { + + doc.getText(start, end-start, s); + + // Get the valid chars before the specified offset. + int startOffs = s.offset + (offset-start) - 1; + while (startOffs>=s.offset && isValidChar(s.array[startOffs])) { + startOffs--; + } + + // Get the valid chars at and after the specified offset. + int endOffs = s.offset + (offset-start); + while (endOffs list = getCompletionByInputText(text); + lastCompletionsAtText = text; + return lastParameterizedCompletionsAt = list; + + } catch (BadLocationException ble) { + // Never happens + } + + lastCompletionsAtText = null; + return lastParameterizedCompletionsAt = null; + + } + + + /** + * {@inheritDoc} + */ + public List getParameterizedCompletions( + JTextComponent tc) { + + List list = null; + + // If this provider doesn't support parameterized completions, + // bail out now. + char paramListStart = getParameterListStart(); + if (paramListStart==0) { + return list; // null + } + + int dot = tc.getCaretPosition(); + Segment s = new Segment(); + Document doc = tc.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(dot); + Element elem = root.getElement(line); + int offs = elem.getStartOffset(); + int len = dot - offs - 1/*paramListStart.length()*/; + if (len<=0) { // Not enough chars on line for a method. + return list; // null + } + + try { + + doc.getText(offs, len, s); + + // Get the identifier preceding the '(', ignoring any whitespace + // between them. + offs = s.offset + len - 1; + while (offs>=s.offset && Character.isWhitespace(s.array[offs])) { + offs--; + } + int end = offs; + while (offs>=s.offset && isValidChar(s.array[offs])) { + offs--; + } + + String text = new String(s.array, offs+1, end-offs); + + // Get a list of all Completions matching the text, but then + // narrow it down to just the ParameterizedCompletions. + List l = getCompletionByInputText(text); + if (l!=null && !l.isEmpty()) { + for (int i=0; i(1); + } + list.add((ParameterizedCompletion)o); + } + } + } + + } catch (BadLocationException ble) { + // Never happens + } + + return list; + + } + + + /** + * Initializes this completion provider. + */ + protected void init() { + completions = new ArrayList(); + seg = new Segment(); + } + + + /** + * Returns whether the specified character is valid in an auto-completion. + * The default implementation is equivalent to + * "Character.isLetterOrDigit(ch) || ch=='_'". Subclasses + * can override this method to change what characters are matched. + * + * @param ch The character. + * @return Whether the character is valid. + */ + protected boolean isValidChar(char ch) { + return Character.isLetterOrDigit(ch) || ch=='_'; + } + + + /** + * Loads completions from an XML file. The XML should validate against + * CompletionXml.dtd. + * + * @param file An XML file to load from. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(File file) throws IOException { + BufferedInputStream bin = new BufferedInputStream( + new FileInputStream(file)); + try { + loadFromXML(bin); + } finally { + bin.close(); + } + } + + + /** + * Loads completions from an XML input stream. The XML should validate + * against CompletionXml.dtd. + * + * @param in The input stream to read from. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(InputStream in) throws IOException { + loadFromXML(in, null); + } + + + /** + * Loads completions from an XML input stream. The XML should validate + * against CompletionXml.dtd. + * + * @param in The input stream to read from. + * @param cl The class loader to use when loading any extra classes defined + * in the XML, such as custom {@link FunctionCompletion}s. This + * may be null if the default is to be used, or if no + * custom completions are defined in the XML. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(InputStream in, ClassLoader cl) throws IOException { + + //long start = System.currentTimeMillis(); + + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(true); + CompletionXMLParser handler = new CompletionXMLParser(this, cl); + BufferedInputStream bin = new BufferedInputStream(in); + try { + SAXParser saxParser = factory.newSAXParser(); + saxParser.parse(bin, handler); + List completions = handler.getCompletions(); + addCompletions(completions); + char startChar = handler.getParamStartChar(); + if (startChar!=0) { + char endChar = handler.getParamEndChar(); + String sep = handler.getParamSeparator(); + if (endChar!=0 && sep!=null && sep.length()>0) { // Sanity + setParameterizedCompletionParams(startChar, sep, endChar); + } + } + } catch (SAXException se) { + throw new IOException(se.toString()); + } catch (ParserConfigurationException pce) { + throw new IOException(pce.toString()); + } finally { + //long time = System.currentTimeMillis() - start; + //System.out.println("XML loaded in: " + time + "ms"); + bin.close(); + } + + } + + + /** + * Loads completions from an XML file. The XML should validate against + * CompletionXml.dtd. + * + * @param resource A resource the current ClassLoader can get to. + * @throws IOException If an IO error occurs. + */ + public void loadFromXML(String resource) throws IOException { + ClassLoader cl = getClass().getClassLoader(); + InputStream in = cl.getResourceAsStream(resource); + if (in==null) { + File file = new File(resource); + if (file.isFile()) { + in = new FileInputStream(file); + } + else { + throw new IOException("No such resource: " + resource); + } + } + BufferedInputStream bin = new BufferedInputStream(in); + try { + loadFromXML(bin); + } finally { + bin.close(); + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/DelegatingCellRenderer.java b/designer_base/src/com/fr/design/gui/autocomplete/DelegatingCellRenderer.java new file mode 100644 index 0000000000..8fde180c39 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/DelegatingCellRenderer.java @@ -0,0 +1,94 @@ +/* + * 12/22/2008 + * + * DelegatingCellRenderer.java - A renderer for Completions that will delegate + * to the Completion's provider's renderer, if there is one. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Component; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.ListCellRenderer; + + +/** + * List cell renderer that delegates to a {@link CompletionProvider}'s + * renderer, if it has one. If it doesn't, it calls into a fallback renderer. + * If a fallback renderer isn't specified, it simply renders + * (({@link Completion})value).toString(). + * + * @author Robert Futrell + * @version 1.0 + */ +class DelegatingCellRenderer extends DefaultListCellRenderer { + + /** + * The renderer to fall back on if one isn't specified by a provider. + * This is usually this. + */ + private ListCellRenderer fallback; + + + /** + * Returns the fallback cell renderer. + * + * @return The fallback cell renderer. + * @see #setFallbackCellRenderer(ListCellRenderer) + */ + public ListCellRenderer getFallbackCellRenderer() { + return fallback; + } + + + /** + * {@inheritDoc} + */ + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean selected, boolean hasFocus) { + Completion c = (Completion)value; + CompletionProvider p = c.getProvider(); + ListCellRenderer r = p.getListCellRenderer(); + if (r!=null) { + return r.getListCellRendererComponent(list, value, index, selected, + hasFocus); + } + if (fallback==null) { + return super.getListCellRendererComponent(list, value, index, + selected, hasFocus); + } + return fallback.getListCellRendererComponent(list, value, index, + selected, hasFocus); + } + + + /** + * Sets the fallback cell renderer. + * + * @param fallback The fallback cell renderer. If this is + * null, this will be used. + * @see #getFallbackCellRenderer() + */ + public void setFallbackCellRenderer(ListCellRenderer fallback) { + this.fallback = fallback; + } + + + /** + * {@inheritDoc} + */ + @Override + public void updateUI() { + super.updateUI(); + if ((fallback instanceof JComponent) && fallback!=this) { + ((JComponent)fallback).updateUI(); + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/DescWindowCallback.java b/designer_base/src/com/fr/design/gui/autocomplete/DescWindowCallback.java new file mode 100644 index 0000000000..d668cb7456 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/DescWindowCallback.java @@ -0,0 +1,35 @@ +/* + * 05/11/2012 + * + * Copyright (C) 2012 Robert Futrell + * robert_futrell at users.sourceforge.net + * http://fifesoft.com/rsyntaxtextarea + * + * This library is distributed under a modified BSD license. See the included + * RSTALanguageSupport.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + + +/** + * Passed to {@link ExternalURLHandler}s as a way for them to display a summary + * for a new completion in response to a link event. + * + * @author Robert Futrell + * @version 1.0 + * @see ExternalURLHandler + */ +public interface DescWindowCallback { + + + /** + * Callback allowing a new code completion's description to be displayed + * in the description window. + * + * @param completion The new completion. + * @param anchor The anchor to scroll to, or null if none. + */ + public void showSummaryFor(Completion completion, String anchor); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/EmptyIcon.java b/designer_base/src/com/fr/design/gui/autocomplete/EmptyIcon.java new file mode 100644 index 0000000000..6fbc11b073 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/EmptyIcon.java @@ -0,0 +1,49 @@ +/* + * 04/29/2010 + * + * EmptyIcon.java - The canonical icon that paints nothing. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Component; +import java.awt.Graphics; +import java.io.Serializable; +import javax.swing.Icon; + + +/** + * A standard icon that doesn't paint anything. This can be used when some + * Completions have icons and others don't, to visually align the + * text of all completions. + * + * @author Robert Futrell + * @version 1.0 + */ +public class EmptyIcon implements Icon, Serializable { + + private int size; + + + public EmptyIcon(int size) { + this.size = size; + } + + + public int getIconHeight() { + return size; + } + + + public int getIconWidth() { + return size; + } + + + public void paintIcon(Component c, Graphics g, int x, int y) { + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ExternalURLHandler.java b/designer_base/src/com/fr/design/gui/autocomplete/ExternalURLHandler.java new file mode 100644 index 0000000000..6017e20589 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ExternalURLHandler.java @@ -0,0 +1,46 @@ +/* + * 12/23/2008 + * + * ExternalURLHandler.java - Implementations can be registered as a callback + * to handle the user clicking on external URL's. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import javax.swing.event.HyperlinkEvent; + + +/** + * A callback for when an external URL is clicked in the description window. + * If no handler is installed, and if running in Java 6, the system default + * web browser is used to open the URL. If not running Java 6, nothing will + * happen. If you want browser support for pre-Java 6 JRE's, you will need + * to register one of these callbacks on your {@link AutoCompletion}, and + * open the URL in a web browser yourself.

+ * + * Alternatively, folks implementing robust code completion support for a + * language might install an ExternalURLHandler to handle + * navigating through linked documentation of objects, functions, etc. + * + * @author Robert Futrell + * @version 1.0 + * @see AutoCompletion#setExternalURLHandler(ExternalURLHandler) + */ +public interface ExternalURLHandler { + + + /** + * Called when an external URL is clicked in the description window. + * + * @param e The event containing the hyperlink clicked. + * @param c The completion currently being displayed. + * @param callback Allows you to display new content in the description + * window. + */ + public void urlClicked(HyperlinkEvent e, Completion c, + DescWindowCallback callback); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/FastListUI.java b/designer_base/src/com/fr/design/gui/autocomplete/FastListUI.java new file mode 100644 index 0000000000..b136378667 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/FastListUI.java @@ -0,0 +1,189 @@ +/* + * 04/26/2010 + * + * FastListUI.java - A JList UI implementation that computes the preferred size + * of all cells really fast, to facilitate lists of possibly thousands of items + * rendered with HTML, which is slow with BasicListUI extensions. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.SystemColor; +import javax.swing.JViewport; +import javax.swing.ListCellRenderer; +import javax.swing.ListModel; +import javax.swing.UIManager; +import javax.swing.plaf.basic.BasicListUI; + + +/** + * A custom list UI, used by the completion choices list. If the number of + * completion choices is "large," it does a fast estimate of the preferred + * width and height of list items. This allows HTML renderers to be used (such + * as {@link CompletionCellRenderer}), with thousands of completion choices, + * with no performance penalty. With standard BasicListUI subclasses, this can + * cause very poor performance each time the list is displayed, which + * is bad for lists that are repeatedly hidden and re-displayed, such as + * completion choices. This is all because the calculation to get the + * preferred size of each list item, when it is displayed with HTML, is slow. + * + * @author Robert Futrell + * @version 1.0 + */ +class FastListUI extends BasicListUI { + + /** + * Whether the selection background was overridden (usually because of + * Nimbus) so we know to manually uninstall the color we installed. + */ + private boolean overriddenBackground; + + /** + * Whether the selection foreground was overridden (usually because of + * Nimbus) so we know to manually uninstall the color we installed. + */ + private boolean overriddenForeground; + + /** + * If there are more than this many completions in a single list, this + * UI will estimate the cell width and height needed for each item instead + * of computing it, for performance reasons. + */ + private static final int ESTIMATION_THRESHOLD = 200; + + + private Color determineSelectionBackground() { + Color c = UIManager.getColor("List.selectionBackground"); + if (c==null) { + c = UIManager.getColor("nimbusSelectionBackground"); + if (c==null) { // Not Nimbus, but still need a value - fallback + c = UIManager.getColor("textHighlight"); + if (c==null) { + c = SystemColor.textHighlight; + } + } + } + + // Nimbus unfortunately requires a Color, not a ColorUIResource, for + // the background override to work. This causes this color to "stick" + // even if the LAF is changed to something else later. "c" here may + // actually be a ColorUIResource + return new Color(c.getRGB());//new ColorUIResource(c); + + } + + + private Color determineSelectionForeground() { + Color c = UIManager.getColor("List.selectionForeground"); + if (c==null) { + c = UIManager.getColor("nimbusSelectedText"); + if (c==null) { // Not Nimbus, but still need a value - fallback + c = UIManager.getColor("textHighlightText"); + if (c==null) { + c = SystemColor.textHighlightText; + } + } + } + // Nimbus unfortunately requires Color, not ColorUIResource, and "c" + // may actually be a ColorUIResource + return new Color(c.getRGB()); + } + + + /** + * Overridden to ensure we have selection background/foreground colors + * defined, even if we're in some weirdo LAF such as Nimbus which doesn't + * define them. Since FastListUI extends BasicListUI, we need these values + * to be defined. + */ + @Override + protected void installDefaults() { + + super.installDefaults(); + + if (list.getSelectionBackground()==null) { + list.setSelectionBackground(determineSelectionBackground()); + overriddenBackground = true; + } + + if (list.getSelectionForeground()==null) { + list.setSelectionForeground(determineSelectionForeground()); + overriddenForeground = true; + } + } + + + /** + * Overridden to work around a Nimbus issue. + */ + @Override + protected void uninstallDefaults() { + + super.uninstallDefaults(); + + if (overriddenBackground) { + list.setSelectionBackground(null); + } + + if (overriddenForeground) { + list.setSelectionForeground(null); + } + + } + + + /** + * Recalculates the cell width and height of each cell in the list. This + * method is overridden to do a fast estimation if the completion list is + * too long, to improve performance for lists with huge amounts of + * completions. + */ + @Override + protected void updateLayoutState() { + + ListModel model = list.getModel(); + int itemCount = model.getSize(); + + // If the item count is small enough to run fast on practically all + // machines, go ahead and use the super implementation to determine + // the optimal cell sizes. + if (itemCount0) { + Object value = model.getElementAt(0); + java.awt.Component c = renderer.getListCellRendererComponent(list, + value, 0, false, false); + rendererPane.add(c); + Dimension cellSize = c.getPreferredSize(); + cellHeight = cellSize.height; + cellWidth = Math.max(cellWidth, cellSize.width); + } + else { + cellHeight = 20; + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/FunctionCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/FunctionCompletion.java new file mode 100644 index 0000000000..dbcbfb76a6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/FunctionCompletion.java @@ -0,0 +1,322 @@ +/* + * 12/22/2008 + * + * FunctionCompletion.java - A completion representing a function. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; + + +/** + * A completion choice representing a function. + * + * @author Robert Futrell + * @version 1.0 + */ +public class FunctionCompletion extends VariableCompletion + implements ParameterizedCompletion { + + /** + * Parameters to the function. + */ + private List params; + + /** + * A description of the return value of this function. + */ + private String returnValDesc; + + + /** + * Constructor. + * + * @param provider The parent provider. + * @param name The name of this function. + * @param returnType The return type of this function. + */ + public FunctionCompletion(CompletionProvider provider, String name, + String returnType) { + super(provider, name, returnType); + } + + + @Override + protected void addDefinitionString(StringBuilder sb) { + sb.append(""); + sb.append(getDefinitionString()); + sb.append(""); + } + + + /** + * Adds HTML describing the parameters to this function to a buffer. + * + * @param sb The buffer to append to. + */ + protected void addParameters(StringBuilder sb) { + + // TODO: Localize me + + int paramCount = getParamCount(); + if (paramCount>0) { + sb.append("Parameters:
"); + sb.append("

"); + for (int i=0; i"); + sb.append(param.getName()!=null ? param.getName() : + param.getType()); + sb.append(" "); + String desc = param.getDescription(); + if (desc!=null) { + sb.append(desc); + } + sb.append("
"); + } + sb.append("


"); + } + + if (returnValDesc!=null) { + sb.append("Returns:
"); + sb.append(returnValDesc); + sb.append("


"); + } + + } + + + /** + * Returns the "definition string" for this function completion. For + * example, for the C "printf" function, this would return + * "int printf(const char *, ...)". + * + * @return The definition string. + */ + @Override + public String getDefinitionString() { + + StringBuilder sb = new StringBuilder(); + + // Add the return type if applicable (C macros like NULL have no type). + String type = getType(); + if (type!=null) { + sb.append(type).append(' '); + } + + // Add the item being described's name. + sb.append(getName()); + + // Add parameters for functions. + CompletionProvider provider = getProvider(); + char start = provider.getParameterListStart(); + if (start!=0) { + sb.append(start); + } + for (int i=0; i 2 - + // thanks to Matthew Adereth! + String sep = getProvider().getParameterListSeparator(); + if (i0 ? (dot+firstParamLen) : dot; + info.setInitialSelection(dot, selectionEnd); + info.setTextToInsert(sb.toString()); + return info; + + } + + + /** + * {@inheritDoc} + */ + public Parameter getParam(int index) { + return params.get(index); + } + + + /** + * Returns the number of parameters to this function. + * + * @return The number of parameters to this function. + * @see #getParam(int) + */ + public int getParamCount() { + return params==null ? 0 : params.size(); + } + + + /** + * {@inheritDoc} + */ + public boolean getShowParameterToolTip() { + return true; + } + + + /** + * Returns the text to insert for a parameter. + * + * @param param The parameter. + * @return The text. + */ + private String getParamText(ParameterizedCompletion.Parameter param) { + String text = param.getName(); + if (text==null) { + text = param.getType(); + if (text==null) { // Shouldn't ever happen + text = "arg"; + } + } + return text; + } + + + /** + * Returns the description of the return value of this function. + * + * @return The description, or null if there is none. + * @see #setReturnValueDescription(String) + */ + public String getReturnValueDescription() { + return returnValDesc; + } + + + /** + * {@inheritDoc} + */ + @Override + public String getSummary() { + StringBuilder sb = new StringBuilder(); + addDefinitionString(sb); + if (!possiblyAddDescription(sb)) { + sb.append("


"); + } + addParameters(sb); + possiblyAddDefinedIn(sb); + return sb.toString(); + } + + + /** + * {@inheritDoc} + */ + @Override + public String getToolTipText() { + String text = getSummary(); + if (text==null) { + text = getDefinitionString(); + } + return text; + } + + + /** + * Sets the parameters to this function. + * + * @param params The parameters. This should be a list of + * {@link ParameterizedCompletion.Parameter}s. + * @see #getParam(int) + * @see #getParamCount() + */ + public void setParams(List params) { + if (params!=null) { + // Deep copy so parsing can re-use its array. + this.params = new ArrayList(params); + } + } + + + /** + * Sets the description of the return value of this function. + * + * @param desc The description. + * @see #getReturnValueDescription() + */ + public void setReturnValueDescription(String desc) { + this.returnValDesc = desc; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java b/designer_base/src/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java new file mode 100644 index 0000000000..b9c761446b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/LanguageAwareCompletionProvider.java @@ -0,0 +1,429 @@ +/* + * 01/03/2009 + * + * LanguageAwareCompletionProvider.java - A completion provider that is aware + * of the language it is working with. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.swing.text.JTextComponent; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxDocument; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxUtilities; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.Token; +import com.fr.design.gui.syntax.ui.rtextarea.RTextArea; +import com.fr.design.gui.syntax.ui.rtextarea.ToolTipSupplier; + + +/** + * A completion provider for the C programming language (and other languages + * with similar syntax). This provider simply delegates to another provider, + * depending on whether the caret is in: + * + *
    + *
  • Code (plain text)
  • + *
  • A string
  • + *
  • A comment
  • + *
  • A documentation comment
  • + *
+ * + * This allows for different completion choices in comments than in code, + * for example.

+ * + * This provider also implements the + * org.fife.ui.rtextarea.ToolTipSupplier interface, which allows it + * to display tooltips for completion choices. Thus the standard + * {@link VariableCompletion} and {@link FunctionCompletion} completions should + * be able to display tooltips with the variable declaration or function + * definition (provided the RSyntaxTextArea was registered with the + * javax.swing.ToolTipManager). + * + * @author Robert Futrell + * @version 1.0 + */ +public class LanguageAwareCompletionProvider extends CompletionProviderBase + implements ToolTipSupplier { + + /** + * The provider to use when no provider is assigned to a particular token + * type. + */ + private CompletionProvider defaultProvider; + + /** + * The provider to use when completing in a string. + */ + private CompletionProvider stringCompletionProvider; + + /** + * The provider to use when completing in a comment. + */ + private CompletionProvider commentCompletionProvider; + + /** + * The provider to use while in documentation comments. + */ + private CompletionProvider docCommentCompletionProvider; + + + /** + * Constructor subclasses can use when they don't have their default + * provider created at construction time. They should call + * {@link #setDefaultCompletionProvider(CompletionProvider)} in this + * constructor. + */ + protected LanguageAwareCompletionProvider() { + } + + + /** + * Constructor. + * + * @param defaultProvider The provider to use when no provider is assigned + * to a particular token type. This cannot be null. + */ + public LanguageAwareCompletionProvider(CompletionProvider defaultProvider) { + setDefaultCompletionProvider(defaultProvider); + } + + + /** + * Calling this method will result in an + * {@link UnsupportedOperationException} being thrown. To set the + * parameter completion parameters, do so on the provider returned by + * {@link #getDefaultCompletionProvider()}. + * + * @throws UnsupportedOperationException Always. + * @see #setParameterizedCompletionParams(char, String, char) + */ + @Override + public void clearParameterizedCompletionParams() { + throw new UnsupportedOperationException(); + } + + + /** + * {@inheritDoc} + */ + public String getAlreadyEnteredText(JTextComponent comp) { + if (!(comp instanceof RSyntaxTextArea)) { + return EMPTY_STRING; + } + CompletionProvider provider = getProviderFor(comp); + return provider!=null ? provider.getAlreadyEnteredText(comp) : null; + } + + + /** + * Returns the completion provider to use for comments. + * + * @return The completion provider to use. + * @see #setCommentCompletionProvider(CompletionProvider) + */ + public CompletionProvider getCommentCompletionProvider() { + return commentCompletionProvider; + } + + + /** + * {@inheritDoc} + */ + public List getCompletionsAt(JTextComponent tc, Point p) { + return defaultProvider==null ? null : + defaultProvider.getCompletionsAt(tc, p); + } + + + /** + * Does the dirty work of creating a list of completions. + * + * @param comp The text component to look in. + * @return The list of possible completions, or an empty list if there + * are none. + */ + @Override + protected List getCompletionsImpl(JTextComponent comp) { + if (!(comp instanceof RSyntaxTextArea)) { + return new ArrayList(0); + } + CompletionProvider provider = getProviderFor(comp); + if (provider!=null) { + return provider.getCompletions(comp); + } + return Collections.emptyList(); + } + + + /** + * Returns the completion provider used when one isn't defined for a + * particular token type. + * + * @return The completion provider to use. + * @see #setDefaultCompletionProvider(CompletionProvider) + */ + public CompletionProvider getDefaultCompletionProvider() { + return defaultProvider; + } + + + /** + * Returns the completion provider to use for documentation comments. + * + * @return The completion provider to use. + * @see #setDocCommentCompletionProvider(CompletionProvider) + */ + public CompletionProvider getDocCommentCompletionProvider() { + return docCommentCompletionProvider; + } + + + /** + * {@inheritDoc} + */ + public List getParameterizedCompletions( + JTextComponent tc) { + // Parameterized completions can only come from the "code" completion + // provider. We do not do function/method completions while editing + // strings or comments. + CompletionProvider provider = getProviderFor(tc); + return provider==defaultProvider ? + provider.getParameterizedCompletions(tc) : null; + } + + + /** + * {@inheritDoc} + */ + @Override + public char getParameterListEnd() { + return defaultProvider.getParameterListEnd(); + } + + + /** + * {@inheritDoc} + */ + @Override + public String getParameterListSeparator() { + return defaultProvider.getParameterListSeparator(); + } + + + /** + * {@inheritDoc} + */ + @Override + public char getParameterListStart() { + return defaultProvider.getParameterListStart(); + } + + + /** + * Returns the completion provider to use at the current caret position in + * a text component. + * + * @param comp The text component to check. + * @return The completion provider to use. + */ + private CompletionProvider getProviderFor(JTextComponent comp) { + + RSyntaxTextArea rsta = (RSyntaxTextArea)comp; + RSyntaxDocument doc = (RSyntaxDocument)rsta.getDocument(); + int line = rsta.getCaretLineNumber(); + Token t = doc.getTokenListForLine(line); + if (t==null) { + return getDefaultCompletionProvider(); + } + + int dot = rsta.getCaretPosition(); + Token curToken = RSyntaxUtilities.getTokenAtOffset(t, dot); + + if (curToken==null) { // At end of the line + + int type = doc.getLastTokenTypeOnLine(line); + if (type==Token.NULL) { + Token temp = t.getLastPaintableToken(); + if (temp==null) { + return getDefaultCompletionProvider(); + } + type = temp.getType(); + } + + // TokenMakers can use types < 0 for "internal types." This + // gives them a chance to map their internal types back to "real" + // types to get completion providers. + else if (type<0) { + type = doc.getClosestStandardTokenTypeForInternalType(type); + } + + switch (type) { + case Token.ERROR_STRING_DOUBLE: + return getStringCompletionProvider(); + case Token.COMMENT_EOL: + case Token.COMMENT_MULTILINE: + return getCommentCompletionProvider(); + case Token.COMMENT_DOCUMENTATION: + return getDocCommentCompletionProvider(); + default: + return getDefaultCompletionProvider(); + } + + } + + // FIXME: This isn't always a safe assumption. + if (dot==curToken.getOffset()) { // At the very beginning of a new token + // Need to check previous token for its type before deciding. + // Previous token may also be on previous line! + return getDefaultCompletionProvider(); + } + + switch (curToken.getType()) { + case Token.LITERAL_STRING_DOUBLE_QUOTE: + case Token.ERROR_STRING_DOUBLE: + return getStringCompletionProvider(); + case Token.COMMENT_EOL: + case Token.COMMENT_MULTILINE: + return getCommentCompletionProvider(); + case Token.COMMENT_DOCUMENTATION: + return getDocCommentCompletionProvider(); + case Token.NULL: + case Token.WHITESPACE: + case Token.IDENTIFIER: + case Token.VARIABLE: + case Token.PREPROCESSOR: + case Token.DATA_TYPE: + case Token.FUNCTION: + case Token.OPERATOR: + return getDefaultCompletionProvider(); + } + + return null; // In a token type we can't auto-complete from. + + } + + + /** + * Returns the completion provider to use for strings. + * + * @return The completion provider to use. + * @see #setStringCompletionProvider(CompletionProvider) + */ + public CompletionProvider getStringCompletionProvider() { + return stringCompletionProvider; + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean isAutoActivateOkay(JTextComponent tc) { + CompletionProvider provider = getProviderFor(tc); + return provider!=null ? provider.isAutoActivateOkay(tc) : false; + } + + + /** + * Sets the comment completion provider. + * + * @param provider The provider to use in comments. + * @see #getCommentCompletionProvider() + */ + public void setCommentCompletionProvider(CompletionProvider provider) { + this.commentCompletionProvider = provider; + } + + + /** + * Sets the default completion provider. + * + * @param provider The provider to use when no provider is assigned to a + * particular token type. This cannot be null. + * @see #getDefaultCompletionProvider() + */ + public void setDefaultCompletionProvider(CompletionProvider provider) { + if (provider==null) { + throw new IllegalArgumentException("provider cannot be null"); + } + this.defaultProvider = provider; + } + + + /** + * Sets the documentation comment completion provider. + * + * @param provider The provider to use in comments. + * @see #getDocCommentCompletionProvider() + */ + public void setDocCommentCompletionProvider(CompletionProvider provider) { + this.docCommentCompletionProvider = provider; + } + + + /** + * Calling this method will result in an + * {@link UnsupportedOperationException} being thrown. To set the + * parameter completion parameters, do so on the provider returned by + * {@link #getDefaultCompletionProvider()}. + * + * @throws UnsupportedOperationException Always. + * @see #clearParameterizedCompletionParams() + */ + @Override + public void setParameterizedCompletionParams(char listStart, + String separator, char listEnd) { + throw new UnsupportedOperationException(); + } + + + /** + * Sets the completion provider to use while in a string. + * + * @param provider The provider to use. + * @see #getStringCompletionProvider() + */ + public void setStringCompletionProvider(CompletionProvider provider) { + stringCompletionProvider = provider; + } + + + /** + * Returns the tool tip to display for a mouse event.

+ * + * For this method to be called, the RSyntaxTextArea must be + * registered with the javax.swing.ToolTipManager like so: + * + *

+	 * ToolTipManager.sharedInstance().registerComponent(textArea);
+	 * 
+ * + * @param textArea The text area. + * @param e The mouse event. + * @return The tool tip text, or null if none. + */ + public String getToolTipText(RTextArea textArea, MouseEvent e) { + + String tip = null; + + List completions = getCompletionsAt(textArea, e.getPoint()); + if (completions!=null && completions.size()>0) { + // Only ever 1 match for us in C... + Completion c = completions.get(0); + tip = c.getToolTipText(); + } + + return tip; + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/LinkRedirector.java b/designer_base/src/com/fr/design/gui/autocomplete/LinkRedirector.java new file mode 100644 index 0000000000..9451060ceb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/LinkRedirector.java @@ -0,0 +1,20 @@ +package com.fr.design.gui.autocomplete; + +import java.net.URL; + + +/** + * Possibly redirects one URL to another. Useful if you want "external" URL's + * in code completion documentation to point to a local copy instead, for + * example. + * + * @author Robert Futrell + * @version 1.0 + */ +public interface LinkRedirector { + + + public URL possiblyRedirect(URL original); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/MarkupTagCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/MarkupTagCompletion.java new file mode 100644 index 0000000000..eca4ab8de1 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/MarkupTagCompletion.java @@ -0,0 +1,240 @@ +/* + * 01/06/2009 + * + * MarkupTagComletion.java - A completion representing a tag in markup, such + * as HTML or XML. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.util.ArrayList; +import java.util.List; + +import com.fr.design.gui.autocomplete.ParameterizedCompletion.Parameter; + + +/** + * A completion representing a tag in markup, such as HTML or XML. + * + * @author Robert Futrell + * @version 1.0 + */ +public class MarkupTagCompletion extends AbstractCompletion { + + private String name; + private String desc; + private String definedIn; + + /** + * Attributes of the tag. + */ + private List attrs; + + + /** + * Constructor. + * + * @param provider The parent provider instance. + * @param name The name of the tag. + */ + public MarkupTagCompletion(CompletionProvider provider, String name) { + super(provider); + this.name = name; + } + + + /** + * Adds HTML describing the attributes of this tag to a buffer. + * + * @param sb The buffer to append to. + */ + protected void addAttributes(StringBuilder sb) { + + // TODO: Localize me. + + int attrCount = getAttributeCount(); + if (attrCount>0) { + sb.append("Attributes:
"); + sb.append("
"); + for (int i=0; i"); + sb.append(attr.getName()!=null ? attr.getName() : + attr.getType()); + sb.append(" "); + String desc = attr.getDescription(); + if (desc!=null) { + sb.append(desc); + } + sb.append("
"); + } + sb.append("


"); + } + + } + + + protected void addDefinitionString(StringBuilder sb) { + sb.append("").append(name).append(""); + } + + + /** + * Returns all attributes of this tag. + * + * @return A list of {@link ParameterizedCompletion.Parameter}s. + * @see #getAttribute(int) + * @see #getAttributeCount() + */ + public List getAttributes() { + return attrs; + } + + + /** + * Returns the specified {@link ParameterizedCompletion.Parameter}. + * + * @param index The index of the attribute to retrieve. + * @return The attribute. + * @see #getAttributeCount() + */ + public Parameter getAttribute(int index) { + return attrs.get(index); + } + + + /** + * Returns the number of attributes of this tag. + * + * @return The number of attributes of this tag. + * @see #getAttribute(int) + */ + public int getAttributeCount() { + return attrs==null ? 0 : attrs.size(); + } + + + /** + * Returns where this variable is defined. + * + * @return Where this variable is defined. + * @see #setDefinedIn(String) + */ + public String getDefinedIn() { + return definedIn; + } + + + /** + * Returns a short description of this variable. This should be an + * HTML snippet. + * + * @return A short description of this variable. This may be + * null. + * @see #setDescription(String) + */ + public String getDescription() { + return desc; + } + + + /** + * Returns the name of this tag. + * + * @return The name of this tag. + */ + public String getName() { + return name; + } + + + /** + * {@inheritDoc} + */ + public String getReplacementText() { + return getName(); + } + + + /** + * {@inheritDoc} + */ + public String getSummary() { + StringBuilder sb = new StringBuilder(); + addDefinitionString(sb); + possiblyAddDescription(sb); + addAttributes(sb); + possiblyAddDefinedIn(sb); + return sb.toString(); + } + + + /** + * Adds some HTML describing where this variable is defined, if this + * information is known. + * + * @param sb The buffer to append to. + */ + protected void possiblyAddDefinedIn(StringBuilder sb) { + if (definedIn!=null) { + sb.append("
Defined in:"); // TODO: Localize me + sb.append(" ").append(definedIn).append(""); + } + } + + + /** + * Adds the description text as HTML to a buffer, if a description is + * defined. + * + * @param sb The buffer to append to. + */ + protected void possiblyAddDescription(StringBuilder sb) { + if (desc!=null) { + sb.append("

"); + sb.append(desc); + sb.append("


"); + } + } + + + /** + * Sets where this variable is defined. + * + * @param definedIn Where this variable is defined. + * @see #getDefinedIn() + */ + public void setDefinedIn(String definedIn) { + this.definedIn = definedIn; + } + + + /** + * Sets the short description of this tag. This should be an + * HTML snippet. + * + * @param desc A short description of this tag. This may be + * null. + * @see #getDescription() + */ + public void setDescription(String desc) { + this.desc = desc; + } + + + /** + * Sets the attributes of this tag. + * + * @param attrs The attributes. + * @see #getAttribute(int) + * @see #getAttributeCount() + */ + public void setAttributes(List attrs) { + // Deep copy so parsing can re-use its array. + this.attrs = new ArrayList(attrs); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/OutlineHighlightPainter.java b/designer_base/src/com/fr/design/gui/autocomplete/OutlineHighlightPainter.java new file mode 100644 index 0000000000..e1305d3fe8 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/OutlineHighlightPainter.java @@ -0,0 +1,143 @@ +/* + * 04/26/2009 + * + * OutlineHighlightPainter.java - Highlight painter that draws an outline + * around its text. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import javax.swing.text.View; + + +/** + * Highlight painter that draws an outline around the text. This is used to + * draw bounds around function/method parameters. + * + * @author Robert Futrell + * @version 1.0 + */ +/* + * NOTE: Whenever you see text like "Workaround for Java Highlight issues", + * this is because highlighted text in a JTextComponent gets "pushed" forward + * when the caret is at the Highlight's start, when we need it to instead get + * prepended to. For this reason, the auto-complete package adds its Highlights + * 1 char too long (1 char earlier than where it should really start), but only + * paint the Highlight from the 2nd char on. + */ +class OutlineHighlightPainter extends + DefaultHighlighter.DefaultHighlightPainter { + + /** + * DefaultHighlightPainter doesn't allow changing color, so we must cache + * ours here. + */ + private Color color; + + + /** + * Constructor. + * + * @param color The color to draw the bounding boxes with. This cannot + * be null. + */ + public OutlineHighlightPainter(Color color) { + super(color); + setColor(color); + } + + + /** + * Returns the color to paint bounding boxes with. + * + * @return The color. + * @see #setColor(Color) + */ + @Override + public Color getColor() { + return color; + } + + + /** + * {@inheritDoc} + */ + @Override + public Shape paintLayer(Graphics g, int p0, int p1, Shape viewBounds, + JTextComponent c, View view) { + + g.setColor(getColor()); + p0++; // Workaround for Java Highlight issues. + + // This special case isn't needed for most standard Swing Views (which + // always return a width of 1 for modelToView() calls), but it is + // needed for RSTA views, which actually return the width of chars for + // modelToView calls. But this should be faster anyway, as we + // short-circuit and do only one modelToView() for one offset. + if (p0==p1) { + try { + Shape s = view.modelToView(p0, viewBounds, + Position.Bias.Forward); + Rectangle r = s.getBounds(); + g.drawLine(r.x, r.y, r.x, r.y+r.height); + return r; + } catch (BadLocationException ble) { + // Never happens + return null; + } + } + + if (p0 == view.getStartOffset() && p1 == view.getEndOffset()) { + // Contained in view, can just use bounds. + Rectangle alloc; + if (viewBounds instanceof Rectangle) { + alloc = (Rectangle) viewBounds; + } else { + alloc = viewBounds.getBounds(); + } + g.drawRect(alloc.x, alloc.y, alloc.width - 1, alloc.height - 1); + return alloc; + } + + // Should only render part of View. + try { + // --- determine locations --- + Shape shape = view.modelToView(p0, Position.Bias.Forward, p1, + Position.Bias.Backward, viewBounds); + Rectangle r = (shape instanceof Rectangle) ? (Rectangle) shape + : shape.getBounds(); + g.drawRect(r.x, r.y, r.width - 1, r.height - 1); + return r; + } catch (BadLocationException e) { // Never happens + + return null; + } + + } + + + /** + * Sets the color to paint the bounding boxes with. + * + * @param color The new color. This cannot be null. + * @see #getColor() + */ + public void setColor(Color color) { + if (color==null) { + throw new IllegalArgumentException("color cannot be null"); + } + this.color = color; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ParameterChoicesProvider.java b/designer_base/src/com/fr/design/gui/autocomplete/ParameterChoicesProvider.java new file mode 100644 index 0000000000..be7c3abd6e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ParameterChoicesProvider.java @@ -0,0 +1,40 @@ +/* + * 12/14/2010 + * + * ParameterChoicesProvider.java - Provides completions for a + * ParameterizedCompletion's parameters. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.util.List; +import javax.swing.text.JTextComponent; + + +/** + * Provides completions for a {@link ParameterizedCompletion}'s parameters. + * So, for example, if the user code-completes a function or method, if + * a ParameterChoicesProvider is installed, it can return possible + * completions for the parameters to that function or method. + * + * @author Robert Futrell + * @version 1.0 + */ +public interface ParameterChoicesProvider { + + + /** + * Returns a list of choices for a specific parameter. + * + * @param tc The text component. + * @param param The currently focused parameter. + * @return The list of parameters. This may be null for + * "no parameters," but might also be an empty list. + */ + public List getParameterChoices(JTextComponent tc, + ParameterizedCompletion.Parameter param); + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletion.java new file mode 100644 index 0000000000..d4b2d66854 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletion.java @@ -0,0 +1,172 @@ +/* + * 12/11/2010 + * + * ParameterizedCompletion.java - A completion option. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import javax.swing.text.JTextComponent; + + +/** + * A completion option that takes parameters, such as a function or method. + * + * @author Robert Futrell + * @version 1.0 + */ +public interface ParameterizedCompletion extends Completion { + + + /** + * Returns the "definition string" for this completion. For example, + * for the C "printf" function, this would return + * "int printf(const char *, ...)". + * + * @return The definition string. + */ + public String getDefinitionString(); + + + /** + * Returns the specified {@link Parameter}. + * + * @param index The index of the parameter to retrieve. + * @return The parameter. + * @see #getParamCount() + */ + public Parameter getParam(int index); + + + /** + * Returns the number of parameters this completion takes. + * + * @return The number of parameters this completion takes. + * @see #getParam(int) + */ + public int getParamCount(); + + + public ParameterizedCompletionInsertionInfo getInsertionInfo( + JTextComponent tc, boolean replaceTabsWithSpaces); + + + /** + * Returns whether a tool tip displaying assistance for each parameter + * while it is being edited is appropriate for this completion. + * + * @return Whether the tool tip is appropriate to display. + */ + public boolean getShowParameterToolTip(); + + + /** + * A parameter passed to a parameterized {@link Completion}. + */ + public static class Parameter { + + private String name; + private Object type; + private String desc; + private boolean isEndParam; + + /** + * Constructor. + * + * @param type The type of this parameter. This may be + * null for languages without specific types, + * dynamic typing, etc. Usually you'll pass a String for this + * value, but you may pass any object representing a type in + * your language, as long as its toString() method + * returns a string representation of the type. + * @param name The name of the parameter. + */ + public Parameter(Object type, String name) { + this(type, name, false); + } + + /** + * Constructor. + * + * @param type The type of this parameter. This may be + * null for languages without specific types, + * dynamic typing, etc. Usually you'll pass a String for this + * value, but you may pass any object representing a type in + * your language, as long as its toString() method + * returns a string representation of the type. + * @param name The name of the parameter. + * @param endParam Whether this parameter is an "ending parameter;" + * that is, whether this parameter is at a logical "ending + * point" in the completion text. If the user types in a + * parameter that is an ending point, parameter completion mode + * terminates. Set this to true for a trailing + * parameter after a function call's closing ')', for example. + */ + public Parameter(Object type, String name, boolean endParam) { + this.name = name; + this.type = type; + this.isEndParam = endParam; + } + + public String getDescription() { + return desc; + } + + public String getName() { + return name; + } + + /** + * Returns the type of this parameter, as a string. + * + * @return The type of the parameter, or null for none. + */ + public String getType() { + return type==null ? null : type.toString(); + } + + /** + * Returns the object used to describe the type of this parameter. + * + * @return The type object, or null for none. + */ + public Object getTypeObject() { + return type; + } + + /** + * @return Whether this parameter is an "ending parameter;" + * that is, whether this parameter is at a logical "ending + * point" in the completion text. If the user types in a + * parameter that is an ending point, parameter completion mode + * terminates. + */ + public boolean isEndParam() { + return isEndParam; + } + + public void setDescription(String desc) { + this.desc = desc; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (getType()!=null) { + sb.append(getType()); + } + if (getName()!=null) { + if (getType()!=null) { + sb.append(' '); + } + sb.append(getName()); + } + return sb.toString(); + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionChoicesWindow.java b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionChoicesWindow.java new file mode 100644 index 0000000000..754b312a92 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionChoicesWindow.java @@ -0,0 +1,301 @@ +/* + * 12/11/2010 + * + * ParameterizedCompletionChoicesWindow.java - A list of likely choices for a + * parameter. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator; + +import javax.swing.*; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + + +/** + * A small popup window offering a list of likely choices for a parameter + * when the user has code-completed a parameterized completion. For example, + * if they have just code-completed the C function "fprintf", + * when entering the file name, this popup might display all local variables + * of type "char *". + * + * @author Robert Futrell + * @version 1.0 + */ +public class ParameterizedCompletionChoicesWindow extends JWindow { + + /** + * The parent AutoCompletion instance. + */ + private AutoCompletion ac; + + /** + * The list of completion choices. + */ + private JList list; + + /** + * The currently displayed completion choices. + */ + private DefaultListModel model; + + /** + * A list of lists of choices for each parameter. + */ + private List> choicesListList; + + /** + * The scroll pane containing the list. + */ + private JScrollPane sp; + + /** + * Comparator used to sort completions by their relevance before sorting + * them lexicographically. + */ + private static final Comparator sortByRelevanceComparator = + new SortByRelevanceComparator(); + + + /** + * Constructor. + * + * @param parent The parent window (hosting the text component). + * @param ac The auto-completion instance. + * @param context The completion context. + */ + public ParameterizedCompletionChoicesWindow(Window parent, + AutoCompletion ac, + final ParameterizedCompletionContext context) { + + super(parent); + this.ac = ac; + ComponentOrientation o = ac.getTextComponentOrientation(); + + model = new DefaultListModel(); + list = new JList(model); + if (ac.getParamChoicesRenderer() != null) { + list.setCellRenderer(ac.getParamChoicesRenderer()); + } + list.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + context.insertSelectedChoice(); + } + } + }); + sp = new JScrollPane(list); + + setContentPane(sp); + applyComponentOrientation(o); + setFocusableWindowState(false); + + // Give apps a chance to decorate us with drop shadows, etc. + PopupWindowDecorator decorator = PopupWindowDecorator.get(); + if (decorator != null) { + decorator.decorate(this); + } + + } + + + /** + * Returns the selected value. + * + * @return The selected value, or null if nothing is + * selected. + */ + public String getSelectedChoice() { + Completion c = (Completion) list.getSelectedValue(); + return c == null ? null : c.toString(); + } + + + /** + * Changes the selected index. + * + * @param amount The amount by which to change the selected index. + */ + public void incSelection(int amount) { + int selection = list.getSelectedIndex(); + selection += amount; + if (selection < 0) { + // Account for nothing selected yet + selection = model.getSize() - 1;//+= model.getSize(); + } else { + selection %= model.getSize(); + } + list.setSelectedIndex(selection); + list.ensureIndexIsVisible(selection); + } + + + /** + * Initializes this window to offer suggestions for the parameters of + * a specific completion. + * + * @param pc The completion whose parameters we should offer suggestions + * for. + */ + public void initialize(ParameterizedCompletion pc) { + + CompletionProvider provider = pc.getProvider(); + ParameterChoicesProvider pcp = provider.getParameterChoicesProvider(); + if (pcp == null) { + choicesListList = null; + return; + } + + int paramCount = pc.getParamCount(); + choicesListList = new ArrayList>(paramCount); + JTextComponent tc = ac.getTextComponent(); + + for (int i = 0; i < paramCount; i++) { + ParameterizedCompletion.Parameter param = pc.getParam(i); + List choices = pcp.getParameterChoices(tc, param); + choicesListList.add(choices); + } + + } + + + /** + * Sets the location of this window relative to the given rectangle. + * + * @param r The visual position of the caret (in screen coordinates). + */ + public void setLocationRelativeTo(Rectangle r) { + + // Multi-monitor support - make sure the completion window (and + // description window, if applicable) both fit in the same window in + // a multi-monitor environment. To do this, we decide which monitor + // the rectangle "r" is in, and use that one (just pick top-left corner + // as the defining point). + Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y); + //Dimension screenSize = tooltip.getToolkit().getScreenSize(); + + // Try putting our stuff "below" the caret first. + int y = r.y + r.height + 5; + + // Get x-coordinate of completions. Try to align left edge with the + // caret first. + int x = r.x; + if (x < screenBounds.x) { + x = screenBounds.x; + } else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit + x = screenBounds.x + screenBounds.width - getWidth(); + } + + setLocation(x, y); + + } + + + /** + * Displays the choices for the specified parameter matching the given + * text. This will display or hide this popup window as necessary. + * + * @param param The index of the parameter the caret is currently in. + * This may be -1 if not in a parameter (i.e., on + * the comma between parameters). + * @param prefix Text in the parameter before the dot. This may + * be null to represent the empty string. + */ + public void setParameter(int param, String prefix) { + + model.clear(); + List temp = new ArrayList(); + + if (choicesListList != null && param >= 0 && param < choicesListList.size()) { + + List choices = choicesListList.get(param); + if (choices != null) { + for (Completion c : choices) { + String choice = c.getReplacementText(); + if (prefix == null || Util.startsWithIgnoreCase(choice, prefix)) { + temp.add(c); + } + } + } + + // Sort completions appropriately. + Comparator c = null; + if (/*sortByRelevance*/true) { + c = sortByRelevanceComparator; + } + Collections.sort(temp, c); + for (int i = 0; i < temp.size(); i++) { + model.addElement(temp.get(i)); + } + + int visibleRowCount = Math.min(model.size(), 10); + list.setVisibleRowCount(visibleRowCount); + + // Toggle visibility, if necessary. + if (visibleRowCount == 0 && isVisible()) { + setVisible(false); + } else if (visibleRowCount > 0) { + Dimension size = getPreferredSize(); + if (size.width < 150) { + setSize(150, size.height); + } else { + pack(); + } + // Make sure nothing is ever obscured by vertical scroll bar. + if (sp.getVerticalScrollBar() != null && + sp.getVerticalScrollBar().isVisible()) { + size = getSize(); + int w = size.width + sp.getVerticalScrollBar().getWidth() + 5; + setSize(w, size.height); + } + list.setSelectedIndex(0); + list.ensureIndexIsVisible(0); + if (!isVisible()) { + setVisible(true); + } + } + + } else { + setVisible(false); + } + + } + + + /** + * Toggles the visibility of this popup window. + * + * @param visible Whether this window should be visible. + */ + @Override + public void setVisible(boolean visible) { + if (visible != isVisible()) { + // i.e. if no possibilities matched what's been typed + if (visible && model.size() == 0) {//list.getVisibleRowCount()==0) { + return; + } + super.setVisible(visible); + } + } + + + /** + * Updates the LookAndFeel of this window. + */ + public void updateUI() { + SwingUtilities.updateComponentTreeUI(this); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java new file mode 100644 index 0000000000..62c68dc987 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionContext.java @@ -0,0 +1,1199 @@ +/* + * 06/17/2012 + * + * ParameritizedCompletionContext.java - Manages the state of parameterized + * completion-related UI components during code completion. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.autocomplete.ParameterizedCompletion.Parameter; +import com.fr.design.gui.autocomplete.ParameterizedCompletionInsertionInfo.ReplacementCopy; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.DocumentRange; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea; +import com.fr.design.gui.syntax.ui.rtextarea.ChangeableHighlightPainter; + +import javax.swing.*; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.*; +import javax.swing.text.Highlighter.Highlight; +import javax.swing.text.Highlighter.HighlightPainter; +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import java.util.List; + + +/** + * Manages UI and state specific to parameterized completions - the parameter + * description tool tip, the parameter completion choices list, the actual + * highlights in the editor, etc. This component installs new key bindings + * when appropriate to allow the user to cycle through the parameters of the + * completion, and optionally cycle through completion choices for those + * parameters. + * + * @author Robert Futrell + * @version 1.0 + */ +class ParameterizedCompletionContext { + + /** + * The parent window. + */ + private Window parentWindow; + + /** + * The parent AutoCompletion instance. + */ + private AutoCompletion ac; + + /** + * The completion being described. + */ + private ParameterizedCompletion pc; + + /** + * Whether parameterized completion assistance is active. + */ + private boolean active; + + /** + * A tool tip displaying the currently edited parameter name and type. + */ + private ParameterizedCompletionDescriptionToolTip tip; + + /** + * The painter to paint borders around the variables. + */ + private Highlighter.HighlightPainter p; + + private Highlighter.HighlightPainter endingP; + + private Highlighter.HighlightPainter paramCopyP; + + /** + * The tags for the highlights around parameters. + */ + private List tags; + + private List paramCopyInfos; + + private transient boolean ignoringDocumentEvents; + + /** + * Listens for events in the text component while this window is visible. + */ + private Listener listener; + + /** + * The minimum offset into the document that the caret can move to + * before this tool tip disappears. + */ + private int minPos; + + /** + * The maximum offset into the document that the caret can move to + * before this tool tip disappears. + */ + private Position maxPos; // Moves with text inserted. + + private Position defaultEndOffs; + + /** + * The currently "selected" parameter in the displayed text. + */ + private int lastSelectedParam; + + /** + * A small popup window giving likely choices for parameterized completions. + */ + private ParameterizedCompletionChoicesWindow paramChoicesWindow; + + /** + * The text before the caret for the current parameter. If + * {@link #paramChoicesWindow} is non-null, this is used to + * determine what parameter choices to actually show. + */ + private String paramPrefix; + + private Object oldTabKey; + private Action oldTabAction; + private Object oldShiftTabKey; + private Action oldShiftTabAction; + private Object oldUpKey; + private Action oldUpAction; + private Object oldDownKey; + private Action oldDownAction; + private Object oldEnterKey; + private Action oldEnterAction; + private Object oldEscapeKey; + private Action oldEscapeAction; + private Object oldClosingKey; + private Action oldClosingAction; + + private static final String IM_KEY_TAB = "ParamCompKey.Tab"; + private static final String IM_KEY_SHIFT_TAB = "ParamCompKey.ShiftTab"; + private static final String IM_KEY_UP = "ParamCompKey.Up"; + private static final String IM_KEY_DOWN = "ParamCompKey.Down"; + private static final String IM_KEY_ESCAPE = "ParamCompKey.Escape"; + private static final String IM_KEY_ENTER = "ParamCompKey.Enter"; + private static final String IM_KEY_CLOSING = "ParamCompKey.Closing"; + + + /** + * Constructor. + */ + public ParameterizedCompletionContext(Window owner, + AutoCompletion ac, ParameterizedCompletion pc) { + + this.parentWindow = owner; + this.ac = ac; + this.pc = pc; + listener = new Listener(); + + AutoCompletionStyleContext sc = AutoCompletion.getStyleContext(); + p = new OutlineHighlightPainter(sc.getParameterOutlineColor()); + endingP = new OutlineHighlightPainter( + sc.getParameterizedCompletionCursorPositionColor()); + paramCopyP = new ChangeableHighlightPainter(sc.getParameterCopyColor()); + tags = new ArrayList(1); // Usually small + paramCopyInfos = new ArrayList(1); + + } + + + /** + * Activates parameter completion support. + * + * @see #deactivate() + */ + public void activate() { + + if (active) { + return; + } + + active = true; + JTextComponent tc = ac.getTextComponent(); + lastSelectedParam = -1; + + if (pc.getShowParameterToolTip()) { + tip = new ParameterizedCompletionDescriptionToolTip( + parentWindow, this, ac, pc); + try { + int dot = tc.getCaretPosition(); + Rectangle r = tc.modelToView(dot); + Point p = new Point(r.x, r.y); + SwingUtilities.convertPointToScreen(p, tc); + r.x = p.x; + r.y = p.y; + tip.setLocationRelativeTo(r); + tip.setVisible(true); + } catch (BadLocationException ble) { // Should never happen + UIManager.getLookAndFeel().provideErrorFeedback(tc); + + tip = null; + } + } + + listener.install(tc); + // First time through, we'll need to create this window. + if (paramChoicesWindow == null) { + paramChoicesWindow = createParamChoicesWindow(); + } + lastSelectedParam = getCurrentParameterIndex(); + prepareParamChoicesWindow(); + paramChoicesWindow.setVisible(true); + + } + + + /** + * Creates the completion window offering suggestions for parameters. + * + * @return The window. + */ + private ParameterizedCompletionChoicesWindow createParamChoicesWindow() { + ParameterizedCompletionChoicesWindow pcw = + new ParameterizedCompletionChoicesWindow(parentWindow, + ac, this); + pcw.initialize(pc); + return pcw; + } + + + /** + * Hides any popup windows and terminates parameterized completion + * assistance. + * + * @see #activate() + */ + public void deactivate() { + if (!active) { + return; + } + active = false; + listener.uninstall(); + if (tip != null) { + tip.setVisible(false); + } + if (paramChoicesWindow != null) { + paramChoicesWindow.setVisible(false); + } + } + + + /** + * Returns the text inserted for the parameter containing the specified + * offset. + * + * @param offs The offset into the document. + * @return The text of the parameter containing the offset, or + * null if the offset is not in a parameter. + */ + public String getArgumentText(int offs) { + List paramHighlights = getParameterHighlights(); + if (paramHighlights == null || paramHighlights.size() == 0) { + return null; + } + for (Highlight h : paramHighlights) { + if (offs >= h.getStartOffset() && offs <= h.getEndOffset()) { + int start = h.getStartOffset() + 1; + int len = h.getEndOffset() - start; + JTextComponent tc = ac.getTextComponent(); + Document doc = tc.getDocument(); + try { + return doc.getText(start, len); + } catch (BadLocationException ble) { + UIManager.getLookAndFeel().provideErrorFeedback(tc); + + return null; + } + } + } + return null; + } + + + /** + * Returns the highlight of the current parameter. + * + * @return The current parameter's highlight, or null if + * the caret is not in a parameter's bounds. + * @see #getCurrentParameterStartOffset() + */ + private Highlight getCurrentParameterHighlight() { + + JTextComponent tc = ac.getTextComponent(); + int dot = tc.getCaretPosition(); + if (dot > 0) { + dot--; // Workaround for Java Highlight issues + } + + List paramHighlights = getParameterHighlights(); + for (Highlight h : paramHighlights) { + if (dot >= h.getStartOffset() && dot < h.getEndOffset()) { + return h; + } + } + + return null; + + } + + + private int getCurrentParameterIndex() { + + JTextComponent tc = ac.getTextComponent(); + int dot = tc.getCaretPosition(); + if (dot > 0) { + dot--; // Workaround for Java Highlight issues + } + + List paramHighlights = getParameterHighlights(); + for (int i = 0; i < paramHighlights.size(); i++) { + Highlight h = paramHighlights.get(i); + if (dot >= h.getStartOffset() && dot < h.getEndOffset()) { + return i; + } + } + + return -1; + + } + + + /** + * Returns the starting offset of the current parameter. + * + * @return The current parameter's starting offset, or -1 if + * the caret is not in a parameter's bounds. + * @see #getCurrentParameterHighlight() + */ + private int getCurrentParameterStartOffset() { + Highlight h = getCurrentParameterHighlight(); + return h != null ? h.getStartOffset() + 1 : -1; + } + + + /** + * Returns the highlight from a list that comes "first" in a list. Even + * though most parameter highlights are ordered, sometimes they aren't + * (e.g. the "cursor" parameter in a template completion is always last, + * even though it can be anywhere in the template). + * + * @param highlights The list of highlights. Assumed to be non-empty. + * @return The highlight that comes first in the document. + * @see #getLastHighlight(List) + */ + private static final int getFirstHighlight(List highlights) { + int first = -1; + Highlight firstH = null; + for (int i = 0; i < highlights.size(); i++) { + Highlight h = highlights.get(i); + if (firstH == null || h.getStartOffset() < firstH.getStartOffset()) { + firstH = h; + first = i; + } + } + return first; + } + + + /** + * Returns the highlight from a list that comes "last" in that list. Even + * though most parameter highlights are ordered, sometimes they aren't + * (e.g. the "cursor" parameter in a template completion is always last, + * even though it can be anywhere in the template. + * + * @param highlights The list of highlights. Assumed to be non-empty. + * @return The highlight that comes last in the document. + * @see #getFirstHighlight(List) + */ + private static final int getLastHighlight(List highlights) { + int last = -1; + Highlight lastH = null; + for (int i = highlights.size() - 1; i >= 0; i--) { + Highlight h = highlights.get(i); + if (lastH == null || h.getStartOffset() > lastH.getStartOffset()) { + lastH = h; + last = i; + } + } + return last; + } + + + public List getParameterHighlights() { + List paramHighlights = new ArrayList(2); + JTextComponent tc = ac.getTextComponent(); + Highlight[] highlights = tc.getHighlighter().getHighlights(); + for (int i = 0; i < highlights.length; i++) { + HighlightPainter painter = highlights[i].getPainter(); + if (painter == p || painter == endingP) { + paramHighlights.add(highlights[i]); + } + } + return paramHighlights; + } + + + /** + * Inserts the choice selected in the parameter choices window. + * + * @return Whether the choice was inserted. This will be false + * if the window is not visible, or no choice is selected. + */ + boolean insertSelectedChoice() { + if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) { + String choice = paramChoicesWindow.getSelectedChoice(); + if (choice != null) { + JTextComponent tc = ac.getTextComponent(); + Highlight h = getCurrentParameterHighlight(); + if (h != null) { + // "+1" is a workaround for Java Highlight issues. + tc.setSelectionStart(h.getStartOffset() + 1); + tc.setSelectionEnd(h.getEndOffset()); + tc.replaceSelection(choice); + moveToNextParam(); + } else { + UIManager.getLookAndFeel().provideErrorFeedback(tc); + } + return true; + } + } + return false; + } + + + /** + * Installs key bindings on the text component that facilitate the user + * editing this completion's parameters. + * + * @see #uninstallKeyBindings() + */ + private void installKeyBindings() { + + if (AutoCompletion.getDebug()) { + System.out.println("CompletionContext: Installing keybindings"); + } + + JTextComponent tc = ac.getTextComponent(); + InputMap im = tc.getInputMap(); + ActionMap am = tc.getActionMap(); + + KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0); + oldTabKey = im.get(ks); + im.put(ks, IM_KEY_TAB); + oldTabAction = am.get(IM_KEY_TAB); + am.put(IM_KEY_TAB, new NextParamAction()); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK); + oldShiftTabKey = im.get(ks); + im.put(ks, IM_KEY_SHIFT_TAB); + oldShiftTabAction = am.get(IM_KEY_SHIFT_TAB); + am.put(IM_KEY_SHIFT_TAB, new PrevParamAction()); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0); + oldUpKey = im.get(ks); + im.put(ks, IM_KEY_UP); + oldUpAction = am.get(IM_KEY_UP); + am.put(IM_KEY_UP, new NextChoiceAction(-1, oldUpAction)); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0); + oldDownKey = im.get(ks); + im.put(ks, IM_KEY_DOWN); + oldDownAction = am.get(IM_KEY_DOWN); + am.put(IM_KEY_DOWN, new NextChoiceAction(1, oldDownAction)); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); + oldEnterKey = im.get(ks); + im.put(ks, IM_KEY_ENTER); + oldEnterAction = am.get(IM_KEY_ENTER); + am.put(IM_KEY_ENTER, new GotoEndAction()); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + oldEscapeKey = im.get(ks); + im.put(ks, IM_KEY_ESCAPE); + oldEscapeAction = am.get(IM_KEY_ESCAPE); + am.put(IM_KEY_ESCAPE, new HideAction()); + + char end = pc.getProvider().getParameterListEnd(); + ks = KeyStroke.getKeyStroke(end); + oldClosingKey = im.get(ks); + im.put(ks, IM_KEY_CLOSING); + oldClosingAction = am.get(IM_KEY_CLOSING); + am.put(IM_KEY_CLOSING, new ClosingAction()); + + } + + + /** + * Moves to and selects the next parameter. + * + * @see #moveToPreviousParam() + */ + private void moveToNextParam() { + + JTextComponent tc = ac.getTextComponent(); + int dot = tc.getCaretPosition(); + int tagCount = tags.size(); + if (tagCount == 0) { + tc.setCaretPosition(maxPos.getOffset()); + deactivate(); + } + + Highlight currentNext = null; + int pos = -1; + List highlights = getParameterHighlights(); + for (int i = 0; i < highlights.size(); i++) { + Highlight hl = highlights.get(i); + // Check "< dot", not "<= dot" as OutlineHighlightPainter paints + // starting at one char AFTER the highlight starts, to work around + // Java issue. Thanks to Matthew Adereth! + if (currentNext == null || currentNext.getStartOffset() dot && + hl.getStartOffset() <= currentNext.getStartOffset())) { + currentNext = hl; + pos = i; + } + } + + // No params after caret - go to first one + if (currentNext.getStartOffset() + 1 <= dot) { + int nextIndex = getFirstHighlight(highlights); + currentNext = highlights.get(nextIndex); + pos = 0; + } + + // "+1" is a workaround for Java Highlight issues. + tc.setSelectionStart(currentNext.getStartOffset() + 1); + tc.setSelectionEnd(currentNext.getEndOffset()); + updateToolTipText(pos); + + } + + + /** + * Moves to and selects the previous parameter. + * + * @see #moveToNextParam() + */ + private void moveToPreviousParam() { + + JTextComponent tc = ac.getTextComponent(); + + int tagCount = tags.size(); + if (tagCount == 0) { // Should never happen + tc.setCaretPosition(maxPos.getOffset()); + deactivate(); + } + + int dot = tc.getCaretPosition(); + int selStart = tc.getSelectionStart() - 1; // Workaround for Java Highlight issues. + Highlight currentPrev = null; + int pos = 0; + List highlights = getParameterHighlights(); + + for (int i = 0; i < highlights.size(); i++) { + Highlight h = highlights.get(i); + if (currentPrev == null || currentPrev.getStartOffset() >= dot || + (h.getStartOffset() < selStart && + (h.getStartOffset() > currentPrev.getStartOffset() || + pos == lastSelectedParam))) { + currentPrev = h; + pos = i; + } + } + + // Loop back from param 0 to last param. + int firstIndex = getFirstHighlight(highlights); + //if (pos==0 && lastSelectedParam==0 && highlights.size()>1) { + if (pos == firstIndex && lastSelectedParam == firstIndex && highlights.size() > 1) { + pos = getLastHighlight(highlights); + currentPrev = highlights.get(pos); + // "+1" is a workaround for Java Highlight issues. + tc.setSelectionStart(currentPrev.getStartOffset() + 1); + tc.setSelectionEnd(currentPrev.getEndOffset()); + updateToolTipText(pos); + } else if (currentPrev != null && dot > currentPrev.getStartOffset()) { + // "+1" is a workaround for Java Highlight issues. + tc.setSelectionStart(currentPrev.getStartOffset() + 1); + tc.setSelectionEnd(currentPrev.getEndOffset()); + updateToolTipText(pos); + } else { + tc.setCaretPosition(maxPos.getOffset()); + deactivate(); + } + + } + + + private void possiblyUpdateParamCopies(Document doc) { + + int index = getCurrentParameterIndex(); + // FunctionCompletions add an extra param at end of inserted text + if (index > -1 && index < pc.getParamCount()) { + + // Typing in an "end parameter" => stop parameter assistance. + Parameter param = pc.getParam(index); + if (param.isEndParam()) { + deactivate(); + return; + } + + // Get the current value of the current parameter. + List paramHighlights = getParameterHighlights(); + Highlight h = paramHighlights.get(index); + int start = h.getStartOffset() + 1; // param offsets are offset (!) by 1 + int len = h.getEndOffset() - start; + String replacement = null; + try { + replacement = doc.getText(start, len); + } catch (BadLocationException ble) { + // Never happens + } + + // Replace any param copies tracking this parameter with the + // value of this parameter. + for (ParamCopyInfo pci : paramCopyInfos) { + if (pci.paramName.equals(param.getName())) { + pci.h = replaceHighlightedText(doc, pci.h, replacement); + } + } + + } else { // Probably the "end parameter" for FunctionCompletions. + deactivate(); + } + + } + + + /** + * Updates the optional window listing likely completion choices, + */ + private void prepareParamChoicesWindow() { + + // If this window was set to null, the user pressed Escape to hide it + if (paramChoicesWindow != null) { + + int offs = getCurrentParameterStartOffset(); + if (offs == -1) { + paramChoicesWindow.setVisible(false); + return; + } + + JTextComponent tc = ac.getTextComponent(); + try { + Rectangle r = tc.modelToView(offs); + Point p = new Point(r.x, r.y); + SwingUtilities.convertPointToScreen(p, tc); + r.x = p.x; + r.y = p.y; + paramChoicesWindow.setLocationRelativeTo(r); + } catch (BadLocationException ble) { // Should never happen + UIManager.getLookAndFeel().provideErrorFeedback(tc); + + } + + // Toggles visibility, if necessary. + paramChoicesWindow.setParameter(lastSelectedParam, paramPrefix); + + } + + } + + + /** + * Removes the bounding boxes around parameters. + */ + private void removeParameterHighlights() { + JTextComponent tc = ac.getTextComponent(); + Highlighter h = tc.getHighlighter(); + for (int i = 0; i < tags.size(); i++) { + h.removeHighlight(tags.get(i)); + } + tags.clear(); + for (ParamCopyInfo pci : paramCopyInfos) { + h.removeHighlight(pci.h); + } + paramCopyInfos.clear(); + } + + + /** + * Replaces highlighted text with new text. Takes special care so that + * the highlight stays just around the newly-highlighted text, since + * Swing's Highlight classes are funny about insertions at + * their start offsets. + * + * @param doc The document. + * @param h The highlight whose text to change. + * @param replacement The new text to be in the highlight. + * @return The replacement highlight for h. + */ + private Highlight replaceHighlightedText(Document doc, Highlight h, + String replacement) { + try { + + int start = h.getStartOffset(); + int len = h.getEndOffset() - start; + Highlighter highlighter = ac.getTextComponent().getHighlighter(); + highlighter.removeHighlight(h); + + if (doc instanceof AbstractDocument) { + ((AbstractDocument) doc).replace(start, len, replacement, null); + } else { + doc.remove(start, len); + doc.insertString(start, replacement, null); + } + + int newEnd = start + replacement.length(); + h = (Highlight) highlighter.addHighlight(start, newEnd, paramCopyP); + return h; + + } catch (BadLocationException ble) { + // Never happens + } + + return null; + + } + + + /** + * Removes the key bindings we installed. + * + * @see #installKeyBindings() + */ + private void uninstallKeyBindings() { + + if (AutoCompletion.getDebug()) { + System.out.println("CompletionContext Uninstalling keybindings"); + } + + JTextComponent tc = ac.getTextComponent(); + InputMap im = tc.getInputMap(); + ActionMap am = tc.getActionMap(); + + KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0); + im.put(ks, oldTabKey); + am.put(IM_KEY_TAB, oldTabAction); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_MASK); + im.put(ks, oldShiftTabKey); + am.put(IM_KEY_SHIFT_TAB, oldShiftTabAction); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0); + im.put(ks, oldUpKey); + am.put(IM_KEY_UP, oldUpAction); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0); + im.put(ks, oldDownKey); + am.put(IM_KEY_DOWN, oldDownAction); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); + im.put(ks, oldEnterKey); + am.put(IM_KEY_ENTER, oldEnterAction); + + ks = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); + im.put(ks, oldEscapeKey); + am.put(IM_KEY_ESCAPE, oldEscapeAction); + + char end = pc.getProvider().getParameterListEnd(); + ks = KeyStroke.getKeyStroke(end); + im.put(ks, oldClosingKey); + am.put(IM_KEY_CLOSING, oldClosingAction); + + } + + + /** + * Updates the text in the tool tip to have the current parameter + * displayed in bold. The "current parameter" is determined from the + * current caret position. + * + * @return The "prefix" of text in the caret's parameter before the caret. + */ + private String updateToolTipText() { + + JTextComponent tc = ac.getTextComponent(); + int dot = tc.getSelectionStart(); + int mark = tc.getSelectionEnd(); + int index = -1; + String paramPrefix = null; + + List paramHighlights = getParameterHighlights(); + for (int i = 0; i < paramHighlights.size(); i++) { + Highlight h = paramHighlights.get(i); + // "+1" because of param hack - see OutlineHighlightPainter + int start = h.getStartOffset() + 1; + if (dot >= start && dot <= h.getEndOffset()) { + try { + // All text selected => offer all suggestions, otherwise + // use prefix before selection + if (dot != start || mark != h.getEndOffset()) { + paramPrefix = tc.getText(start, dot - start); + } + } catch (BadLocationException ble) { + + } + index = i; + break; + } + } + + updateToolTipText(index); + return paramPrefix; + + } + + + private void updateToolTipText(int selectedParam) { + if (selectedParam != lastSelectedParam) { + if (tip != null) { + tip.updateText(selectedParam); + } + this.lastSelectedParam = selectedParam; + } + } + + + /** + * Updates the LookAndFeel of all popup windows this context + * manages. + */ + public void updateUI() { + if (tip != null) { + tip.updateUI(); + } + if (paramChoicesWindow != null) { + paramChoicesWindow.updateUI(); + } + } + + + /** + * Called when the user presses Enter while entering parameters. + */ + private class GotoEndAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + + // If the param choices window is visible and something is chosen, + // replace the parameter with it and move to the next one. + if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) { + if (insertSelectedChoice()) { + return; + } + } + + // Otherwise, just move to the end. + deactivate(); + JTextComponent tc = ac.getTextComponent(); + int dot = tc.getCaretPosition(); + if (dot != defaultEndOffs.getOffset()) { + tc.setCaretPosition(defaultEndOffs.getOffset()); + } else { + // oldEnterAction isn't what we're looking for (wrong key) + Action a = getDefaultEnterAction(tc); + if (a != null) { + a.actionPerformed(e); + } else { + tc.replaceSelection("\n"); + } + } + + } + + private Action getDefaultEnterAction(JTextComponent tc) { + ActionMap am = tc.getActionMap(); + return am.get(DefaultEditorKit.insertBreakAction); + } + + } + + + /** + * Called when the user types the character marking the closing of the + * parameter list, such as ')'. + */ + private class ClosingAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + + JTextComponent tc = ac.getTextComponent(); + int dot = tc.getCaretPosition(); + char end = pc.getProvider().getParameterListEnd(); + + // Are they at or past the end of the parameters? + if (dot >= maxPos.getOffset() - 2) { // ">=" for overwrite mode + + // Try to decide if we're closing a paren that is a part + // of the (last) arg being typed. + String text = getArgumentText(dot); + if (text != null) { + char start = pc.getProvider().getParameterListStart(); + int startCount = getCount(text, start); + int endCount = getCount(text, end); + if (startCount > endCount) { // Just closing a paren + tc.replaceSelection(Character.toString(end)); + return; + } + } + //tc.setCaretPosition(maxPos.getOffset()); + tc.setCaretPosition(Math.min(tc.getCaretPosition() + 1, + tc.getDocument().getLength())); + + deactivate(); + + } + + // If not (in the middle of parameters), just insert the paren. + else { + tc.replaceSelection(Character.toString(end)); + } + + } + + public int getCount(String text, char ch) { + int count = 0; + int old = 0; + int pos = 0; + while ((pos = text.indexOf(ch, old)) > -1) { + count++; + old = pos + 1; + } + + return count; + } + + } + + + /** + * Action performed when the user hits the escape key. + */ + private class HideAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + // On first escape press, if the param choices window is visible, + // just remove it, but keep ability to tab through params. If + // param choices window isn't visible, or second escape press, + // exit tabbing through params entirely. + if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) { + paramChoicesWindow.setVisible(false); + paramChoicesWindow = null; + } else { + deactivate(); + } + } + + } + + + /** + * Listens for various events in the text component while this tool tip + * is visible. + */ + private class Listener implements FocusListener, CaretListener, + DocumentListener { + + private boolean markOccurrencesEnabled; + + /** + * Called when the text component's caret moves. + * + * @param e The event. + */ + public void caretUpdate(CaretEvent e) { + if (maxPos == null) { // Sanity check + deactivate(); + return; + } + int dot = e.getDot(); + if (dot < minPos || dot > maxPos.getOffset()) { + deactivate(); + return; + } + paramPrefix = updateToolTipText(); + if (active) { + prepareParamChoicesWindow(); + } + } + + + public void changedUpdate(DocumentEvent e) { + } + + + /** + * Called when the text component gains focus. + * + * @param e The event. + */ + public void focusGained(FocusEvent e) { + // Do nothing + } + + + /** + * Called when the text component loses focus. + * + * @param e The event. + */ + public void focusLost(FocusEvent e) { + deactivate(); + } + + + private void handleDocumentEvent(final DocumentEvent e) { + if (!ignoringDocumentEvents) { + ignoringDocumentEvents = true; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + possiblyUpdateParamCopies(e.getDocument()); + ignoringDocumentEvents = false; + } + }); + } + } + + + public void insertUpdate(DocumentEvent e) { + handleDocumentEvent(e); + } + + + /** + * Installs this listener onto a text component. + * + * @param tc The text component to install onto. + * @see #uninstall() + */ + public void install(JTextComponent tc) { + + boolean replaceTabs = false; + if (tc instanceof RSyntaxTextArea) { + RSyntaxTextArea textArea = (RSyntaxTextArea) tc; + markOccurrencesEnabled = textArea.getMarkOccurrences(); + textArea.setMarkOccurrences(false); + replaceTabs = textArea.getTabsEmulated(); + } + + Highlighter h = tc.getHighlighter(); + + try { + + // Insert the parameter text + ParameterizedCompletionInsertionInfo info = + pc.getInsertionInfo(tc, replaceTabs); + tc.replaceSelection(info.getTextToInsert()); + + // Add highlights around the parameters. + final int replacementCount = info.getReplacementCount(); + for (int i = 0; i < replacementCount; i++) { + DocumentRange dr = info.getReplacementLocation(i); + HighlightPainter painter = i < replacementCount - 1 ? p : endingP; + // "-1" is a workaround for Java Highlight issues. + tags.add(h.addHighlight( + dr.getStartOffset() - 1, dr.getEndOffset(), painter)); + } + for (int i = 0; i < info.getReplacementCopyCount(); i++) { + ReplacementCopy rc = info.getReplacementCopy(i); + paramCopyInfos.add(new ParamCopyInfo(rc.getId(), + (Highlight) h.addHighlight(rc.getStart(), rc.getEnd(), + paramCopyP))); + } + + // Go back and start at the first parameter. + tc.setCaretPosition(info.getSelectionStart()); + if (info.hasSelection()) { + tc.moveCaretPosition(info.getSelectionEnd()); + } + + minPos = info.getMinOffset(); + maxPos = info.getMaxOffset(); + try { + defaultEndOffs = tc.getDocument().createPosition( + info.getDefaultEndOffs()); + } catch (BadLocationException ble) { + // Never happens + } + + // Listen for document events AFTER we insert + tc.getDocument().addDocumentListener(this); + + } catch (BadLocationException ble) { + // Never happens + } + + // Add listeners to the text component, AFTER text insertion. + tc.addCaretListener(this); + tc.addFocusListener(this); + installKeyBindings(); + + } + + + public void removeUpdate(DocumentEvent e) { + handleDocumentEvent(e); + } + + + /** + * Uninstalls this listener from the current text component. + */ + public void uninstall() { + + JTextComponent tc = ac.getTextComponent(); + tc.removeCaretListener(this); + tc.removeFocusListener(this); + tc.getDocument().removeDocumentListener(this); + uninstallKeyBindings(); + + if (markOccurrencesEnabled) { + ((RSyntaxTextArea) tc).setMarkOccurrences(markOccurrencesEnabled); + } + + // Remove WeakReferences in javax.swing.text. + maxPos = null; + minPos = -1; + removeParameterHighlights(); + + } + + + } + + + /** + * Action performed when the user presses the up or down arrow keys and + * the parameter completion choices popup is visible. + */ + private class NextChoiceAction extends AbstractAction { + + private Action oldAction; + private int amount; + + public NextChoiceAction(int amount, Action oldAction) { + this.amount = amount; + this.oldAction = oldAction; + } + + public void actionPerformed(ActionEvent e) { + if (paramChoicesWindow != null && paramChoicesWindow.isVisible()) { + paramChoicesWindow.incSelection(amount); + } else if (oldAction != null) { + oldAction.actionPerformed(e); + } else { + deactivate(); + } + } + + } + + + /** + * Action performed when the user hits the tab key. + */ + private class NextParamAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + moveToNextParam(); + } + + } + + + private static class ParamCopyInfo { + + private String paramName; + private Highlight h; + + public ParamCopyInfo(String paramName, Highlight h) { + this.paramName = paramName; + this.h = h; + } + + } + + + /** + * Action performed when the user hits shift+tab. + */ + private class PrevParamAction extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + moveToPreviousParam(); + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionDescriptionToolTip.java b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionDescriptionToolTip.java new file mode 100644 index 0000000000..dd0c849773 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionDescriptionToolTip.java @@ -0,0 +1,204 @@ +/* + * 12/21/2008 + * + * ParameterizedCompletionDescriptionToolTip.java - A "tool tip" displaying + * information on the function or method currently being entered. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxUtilities; + +import javax.swing.*; +import java.awt.*; + + +/** + * A "tool tip" that displays information on the function or method currently + * being entered. + * + * @author Robert Futrell + * @version 1.0 + */ +class ParameterizedCompletionDescriptionToolTip { + + /** + * The actual tool tip. + */ + private JWindow tooltip; + + /** + * The label that holds the description. + */ + private JLabel descLabel; + + /** + * The completion being described. + */ + private ParameterizedCompletion pc; + + + /** + * Constructor. + * + * @param owner The parent window. + * @param ac The parent auto-completion. + * @param pc The completion being described. + */ + public ParameterizedCompletionDescriptionToolTip(Window owner, + ParameterizedCompletionContext context, + AutoCompletion ac, ParameterizedCompletion pc) { + + tooltip = new JWindow(owner); + + this.pc = pc; + + descLabel = new JLabel(); + descLabel.setBorder(BorderFactory.createCompoundBorder( + TipUtil.getToolTipBorder(), + BorderFactory.createEmptyBorder(2, 5, 2, 5))); + descLabel.setOpaque(true); + descLabel.setBackground(TipUtil.getToolTipBackground()); + // It appears that if a JLabel is set as a content pane directly, when + // using the JDK's opacity API's, it won't paint its background, even + // if label.setOpaque(true) is called. You have to have a container + // underneath it for it to paint its background. Thus, we embed our + // label in a parent JPanel to handle this case. + //tooltip.setContentPane(descLabel); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(descLabel); + tooltip.setContentPane(panel); + + // Give apps a chance to decorate us with drop shadows, etc. + PopupWindowDecorator decorator = PopupWindowDecorator.get(); + if (decorator != null) { + decorator.decorate(tooltip); + } + + updateText(0); + + tooltip.setFocusableWindowState(false); + + } + + + /** + * Returns whether this tool tip is visible. + * + * @return Whether this tool tip is visible. + * @see #setVisible(boolean) + */ + public boolean isVisible() { + return tooltip.isVisible(); + } + + + /** + * Sets the location of this tool tip relative to the given rectangle. + * + * @param r The visual position of the caret (in screen coordinates). + */ + public void setLocationRelativeTo(Rectangle r) { + + // Multi-monitor support - make sure the completion window (and + // description window, if applicable) both fit in the same window in + // a multi-monitor environment. To do this, we decide which monitor + // the rectangle "r" is in, and use that one (just pick top-left corner + // as the defining point). + Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y); + //Dimension screenSize = tooltip.getToolkit().getScreenSize(); + + // Try putting our stuff "above" the caret first. + int y = r.y - 5 - tooltip.getHeight(); + if (y < 0) { + y = r.y + r.height + 5; + } + + // Get x-coordinate of completions. Try to align left edge with the + // caret first. + int x = r.x; + if (x < screenBounds.x) { + x = screenBounds.x; + } else if (x + tooltip.getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit + x = screenBounds.x + screenBounds.width - tooltip.getWidth(); + } + + tooltip.setLocation(x, y); + + } + + + /** + * Toggles the visibility of this tool tip. + * + * @param visible Whether this tool tip should be visible. + * @see #isVisible() + */ + public void setVisible(boolean visible) { + tooltip.setVisible(visible); + } + + + /** + * Updates the text in the tool tip to have the current parameter + * displayed in bold. + * + * @param selectedParam The index of the selected parameter. + * @return Whether the text needed to be updated. + */ + public boolean updateText(int selectedParam) { + + StringBuilder sb = new StringBuilder(""); + int paramCount = pc.getParamCount(); + for (int i = 0; i < paramCount; i++) { + + if (i == selectedParam) { + sb.append(""); + } + + // Some parameter types may have chars in them unfriendly to HTML + // (such as type parameters in Java). We need to take care to + // escape these. + String temp = pc.getParam(i).toString(); + sb.append(RSyntaxUtilities.escapeForHtml(temp, "
", false)); + + if (i == selectedParam) { + sb.append("
"); + } + if (i < paramCount - 1) { + sb.append(pc.getProvider().getParameterListSeparator()); + } + + } + + if (selectedParam >= 0 && selectedParam < paramCount) { + ParameterizedCompletion.Parameter param = + pc.getParam(selectedParam); + String desc = param.getDescription(); + if (desc != null) { + sb.append("
"); + sb.append(desc); + } + } + + descLabel.setText(sb.toString()); + tooltip.pack(); + + return true; + + } + + + /** + * Updates the LookAndFeel of this window and the description + * window. + */ + public void updateUI() { + SwingUtilities.updateComponentTreeUI(tooltip); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionInsertionInfo.java b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionInsertionInfo.java new file mode 100644 index 0000000000..50fb901e51 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ParameterizedCompletionInsertionInfo.java @@ -0,0 +1,251 @@ +/* + * 05/26/2012 + * + * ParameterizedCompletionInsertionInfo.java - Used internally to track the + * changes required for a specific parameterized completion. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.DocumentRange; + +import javax.swing.text.Position; +import java.util.ArrayList; +import java.util.List; + + +/** + * Describes a parameterized completion - what's being inserted, where the + * parameters are in the inserted text, etc. + * + * @author Robert Futrell + * @version 1.0 + */ +class ParameterizedCompletionInsertionInfo { + + private int minOffs; + private Position maxOffs; + private int defaultEnd; + private int selStart; + private int selEnd; + private String textToInsert; + private List replacementLocations; + private List replacementCopies; + + + public ParameterizedCompletionInsertionInfo() { + defaultEnd = -1; + } + + + public void addReplacementCopy(String id, int start, int end) { + if (replacementCopies == null) { + replacementCopies = new ArrayList(1); + } + replacementCopies.add(new ReplacementCopy(id, start, end)); + } + + + /** + * Marks a region of the replacement text as representing a variable name + * or some other construct that the user should replace. + * + * @param start The start offset. + * @param end The end offset. + * @see #getReplacementCount() + * @see #getReplacementLocation(int) + */ + public void addReplacementLocation(int start, int end) { + if (replacementLocations == null) { + replacementLocations = new ArrayList(1); + } + replacementLocations.add(new DocumentRange(start, end)); + } + + + public int getDefaultEndOffs() { + return defaultEnd > -1 ? defaultEnd : getMaxOffset().getOffset(); + } + + + /** + * Returns the maximum offset the caret can move to before being outside + * of the text inserted for this completion. + * + * @return The maximum offset. + * @see #getMinOffset() + */ + public Position getMaxOffset() { + return maxOffs; + } + + + /** + * Returns the minimum offset the caret can move to before being outside + * of the text inserted for this completion. + * + * @return The minimum offset. + * @see #getMaxOffset() + */ + public int getMinOffset() { + return minOffs; + } + + + public int getReplacementCopyCount() { + return replacementCopies == null ? 0 : replacementCopies.size(); + } + + + /** + * Returns the number of replacements in the completion. + * + * @return The number of replacements in the completion. + */ + public int getReplacementCount() { + return replacementLocations == null ? 0 : replacementLocations.size(); + } + + + public ReplacementCopy getReplacementCopy(int index) { + return replacementCopies.get(index); + } + + + /** + * Returns the starting- and ending-offsets of the replacement regions + * in the completion. + * + * @param index The replacement region. + * @return The range in the document of that replacement region. + * @see #getReplacementCount() + */ + public DocumentRange getReplacementLocation(int index) { + return replacementLocations.get(index); + } + + + /** + * Returns the offset that should be the end of the initially selected + * text when the completion is inserted (i.e., the end offset of the first + * replacement region). + * + * @return The end offset for the initial selection. + * @see #getSelectionStart() + */ + public int getSelectionEnd() { + return selEnd; + } + + + /** + * Returns the offset that should be the start of the initially selected + * text when the completion is inserted (i.e., the start offset of the + * first replacement region). + * + * @return The start offset for the initial selection. + * @see #getSelectionEnd() + */ + public int getSelectionStart() { + return selStart; + } + + + /** + * Returns the actual text to insert when the completion is selected. + * + * @return The text to insert. + * @see #setTextToInsert(String) + */ + public String getTextToInsert() { + return textToInsert; + } + + + /** + * Returns whether or not there is an initial selected region for the + * completion (i.e., whether the completion actually has any parameters). + * + * @return Whether there is a region to initially select for the completion. + */ + public boolean hasSelection() { + return selEnd != selStart; + } + + + /** + * Sets the initially selected region for the completion. + * + * @param selStart The selection start. + * @param selEnd The selection end. + * @see #getSelectionEnd() + * @see #getSelectionStart() + */ + public void setInitialSelection(int selStart, int selEnd) { + this.selStart = selStart; + this.selEnd = selEnd; + } + + + /** + * Sets the document range the caret can move around in before being + * outside of the text inserted for the completion. + * + * @param minOffs The minimum offset. + * @param maxOffs The maximum offset, that will track its location as the + * document is modified. + * @see #getMinOffset() + * @see #getMaxOffset() + */ + public void setCaretRange(int minOffs, Position maxOffs) { + this.minOffs = minOffs; + this.maxOffs = maxOffs; + } + + + public void setDefaultEndOffs(int end) { + defaultEnd = end; + } + + + /** + * Sets the text to insert for the completion. + * + * @param text The text to insert. + * @see #getTextToInsert() + */ + public void setTextToInsert(String text) { + this.textToInsert = text; + } + + + public static class ReplacementCopy { + + private String id; + private int start; + private int end; + + public ReplacementCopy(String id, int start, int end) { + this.id = id; + this.start = start; + this.end = end; + } + + public int getEnd() { + return end; + } + + public String getId() { + return id; + } + + public int getStart() { + return start; + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/ShorthandCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/ShorthandCompletion.java new file mode 100644 index 0000000000..3d2ef55fa5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/ShorthandCompletion.java @@ -0,0 +1,117 @@ +/* + * 12/22/2008 + * + * ShorhandCompletion.java - A completion that is shorthand for some other + * text. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + + +/** + * A completion where the input text is shorthand for (really, just different + * than) the actual text to be inserted. For example, the input text + * "sysout" could be associated with the completion + * "System.out.println(" in Java. + * + * @author Robert Futrell + * @version 1.0 + */ +public class ShorthandCompletion extends BasicCompletion { + + /** + * The text the user can start typing that will match this completion. + */ + private String inputText; + + + /** + * Constructor. + * + * @param provider The provider that returns this completion. + * @param inputText The text the user inputs to get this completion. + * @param replacementText The replacement text of the completion. + */ + public ShorthandCompletion(CompletionProvider provider, String inputText, + String replacementText) { + super(provider, replacementText); + this.inputText = inputText; + } + + + /** + * Constructor. + * + * @param provider The provider that returns this completion. + * @param inputText The text the user inputs to get this completion. + * @param replacementText The replacement text of the completion. + * @param shortDesc A short description of the completion. This will be + * displayed in the completion list. This may be null. + */ + public ShorthandCompletion(CompletionProvider provider, String inputText, + String replacementText, String shortDesc) { + super(provider, replacementText, shortDesc); + this.inputText = inputText; + } + + + /** + * Constructor. + * + * @param provider The provider that returns this completion. + * @param inputText The text the user inputs to get this completion. + * @param replacementText The replacement text of the completion. + * @param shortDesc A short description of the completion. This will be + * displayed in the completion list. This may be null. + * @param summary The summary of this completion. This should be HTML. + * This may be null. + */ + public ShorthandCompletion(CompletionProvider provider, String inputText, + String replacementText, String shortDesc, String summary) { + super(provider, replacementText, shortDesc, summary); + this.inputText = inputText; + } + + + /** + * Returns the text the user must start typing to get this completion. + * + * @return The text the user must start to input. + */ + @Override + public String getInputText() { + return inputText; + } + + + /** + * If a summary has been set, that summary is returned. Otherwise, the + * replacement text is returned. + * + * @return A description of this completion (the text that will be + * inserted). + * @see #getReplacementText() + */ + @Override + public String getSummary() { + String summary = super.getSummary(); + return summary!=null ? summary : ("" + getSummaryBody()); + } + + + /** + * Returns the "body" of the HTML returned by {@link #getSummary()} when + * no summary text has been set. This is defined to return the replacement + * text in a monospaced font. + * + * @return The summary text's body, if no other summary has been defined. + * @see #getReplacementText() + */ + protected String getSummaryBody() { + return "" + getReplacementText(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/SizeGrip.java b/designer_base/src/com/fr/design/gui/autocomplete/SizeGrip.java new file mode 100644 index 0000000000..67e0cff979 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/SizeGrip.java @@ -0,0 +1,256 @@ +/* + * 12/23/2008 + * + * SizeGrip.java - A size grip component that sits at the bottom of the window, + * allowing the user to easily resize that window. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Color; +import java.awt.ComponentOrientation; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import javax.imageio.ImageIO; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.MouseInputAdapter; + + +/** + * A component that allows its parent window to be resizable, similar to the + * size grip seen on status bars. This is essentially a copy of the class with + * the same name in RSyntaxTextArea, but is duplicated to prevent a dependency + * on that library. + * + * @author Robert Futrell + * @version 1.0 + */ +class SizeGrip extends JPanel { + + /** + * The size grip to use if we're on OS X. + */ + private Image osxSizeGrip; + + + public SizeGrip() { + MouseHandler adapter = new MouseHandler(); + addMouseListener(adapter); + addMouseMotionListener(adapter); + setPreferredSize(new Dimension(16, 16)); + } + + + /** + * Overridden to ensure that the cursor for this component is appropriate + * for the orientation. + * + * @param o The new orientation. + */ + @Override + public void applyComponentOrientation(ComponentOrientation o) { + possiblyFixCursor(o.isLeftToRight()); + super.applyComponentOrientation(o); + } + + + /** + * Creates and returns the OS X size grip image. + * + * @return The OS X size grip. + */ + private Image createOSXSizeGrip() { + ClassLoader cl = getClass().getClassLoader(); + URL url = cl.getResource("org/fife/ui/autocomplete/osx_sizegrip.png"); + if (url==null) { + // We're not running in a jar - we may be debugging in Eclipse, + // for example + File f = new File("../AutoComplete/src/org/fife/ui/autocomplete/osx_sizegrip.png"); + if (f.isFile()) { + try { + url = f.toURI().toURL(); + } catch (MalformedURLException mue) { // Never happens + return null; + } + } + else { + return null; // Can't find resource or image file + } + } + Image image = null; + try { + image = ImageIO.read(url); + } catch (IOException ioe) { // Never happens + + } + return image; + } + + + /** + * Paints this panel. + * + * @param g The graphics context. + */ + @Override + protected void paintComponent(Graphics g) { + + super.paintComponent(g); + + Dimension dim = getSize(); + + if (osxSizeGrip!=null) { + g.drawImage(osxSizeGrip, dim.width-16, dim.height-16, null); + return; + } + + Color c1 = UIManager.getColor("Label.disabledShadow"); + Color c2 = UIManager.getColor("Label.disabledForeground"); + ComponentOrientation orientation = getComponentOrientation(); + + if (orientation.isLeftToRight()) { + int width = dim.width -= 3; + int height = dim.height -= 3; + g.setColor(c1); + g.fillRect(width-9,height-1, 3,3); + g.fillRect(width-5,height-1, 3,3); + g.fillRect(width-1,height-1, 3,3); + g.fillRect(width-5,height-5, 3,3); + g.fillRect(width-1,height-5, 3,3); + g.fillRect(width-1,height-9, 3,3); + g.setColor(c2); + g.fillRect(width-9,height-1, 2,2); + g.fillRect(width-5,height-1, 2,2); + g.fillRect(width-1,height-1, 2,2); + g.fillRect(width-5,height-5, 2,2); + g.fillRect(width-1,height-5, 2,2); + g.fillRect(width-1,height-9, 2,2); + } + else { + int height = dim.height -= 3; + g.setColor(c1); + g.fillRect(10,height-1, 3,3); + g.fillRect(6,height-1, 3,3); + g.fillRect(2,height-1, 3,3); + g.fillRect(6,height-5, 3,3); + g.fillRect(2,height-5, 3,3); + g.fillRect(2,height-9, 3,3); + g.setColor(c2); + g.fillRect(10,height-1, 2,2); + g.fillRect(6,height-1, 2,2); + g.fillRect(2,height-1, 2,2); + g.fillRect(6,height-5, 2,2); + g.fillRect(2,height-5, 2,2); + g.fillRect(2,height-9, 2,2); + } + + } + + + /** + * Ensures that the cursor for this component is appropriate for the + * orientation. + * + * @param ltr Whether the current component orientation is LTR. + */ + protected void possiblyFixCursor(boolean ltr) { + int cursor = Cursor.NE_RESIZE_CURSOR; + if (ltr) { + cursor = Cursor.NW_RESIZE_CURSOR; + } + if (cursor!=getCursor().getType()) { + setCursor(Cursor.getPredefinedCursor(cursor)); + } + } + + + @Override + public void updateUI() { + super.updateUI(); + // TODO: Key off of Aqua LaF, not just OS X, as this size grip looks + // bad on other LaFs on Mac such as Nimbus. + if (System.getProperty("os.name").contains("OS X")) { + if (osxSizeGrip==null) { + osxSizeGrip = createOSXSizeGrip(); + } + } + else { // Clear memory in case of runtime LaF change. + osxSizeGrip = null; + } + + } + + + /** + * Listens for mouse events on this panel and resizes the parent window + * appropriately. + */ + /* + * NOTE: We use SwingUtilities.convertPointToScreen() instead of just using + * the locations relative to the corner component because the latter proved + * buggy - stretch the window too wide and some kind of arithmetic error + * started happening somewhere - our window would grow way too large. + */ + private class MouseHandler extends MouseInputAdapter { + + private Point origPos; + + @Override + public void mouseDragged(MouseEvent e) { + Point newPos = e.getPoint(); + SwingUtilities.convertPointToScreen(newPos, SizeGrip.this); + int xDelta = newPos.x - origPos.x; + int yDelta = newPos.y - origPos.y; + Window wind = SwingUtilities.getWindowAncestor(SizeGrip.this); + if (wind!=null) { // Should always be true + if (getComponentOrientation().isLeftToRight()) { + int w = wind.getWidth(); + if (newPos.x>=wind.getX()) { + w += xDelta; + } + int h = wind.getHeight(); + if (newPos.y>=wind.getY()) { + h += yDelta; + } + wind.setSize(w,h); + } + else { // RTL + int newW = Math.max(1, wind.getWidth()-xDelta); + int newH = Math.max(1, wind.getHeight()+yDelta); + wind.setBounds(newPos.x, wind.getY(), newW, newH); + } + // invalidate()/validate() needed pre-1.6. + wind.invalidate(); + wind.validate(); + } + origPos.setLocation(newPos); + } + + @Override + public void mousePressed(MouseEvent e) { + origPos = e.getPoint(); + SwingUtilities.convertPointToScreen(origPos, SizeGrip.this); + } + + @Override + public void mouseReleased(MouseEvent e) { + origPos = null; + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/SortByRelevanceComparator.java b/designer_base/src/com/fr/design/gui/autocomplete/SortByRelevanceComparator.java new file mode 100644 index 0000000000..f14815f9ca --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/SortByRelevanceComparator.java @@ -0,0 +1,33 @@ +/* + * 12/17/2010 + * + * SortByRelevanceComparator.java - Sorts two Completions by relevance before + * sorting them lexicographically. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.util.Comparator; + + +/** + * Compares two Completions by their relevance before + * sorting them lexicographically. + * + * @author Robert Futrell + * @version 1.0 + */ +public class SortByRelevanceComparator implements Comparator { + + + public int compare(Completion c1, Completion c2) { + int rel1 = c1.getRelevance(); + int rel2 = c2.getRelevance(); + int diff = rel2 - rel1;//rel1 - rel2; + return diff==0 ? c1.compareTo(c2) : diff; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/TemplateCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/TemplateCompletion.java new file mode 100644 index 0000000000..99872e4f76 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/TemplateCompletion.java @@ -0,0 +1,363 @@ +/* + * 05/26/2012 + * + * TemplateCompletion.java - A completion used to insert boilerplate code + * snippets that have arbitrary sections the user will want to change, such as + * for-loops. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import com.fr.design.gui.autocomplete.TemplatePiece.Param; +import com.fr.design.gui.autocomplete.TemplatePiece.ParamCopy; +import com.fr.design.gui.autocomplete.TemplatePiece.Text; +import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxUtilities; + +import javax.swing.text.*; +import java.util.ArrayList; +import java.util.List; + + +/** + * A completion made up of a template with arbitrary parameters that the user + * can tab through and fill in. This completion type is useful for inserting + * common boilerplate code, such as for-loops.

+ *

+ * The format of a template is similar to those in Eclipse. The following + * example would be the format for a for-loop template: + *

+ *

+ * for (int ${i} = 0; ${i} < ${array}.length; ${i}++) {
+ *    ${cursor}
+ * }
+ * 
+ *

+ * In the above example, the first ${i} is a parameter for the + * user to type into; all the other ${i} instances are + * automatically changed to what the user types in the first one. The parameter + * named ${cursor} is the "ending position" of the template. It's + * where the caret moves after it cycles through all other parameters. If the + * user types into it, template mode terminates. If more than one + * ${cursor} parameter is specified, behavior is undefined.

+ *

+ * Two dollar signs in a row ("$$") will be evaluated as a single + * dollar sign. Otherwise, the template parsing is pretty straightforward and + * fault-tolerant.

+ *

+ * Leading whitespace is automatically added to lines if the template spans + * more than one line, and if used with a text component using a + * PlainDocument, tabs will be converted to spaces if requested. + * + * @author Robert Futrell + * @version 1.0 + */ +public class TemplateCompletion extends AbstractCompletion + implements ParameterizedCompletion { + + private List pieces; + + private String inputText; + + private String definitionString; + + private String shortDescription; + + private String summary; + + /** + * The template's parameters. + */ + private List params; + + + public TemplateCompletion(CompletionProvider provider, + String inputText, String definitionString, String template) { + this(provider, inputText, definitionString, template, null, null); + } + + + public TemplateCompletion(CompletionProvider provider, + String inputText, String definitionString, String template, + String shortDescription, String summary) { + super(provider); + this.inputText = inputText; + this.definitionString = definitionString; + this.shortDescription = shortDescription; + this.summary = summary; + pieces = new ArrayList(3); + params = new ArrayList(3); + parse(template); + } + + + private void addTemplatePiece(TemplatePiece piece) { + pieces.add(piece); + if (piece instanceof Param && !"cursor".equals(piece.getText())) { + final String type = null; // TODO + Parameter param = new Parameter(type, piece.getText()); + params.add(param); + } + } + + + @Override + public String getInputText() { + return inputText; + } + + + private String getPieceText(int index, String leadingWS) { + TemplatePiece piece = pieces.get(index); + String text = piece.getText(); + if (text.indexOf('\n') > -1) { + text = text.replaceAll("\n", "\n" + leadingWS); + } + return text; + } + + + /** + * Returns null; template completions insert all of their + * text via getInsertionInfo(). + * + * @return null always. + */ + public String getReplacementText() { + return null; + } + + + public String getSummary() { + return summary; + } + + + public String getDefinitionString() { + return definitionString; + } + + public String getShortDescription() { + return shortDescription; + } + + + /** + * {@inheritDoc} + */ + public boolean getShowParameterToolTip() { + return false; + } + + + public ParameterizedCompletionInsertionInfo getInsertionInfo( + JTextComponent tc, boolean replaceTabsWithSpaces) { + + ParameterizedCompletionInsertionInfo info = + new ParameterizedCompletionInsertionInfo(); + + StringBuilder sb = new StringBuilder(); + int dot = tc.getCaretPosition(); + + // Get the range in which the caret can move before we hide + // this tool tip. + int minPos = dot; + Position maxPos = null; + int defaultEndOffs = -1; + try { + maxPos = tc.getDocument().createPosition(dot); + } catch (BadLocationException ble) { + // Never happens + } + info.setCaretRange(minPos, maxPos); + int selStart = dot; // Default value + int selEnd = selStart; + + Document doc = tc.getDocument(); + String leadingWS = null; + try { + leadingWS = RSyntaxUtilities.getLeadingWhitespace(doc, dot); + } catch (BadLocationException ble) { // Never happens + + leadingWS = ""; + } + + // Create the text to insert (keep it one completion for + // performance and simplicity of undo/redo). + int start = dot; + for (int i = 0; i < pieces.size(); i++) { + TemplatePiece piece = pieces.get(i); + String text = getPieceText(i, leadingWS); + if (piece instanceof Text) { + if (replaceTabsWithSpaces) { + start = possiblyReplaceTabsWithSpaces(sb, text, tc, start); + } else { + sb.append(text); + start += text.length(); + } + } else if (piece instanceof Param && "cursor".equals(text)) { + defaultEndOffs = start; + } else { + int end = start + text.length(); + sb.append(text); + if (piece instanceof Param) { + info.addReplacementLocation(start, end); + if (selStart == dot) { + selStart = start; + selEnd = selStart + text.length(); + } + } else if (piece instanceof ParamCopy) { + info.addReplacementCopy(piece.getText(), start, end); + } + start = end; + } + } + + // Highlight the first parameter. If no params were specified, move + // the caret to the ${cursor} location, if specified + if (selStart == minPos && selStart == selEnd && getParamCount() == 0) { + if (defaultEndOffs > -1) { // ${cursor} specified + selStart = selEnd = defaultEndOffs; + } + } + info.setInitialSelection(selStart, selEnd); + + if (defaultEndOffs > -1) { + // Keep this location "after" all others when tabbing + info.addReplacementLocation(defaultEndOffs, defaultEndOffs); + } + info.setDefaultEndOffs(defaultEndOffs); + info.setTextToInsert(sb.toString()); + + return info; + + } + + + /** + * {@inheritDoc} + */ + public Parameter getParam(int index) { + return params.get(index); + } + + + /** + * {@inheritDoc} + */ + public int getParamCount() { + return params == null ? 0 : params.size(); + } + + + /** + * Returns whether a parameter is already defined with a specific name. + * + * @param name The name. + * @return Whether a parameter is defined with that name. + */ + private boolean isParamDefined(String name) { + for (int i = 0; i < getParamCount(); i++) { + Parameter param = getParam(i); + if (name.equals(param.getName())) { + return true; + } + } + return false; + } + + + /** + * Parses a template string into logical pieces used by this class. + * + * @param template The template to parse. + */ + private void parse(String template) { + + int offs = 0; + int lastOffs = 0; + + while ((offs = template.indexOf('$', lastOffs)) > -1 && offs < template.length() - 1) { + + char next = template.charAt(offs + 1); + switch (next) { + case '$': // "$$" => escaped single dollar sign + addTemplatePiece(new TemplatePiece.Text( + template.substring(lastOffs, offs + 1))); + lastOffs = offs += 2; + break; + case '{': // "${...}" => variable + int closingCurly = template.indexOf('}', offs + 2); + if (closingCurly > -1) { + addTemplatePiece(new TemplatePiece.Text( + template.substring(lastOffs, offs))); + String varName = template.substring(offs + 2, closingCurly); + if (!"cursor".equals(varName) && isParamDefined(varName)) { + addTemplatePiece(new TemplatePiece.ParamCopy(varName)); + } else { + addTemplatePiece(new TemplatePiece.Param(varName)); + } + lastOffs = offs = closingCurly + 1; + } + break; + } + + } + + if (lastOffs < template.length()) { + String text = template.substring(lastOffs); + addTemplatePiece(new TemplatePiece.Text(text)); + } + + } + + + private int possiblyReplaceTabsWithSpaces(StringBuilder sb, String text, + JTextComponent tc, int start) { + + int tab = text.indexOf('\t'); + if (tab > -1) { + + int startLen = sb.length(); + + int size = 4; + Document doc = tc.getDocument(); + if (doc != null) { + Integer i = (Integer) doc.getProperty(PlainDocument.tabSizeAttribute); + if (i != null) { + size = i.intValue(); + } + } + String tabStr = ""; + for (int i = 0; i < size; i++) { + tabStr += " "; + } + + int lastOffs = 0; + do { + sb.append(text.substring(lastOffs, tab)); + sb.append(tabStr); + lastOffs = tab + 1; + } while ((tab = text.indexOf('\t', lastOffs)) > -1); + sb.append(text.substring(lastOffs)); + + start += sb.length() - startLen; + + } else { + sb.append(text); + start += text.length(); + } + + return start; + + } + + + @Override + public String toString() { + return getDefinitionString(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/TemplatePiece.java b/designer_base/src/com/fr/design/gui/autocomplete/TemplatePiece.java new file mode 100644 index 0000000000..5414a331b6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/TemplatePiece.java @@ -0,0 +1,86 @@ +/* + * 06/17/2012 + * + * TemplatePiece.java - A logical piece of a template completion. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + + +/** + * A piece of a TemplateCompletion. You add instances of this + * class to template completions to define them. + * + * @author Robert Futrell + * @version 1.0 + * @see TemplateCompletion + */ +interface TemplatePiece { + + + String getText(); + + + public class Text implements TemplatePiece { + + private String text; + + public Text(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + @Override + public String toString() { + return "[TemplatePiece.Text: text=" + text + "]"; + } + + } + + + public class Param implements TemplatePiece { + + String text; + + public Param(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + @Override + public String toString() { + return "[TemplatePiece.Param: param=" + text + "]"; + } + + } + + + public class ParamCopy implements TemplatePiece { + + private String text; + + public ParamCopy(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + @Override + public String toString() { + return "[TemplatePiece.ParamCopy: param=" + text + "]"; + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/TipUtil.java b/designer_base/src/com/fr/design/gui/autocomplete/TipUtil.java new file mode 100644 index 0000000000..bb8f32469d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/TipUtil.java @@ -0,0 +1,179 @@ +/* + * 08/13/2009 + * + * TipUtil.java - Utility methods for homemade tool tips. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import java.awt.Color; +import java.awt.Font; +import java.awt.SystemColor; +import java.net.URL; +import javax.swing.BorderFactory; +import javax.swing.JEditorPane; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.plaf.ColorUIResource; +import javax.swing.text.html.HTMLDocument; + + +/** + * Static utility methods for homemade tool tips.

+ * + * This is blatantly ripped off from RSyntaxTextArea's "FocusableTips" class + * of the same name, but isn't re-used to prevent a hard dependency on the + * RSTA library. + * + * @author Robert Futrell + * @version 1.0 + */ +class TipUtil { + + + private TipUtil() { + } + + + /** + * Returns the default background color to use for tool tip windows. + * + * @return The default background color. + */ + public static Color getToolTipBackground() { + + Color c = UIManager.getColor("ToolTip.background"); + + // Tooltip.background is wrong color on Nimbus (!) + boolean isNimbus = isNimbusLookAndFeel(); + if (c==null || isNimbus) { + c = UIManager.getColor("info"); // Used by Nimbus (and others) + if (c==null || (isNimbus && isDerivedColor(c))) { + c = SystemColor.info; // System default + } + } + + // Workaround for a bug (?) with Nimbus - calling JLabel.setBackground() + // with a ColorUIResource does nothing, must be a normal Color + if (c instanceof ColorUIResource) { + c = new Color(c.getRGB()); + } + + return c; + + } + + + /** + * Returns the border used by tool tips in this look and feel. + * + * @return The border. + */ + public static Border getToolTipBorder() { + + Border border = UIManager.getBorder("ToolTip.border"); + + if (border==null || isNimbusLookAndFeel()) { + border = UIManager.getBorder("nimbusBorder"); + if (border==null) { + border = BorderFactory.createLineBorder(SystemColor.controlDkShadow); + } + } + + return border; + + } + + + /** + * Returns whether a color is a Nimbus DerivedColor, which is troublesome + * in that it doesn't use its RGB values (uses HSB instead?) and so + * querying them is useless. + * + * @param c The color to check. + * @return Whether it is a DerivedColor + */ + private static final boolean isDerivedColor(Color c) { + return c!=null && (c.getClass().getName().endsWith(".DerivedColor") || + c.getClass().getName().endsWith(".DerivedColor$UIResource")); + } + + + /** + * Returns whether the Nimbus Look and Feel is installed. + * + * @return Whether the current LAF is Nimbus. + */ + private static final boolean isNimbusLookAndFeel() { + return UIManager.getLookAndFeel().getName().equals("Nimbus"); + } + + + /** + * Tweaks a JEditorPane so it can be used to render the + * content in a focusable pseudo-tool tip. It is assumed that the editor + * pane is using an HTMLDocument. + * + * @param textArea The editor pane to tweak. + */ + public static void tweakTipEditorPane(JEditorPane textArea) { + + // Jump through a few hoops to get things looking nice in Nimbus + boolean isNimbus = isNimbusLookAndFeel(); + if (isNimbus) { + Color selBG = textArea.getSelectionColor(); + Color selFG = textArea.getSelectedTextColor(); + textArea.setUI(new javax.swing.plaf.basic.BasicEditorPaneUI()); + textArea.setSelectedTextColor(selFG); + textArea.setSelectionColor(selBG); + } + + textArea.setEditable(false); // Required for links to work! + textArea.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); + + // Make selection visible even though we are not (initially) focusable. + textArea.getCaret().setSelectionVisible(true); + + // Set the foreground color. Important because when rendering HTML, + // default foreground becomes black, which may not match all LAF's + // (e.g. Substance). + Color fg = UIManager.getColor("Label.foreground"); + if (fg==null || (isNimbus && isDerivedColor(fg))) { + fg = SystemColor.textText; + } + textArea.setForeground(fg); + + // Make it use the "tool tip" background color. + textArea.setBackground(TipUtil.getToolTipBackground()); + + // Force JEditorPane to use a certain font even in HTML. + // All standard LookAndFeels, even Nimbus (!), define Label.font. + Font font = UIManager.getFont("Label.font"); + if (font == null) { // Try to make a sensible default + font = new Font("SansSerif", Font.PLAIN, 12); + } + HTMLDocument doc = (HTMLDocument) textArea.getDocument(); + doc.getStyleSheet().addRule( + "body { font-family: " + font.getFamily() + + "; font-size: " + font.getSize() + "pt" + + "; color: " + Util.getHexString(fg) + "; }"); + + // Always add link foreground rule. Unfortunately these CSS rules + // stack each time the LaF is changed (how can we overwrite them + // without clearing out the important "standard" ones?). + Color linkFG = Util.getHyperlinkForeground(); + doc.getStyleSheet().addRule( + "a { color: " + Util.getHexString(linkFG) + "; }"); + + URL url = TipUtil.class.getResource("bullet_black.png"); + if (url!=null) { + doc.getStyleSheet().addRule( + "ul { list-style-image: '" + url.toString() + "'; }"); + } + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/Util.java b/designer_base/src/com/fr/design/gui/autocomplete/Util.java new file mode 100644 index 0000000000..a9fbb224cf --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/Util.java @@ -0,0 +1,323 @@ +/* + * 12/21/2008 + * + * Util.java - Utility methods for the autocompletion package. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.Method; +import java.net.URI; +import java.security.AccessControlException; +import java.util.regex.Pattern; + + +/** + * Utility methods for the auto-complete framework. + * + * @author Robert Futrell + * @version 1.0 + */ +public class Util { + + /** + * If a system property is defined with this name and set, ignoring case, + * to true, this library will not attempt to use Substance + * renderers. Otherwise, if a Substance Look and Feel is installed, we + * will attempt to use Substance cell renderers in all of our dropdowns.

+ *

+ * Note that we do not have a build dependency on Substance, so all access + * to Substance stuff is done via reflection. We will fall back onto + * default renderers if something goes horribly wrong. + */ + public static final String PROPERTY_DONT_USE_SUBSTANCE_RENDERERS = + "com.fr.design.gui.autocomplete.DontUseSubstanceRenderers"; + + /** + * If this system property is true, then even the "main" two + * auto-complete windows will allow window decorations via + * {@link com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator}. If this property is undefined or + * false, they won't honor such decorations. This is due to + * certain performance issues with translucent windows (used for drop + * shadows), even as of Java 7u2. + */ + public static final String PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS = + "com.fr.design.gui.autocomplete.allowDecoratedAutoCompleteWindows"; + + /** + * Used for the color of hyperlinks when a LookAndFeel uses light text + * against a dark background. + */ + private static final Color LIGHT_HYPERLINK_FG = new Color(0xd8ffff); + + private static final Pattern TAG_PATTERN = Pattern.compile("<[^>]*>"); + + private static final boolean useSubstanceRenderers; + private static boolean desktopCreationAttempted; + private static Object desktop; + private static final Object LOCK_DESKTOP_CREATION = new Object(); + + + /** + * Attempts to open a web browser to the specified URI. + * + * @param uri The URI to open. If this is null, nothing + * happens and this method returns false. + * @return Whether the operation was successful. This will be + * false on JRE's older than 1.6. + */ + public static boolean browse(URI uri) { + + boolean success = false; + + if (uri != null) { + Object desktop = getDesktop(); + if (desktop != null) { + try { + Method m = desktop.getClass().getDeclaredMethod( + "browse", new Class[]{URI.class}); + m.invoke(desktop, new Object[]{uri}); + success = true; + } catch (RuntimeException re) { + throw re; // Keep FindBugs happy + } catch (Exception e) { + // Ignore, just return "false" below. + } + } + } + + return success; + + } + + + /** + * Returns the singleton java.awt.Desktop instance, or + * null if it is unsupported on this platform (or the JRE + * is older than 1.6). + * + * @return The desktop, as an {@link Object}. + */ + private static Object getDesktop() { + + synchronized (LOCK_DESKTOP_CREATION) { + + if (!desktopCreationAttempted) { + + desktopCreationAttempted = true; + + try { + Class desktopClazz = Class.forName("java.awt.Desktop"); + Method m = desktopClazz. + getDeclaredMethod("isDesktopSupported"); + + boolean supported = ((Boolean) m.invoke(null)).booleanValue(); + if (supported) { + m = desktopClazz.getDeclaredMethod("getDesktop"); + desktop = m.invoke(null); + } + + } catch (RuntimeException re) { + throw re; // Keep FindBugs happy + } catch (Exception e) { + // Ignore; keeps desktop as null. + } + + } + + } + + return desktop; + + } + + + /** + * Returns a hex string for the specified color, suitable for HTML. + * + * @param c The color. + * @return The string representation, in the form "#rrggbb", + * or null if c is null. + */ + public static String getHexString(Color c) { + + if (c == null) { + return null; + } + + // Don't assume 0xff alpha + //return "#" + Integer.toHexString(c.getRGB()&0xffffff).substring(2); + + StringBuilder sb = new StringBuilder("#"); + int r = c.getRed(); + if (r < 16) { + sb.append('0'); + } + sb.append(Integer.toHexString(r)); + int g = c.getGreen(); + if (g < 16) { + sb.append('0'); + } + sb.append(Integer.toHexString(g)); + int b = c.getBlue(); + if (b < 16) { + sb.append('0'); + } + sb.append(Integer.toHexString(b)); + + return sb.toString(); + + } + + + /** + * Returns the color to use for hyperlink-style components. This method + * will return Color.blue unless it appears that the current + * LookAndFeel uses light text on a dark background, in which case a + * brighter alternative is returned. + * + * @return The color to use for hyperlinks. + */ + static final Color getHyperlinkForeground() { + + // This property is defined by all standard LaFs, even Nimbus (!), + // but you never know what crazy LaFs there are... + Color fg = UIManager.getColor("Label.foreground"); + if (fg == null) { + fg = new JLabel().getForeground(); + } + + return isLightForeground(fg) ? LIGHT_HYPERLINK_FG : Color.blue; + + } + + + /** + * Returns the screen coordinates for the monitor that contains the + * specified point. This is useful for setups with multiple monitors, + * to ensure that popup windows are positioned properly. + * + * @param x The x-coordinate, in screen coordinates. + * @param y The y-coordinate, in screen coordinates. + * @return The bounds of the monitor that contains the specified point. + */ + public static Rectangle getScreenBoundsForPoint(int x, int y) { + GraphicsEnvironment env = GraphicsEnvironment. + getLocalGraphicsEnvironment(); + GraphicsDevice[] devices = env.getScreenDevices(); + for (int i = 0; i < devices.length; i++) { + GraphicsConfiguration config = devices[i].getDefaultConfiguration(); + Rectangle gcBounds = config.getBounds(); + if (gcBounds.contains(x, y)) { + return gcBounds; + } + } + // If point is outside all monitors, default to default monitor (?) + return env.getMaximumWindowBounds(); + } + + + /** + * Give apps a chance to decorate us with drop shadows, etc. Since very + * scrolly things such as lists (of e.g. completions) are *very* slow when + * in per-pixel translucent windows, even as of Java 7u2, we force the user + * to specify an extra option for the two "main" auto-complete windows. + * + * @return Whether to allow decorating the main auto-complete windows. + * @see #PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS + */ + public static boolean getShouldAllowDecoratingMainAutoCompleteWindows() { + try { + return Boolean.getBoolean( + PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS); + } catch (AccessControlException ace) { // We're in an applet. + return false; + } + } + + + /** + * Returns whether we should attempt to use Substance cell renderers and + * styles for things such as completion choices, if a Substance Look and + * Feel is installed. If this is false, we'll use our + * standard rendering for completions, even when Substance is being used. + * + * @return Whether to use Substance renderers if Substance is installed. + */ + public static boolean getUseSubstanceRenderers() { + return useSubstanceRenderers; + } + + + /** + * Returns whether the specified color is "light" to use as a foreground. + * Colors that return true indicate that the current Look and + * Feel probably uses light text colors on a dark background. + * + * @param fg The foreground color. + * @return Whether it is a "light" foreground color. + */ + public static final boolean isLightForeground(Color fg) { + return fg.getRed() > 0xa0 && fg.getGreen() > 0xa0 && fg.getBlue() > 0xa0; + } + + + /** + * Returns whether str starts with start, + * ignoring case. + * + * @param str The string to check. + * @param start The prefix to check for. + * @return Whether str starts with start, + * ignoring case. + */ + public static boolean startsWithIgnoreCase(String str, String start) { + int startLen = start.length(); + if (str.length() >= startLen) { + for (int i = 0; i < startLen; i++) { + char c1 = str.charAt(i); + char c2 = start.charAt(i); + if (Character.toLowerCase(c1) != Character.toLowerCase(c2)) { + return false; + } + } + return true; + } + return false; + } + + + /** + * Strips any HTML from a string. The string must start with + * "<html>" for markup tags to be stripped. + * + * @param text The string. + * @return The string, with any HTML stripped. + */ + public static String stripHtml(String text) { + if (text == null || !text.startsWith("")) { + return text; + } + // TODO: Micro-optimize me, might be called in renderers and loops + return TAG_PATTERN.matcher(text).replaceAll(""); + } + + + static { + + boolean use = true; + try { + use = !Boolean.getBoolean(PROPERTY_DONT_USE_SUBSTANCE_RENDERERS); + } catch (AccessControlException ace) { // We're in an applet. + use = true; + } + useSubstanceRenderers = use; + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/VariableCompletion.java b/designer_base/src/com/fr/design/gui/autocomplete/VariableCompletion.java new file mode 100644 index 0000000000..f3204dc87a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/autocomplete/VariableCompletion.java @@ -0,0 +1,196 @@ +/* + * 12/22/2008 + * + * VariableCompletion.java - A completion for a variable. + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package com.fr.design.gui.autocomplete; + +import javax.swing.text.JTextComponent; + + +/** + * A completion for a variable (or constant) in a programming language.

+ * + * This completion type uses its shortDescription property as part of + * its summary returned by {@link #getSummary()}; for this reason, it may be + * a little longer (even much longer), if desired, than what is recommended + * for BasicCompletions (where the shortDescription is used + * in {@link #toString()} for ListCellRenderers). + * + * @author Robert Futrell + * @version 1.0 + */ +public class VariableCompletion extends BasicCompletion { + + /** + * The variable's type. + */ + private String type; + + /** + * What library (for example) this variable is defined in. + */ + private String definedIn; + + + /** + * Constructor. + * + * @param provider The parent provider. + * @param name The name of this variable. + * @param type The type of this variable (e.g. "int", + * "String", etc.). + */ + public VariableCompletion(CompletionProvider provider, String name, + String type) { + super(provider, name); + this.type = type; + } + + + protected void addDefinitionString(StringBuilder sb) { + sb.append("").append(getDefinitionString()).append(""); + } + + + public String getDefinitionString() { + + StringBuilder sb = new StringBuilder(); + + // Add the return type if applicable (C macros like NULL have no type). + if (type!=null) { + sb.append(type).append(' '); + } + + // Add the item being described's name. + sb.append(getName()); + + return sb.toString(); + + } + + + /** + * Returns where this variable is defined. + * + * @return Where this variable is defined. + * @see #setDefinedIn(String) + */ + public String getDefinedIn() { + return definedIn; + } + + + /** + * Returns the name of this variable. + * + * @return The name. + */ + public String getName() { + return getReplacementText(); + } + + + /** + * {@inheritDoc} + */ + @Override + public String getSummary() { + StringBuilder sb = new StringBuilder(); + addDefinitionString(sb); + possiblyAddDescription(sb); + possiblyAddDefinedIn(sb); + return sb.toString(); + } + + + /** + * Returns the tool tip text to display for mouse hovers over this + * completion.

+ * + * Note that for this functionality to be enabled, a + * JTextComponent must be registered with the + * ToolTipManager, and the text component must know to search + * for this value. In the case of an + * RSyntaxTextArea, this + * can be done with a org.fife.ui.rtextarea.ToolTipSupplier that + * calls into + * {@link CompletionProvider#getCompletionsAt(JTextComponent, java.awt.Point)}. + * + * @return The tool tip text for this completion, or null if + * none. + */ + @Override + public String getToolTipText() { + return getDefinitionString(); + } + + + /** + * Returns the type of this variable. + * + * @return The type. + */ + public String getType() { + return type; + } + + + /** + * Adds some HTML describing where this variable is defined, if this + * information is known. + * + * @param sb The buffer to append to. + */ + protected void possiblyAddDefinedIn(StringBuilder sb) { + if (definedIn!=null) { + sb.append("


Defined in:"); // TODO: Localize me + sb.append(" ").append(definedIn).append(""); + } + } + + + /** + * Adds the description text as HTML to a buffer, if a description is + * defined. + * + * @param sb The buffer to append to. + * @return Whether there was a description to add. + */ + protected boolean possiblyAddDescription(StringBuilder sb) { + if (getShortDescription()!=null) { + sb.append("

"); + sb.append(getShortDescription()); + sb.append("


"); + return true; + } + return false; + } + + + /** + * Sets where this variable is defined. + * + * @param definedIn Where this variable is defined. + * @see #getDefinedIn() + */ + public void setDefinedIn(String definedIn) { + this.definedIn = definedIn; + } + + + /** + * Overridden to return the name of the variable being completed. + * + * @return A string representation of this completion. + */ + @Override + public String toString() { + return getName(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/autocomplete/arrow_left.png b/designer_base/src/com/fr/design/gui/autocomplete/arrow_left.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc696781e6135d37b5bf2e98e46fd94f020c48d GIT binary patch literal 345 zcmV-f0jBq$gGR5;6H z{Qv(y10{fofkH6I3@AO3$p*x`Nil#0jeqs;pT9Ds7{CaN1)$9r#n~kE{`~pF@bLXZ zhF?E_GyM7i!oL`P0x_8Wj$ni2F7#hzWPxfvDaIo>#A+qW*AYQLZl(!&BX$x7Ik;qO170ssEM z@$bKXf%rGW?|(r27bf-TSv zD}TdX0CM*JhkLO)8|Y^+n~Q^sK~hqR;q|N647YFGy>NTZJsWr!5CaSfwJm@a><8NX v2&h?|yGq%gzvv3epMS6VUgTO+t)&4yg_Z9&?~wX1XYz3g^%vJ} zsd8-%W7^RuT(Z`*)5+_lkeLp*VoUZVu_vDAcINajHbe`4`F-)spS_>!?T=Y$yPY}I Rd=F?fgQu&X%Q~loCICsSQ$YX# literal 0 HcmV?d00001 diff --git a/designer_base/src/com/fr/design/gui/autocomplete/osx_sizegrip.png b/designer_base/src/com/fr/design/gui/autocomplete/osx_sizegrip.png new file mode 100644 index 0000000000000000000000000000000000000000..07fa8b19e32736a66b30471f5d4410a6fc310ab8 GIT binary patch literal 4876 zcmeH~_dnEuAICq)5i(MeY_dm2GBVD}=A3M@M|Ae-PT|bUj0%Ob_m(c3vN8`BXOBzS zBYXSy{Wrdk@B8t1zhCe7jOaaKU3U209d#U0BA-42%!dm(SN&VX_cvJfalfIA@mq%?uvWT-g7egesAj9PAten&4;HvHQv$M;+mMVf2?hLa$!1`=eOglIL*@O$}lsq)m9SKaDStfas@R9c5e^p}ziY{$3>?R8#q)eU{;Krb^o zv>{kT4U7F5UXOm>;}N|LoqQ3U1(BPWjg^Pf1Jd`tbwmTepc(qhV{ekJVaL*EbcsNq zG8)R+qOYvX?UY6Cz`1I`t>$P^EaP0VUMuAsLJsWTBeCng;PI=V2u;2o`hH2dcJ?!{ zgC%>Ld6MY)%{QpR&RUTKqZ2dD&8&F`_<2@QLGI%QD*-&M=cX*1YQB7d0DuE?X!Oe? zPT!sFgRpNHvYq);h3)euF3xD9PzEV=U>ik-+S9XbntWs zy?bWOY4#Q>0GvJTbUzABi+ov>k2U#RSF4w>5s0vgG}X9$KSnZ7Cx0zs3UWXso0rzF zi>Y%D@NN`6B?T=;dC`?HPjiS#kUZJc>mRUZGDr!mK*fJ~F;rs_^e`HlP|!n>VJ|ky zpU{AT=hZ9!P1|+aNj}0JzL7)VzcMNtE^wD7mtVYDiVK};pUbY|s>?~X?_R7&qoHz1 zw~MmW^C*7;;Yjl@<1FgEzLg<=Cb7<0xaG^!DzYjmWxS zn+*dTS7%)3+fw>f{%e#`nN5%7(Pgmq>mOvZAia+C?is!#my$nTq95qUte#q#aXeI_ z4a(hh%BeUPY_%zUy*9Z?yKGQ7gsF^x&2D{Ib{2n(yoR(r;yYM96y1Lo;=Z%HS5{BR zt(u;DNs|qtqKF3-&Dk<1-$P!AIi-2kJ9qw4oIPvGGtDb=e59NfY<_9}AlUyEf;gT( z#(!MYhueZ?Kn;s{S~o5v<=&l*J!g_S+pyX=3iq>v{dw}Y85g!|h{@u(<0T$>QESQc z3}fMLIcUXGRp!O{$W-PYcIGQK`xwuyF!Hy~yb%QAA0UO&_LGd;!*BM;6A zP_$si9GHDjQedvBgE(*8eXBzOozx$@{awA{TLC7XQ~V{Y6_U-*3`MOjnxarHDdTrG zTjWO?*-i&QGEsy$rMtqchYH3{yS*mg2d10b9cHLJHr?LAre8$Y68v}k^pxioq}Re^ zxmJ-AgLuX6@Gy^k)_u#vMWqHDfyMB!Nh_P)LyPUwaj8qipWdum9gQrunE30BL+?N# zNi{{#JjvY8L$^9_bu(c^*_GHC=F&$d=VP*5op_TIBP&^Y8J} zX%_ekC&j=H`*$9DT`A%ZFTHtHnM&e))hY12qjT9oD)XI2p}o${9Y5P=dL%nQ6Bcsn zviIed>zNRMxKtK>TSjQNm@e3r%R?mbK^uAk<~%~?fF!!yJWS@#_dN2}`uwB1*Y}4{ zzn_rz_HXDd6C#9V#w^dez_`G&;R<8ffSg1b$E)hcm~MTe*;LQevQbu4c(>zuzN>B#tJ+cueu~uYx-$K@%Y4>h={nN`ju5!*A)IzCLA3|cQy{gI)bb-pkihdYSnG{0G(1eJ?es0&abuESTkEKnU@=d2_eiZ1NcuW4JW_(ZtWJtBn4G`xc}5=jQwHb zm#{BwYnb^q2*+i6IXHjO)iDSP^RtWXRU3(3uOLh8W9L`qs{5!oOAtGcYYE3Xw(OY^ zPW>jR^%BjiY_nXi3Q})Wna;b>Su?ZVt7X@W=Z$mdu6+Giic3*$UoNOI_zzKJt7$n= zf%<7|MVqE+VtEe?Q`jBCe+0Q_NgkU27)V$IWQDG`H#{*aWdw!dC;>lBpnME?1-{-+ z4FcjE_W47M{HRq_mPz?mtU0e80=Kj2%0nqANtbgBU)){+G1@V9Q$tY}-_g}h=5pnC zu)s3PtyC2sEgp>+ zk;dn`>AT_G`B#6g5LayRu_F}tzz39)*B(tzC$d#OZ@fQv3;RCWVI|&OQtWLSO8qYWZJyVT=Ru3G zfsuK&_78{~nJ$A2)1_c?gO%$M9V8~LK-Rcf^SiFGman-`Kw^P((Z0t=5eqXp!3K`q zL8{b4jFE|PE`(){P@YkFGk2}}nXbM%TgBx;yH&iwAgDrtVy_PGe>1@GU}&Z1E-$mK zw2spI7v~E*an}iudwBKF(SL+fo}1Q;&tfxrGB*3z>=NKT>lu;OM1xm8pWz{Iq;@?I z#}8NczqA|DhiPYAj*-B@KNhBpvb=N9xFlytlB=G>32q3po>kk}}!)(|yY3)S(6U z$GLa?3pg)le{tmK2FFUbDBn@Y;YYEo63phOUukA%CH1$kGmScvD#k~+?c+QWP&J7X zC)H98ev!+Y<|T^$E#M0#cO&aq;E%h`M~;uq4AuDVYad_DAR8L{ovuTBhvuc!E2?j( zVK6;CfgZ5dG|W8AJG_sl8b;#Bhq+eDS70L* zBk3dah4T*HcEw%Qj#_E#nuu=c?uUGVg<^kR4`q)hVR}z-N6d5%40aapnIrEq(+N1EdM{oaQ9?XwDz+$I z=a{Im=IRwmR`Mq*-vL&44Vm5`GhgI{AjeSF7xfqF#)k)ksqUgn|`Zc`YA zaWC;D6>m?!oA3nqU7x1`{rlM+42l%ZbSHJkeZ*MG+)mOEcVGL3x$G4B&%;NHs3LQo z{yfiIGY8+H=RJd&;(Fd%POTHE86S!78`t~1k%MD(<;5B09?mBf?*qx_VSY@T!Zi(y zw(ts~`)}iTlT6)Y(l=en1!F0j1-Y=0Mr_`cVZM6VvrIm;oL(M_{fv*l6Ho6 zvEJJCQq9+tQ1sw>ZWt$D(x}$WU6L5k?NDUQA2r6|O=)iFBu*vij1ziE*u!oU1`b`I614`XKF@ATJ)x@5`;9E@W+*JbG z^z*larAUydqNbtiEL0;@2X=lDuQg~lTqZ8Sbzl*jnP=a%j7?*nt`RUktF|9aCoLPS zc5g+Vw;*CpbjZ(y-g`WiH;F#NmGIE*sMPq4#wfjnHkrBF8tPrugB$G=M+$3%{4ovo zl1_d0E-viOBhMqTGM^isD>(7L;8@vNkxhh#?)5VoSJuGr?56cB;=$XoO7~h{p38nq zIPRN|nPGEd*%#`R@E4hR<7vz|a)9v4#6zOm8{6qmErEJ`Vyba`O= z`mOUv#jNzSqIBga4Nn)~x@(8V5NPjjg=5KZDpb&X89QNVENLxKW=A?0R*7KV*CPH+ z#~#BATx~KjMldw8W^{f2(ce+xQ~bRIk{P>AdSd1`?EmD7V^D+sA%p3Irzxiw=hp3XO^Du;)yUE;vpXHB8^MC&QsN<&4Xta{e6=!d za}AJ2izo3{1}$~7D+lP8+;=^4i|8)D4$^V#_fSar+rJ`>|GKWcf+T9o)J1F=Ra^sI zhZVXEXWp24|EeA!E1MVjwd&|bBSGD1nXlrvX3mb*?`Ww=gm{3_iiVBsGFOABYt4dR zDu0K`c9Ru(?F4xiivOh?yAx$;MWmDo*)XHHW_2-wSX(R&x#mEEo{tDx|9Cl`MZu>+ z*B58LKzpIKGpqqp$|hS&LJ4!K?AC0$nz#d$5l&#vTgeMKt;(HBMw(qB=JfdFBd{QSGp7pJs?Rs$?1|{9Z^;xLnOrVd}{x zvJ?FI!qL5_X*%mNwkqJ+Rl@L@2iuuhkV8=ARUmt9yWh0V&f(cfm?8ZcWO+A`b)ux@ zD^6gTWqB)S^dfI5WSSpUKfHNrny5v^bM_KJ;Siw3`pHa12e5GE%lr>3T+r>AFTW@cw+S65fBuCD$) z-2adN6Zjt{FlHVq^zS@oe+_egsF#a>puMj%U}WzO^A|JFFyVwtiAl+nEEDhl+tJci z2b%~$9qly9Xa+KhL!C%u3`|5lX^Kh9X;=kFIhASwske!qAVzee69|n9a{|TDNrf{A o;Ye=-C6RV$AdJqRLgAAa$@~opi9``}=YO$kYZ$0ks@jG92OQi35dZ)H literal 0 HcmV?d00001 diff --git a/designer_base/src/com/fr/design/gui/borders/UIFrameBorder.java b/designer_base/src/com/fr/design/gui/borders/UIFrameBorder.java new file mode 100644 index 0000000000..6410305516 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/borders/UIFrameBorder.java @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.borders; + +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-6 + * Time: 下午3:08 + */ +public class UIFrameBorder extends AbstractBorder implements UIResource { + + // cache for already painted captions + private static HashMap cache = new HashMap(); + + public static Color buttonUpperColor, buttonLowerColor; + private static UIFrameBorder onlyInstance; + private static Robot robot; + private static boolean robotsSupported = true; + private Window window; + private int titleHeight; + private boolean isActive; + + public static UIFrameBorder getInstance() { + if (onlyInstance == null) { + onlyInstance = new UIFrameBorder(); + + if (robot == null && robotsSupported) { + try { + robot = new Robot(); + } catch (Exception ex) { + robotsSupported = false; + } + } + } + + return onlyInstance; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + window = SwingUtilities.getWindowAncestor(c); + isActive = window.isActive(); + + if (window instanceof JFrame) { + titleHeight = ThemeUtils.FRAME_TITLE_HEIGHT; + } else { + titleHeight = ThemeUtils.FRAME_INTERNAL_TITLE_HEIGHT; + } + + if (isActive) { + g.setColor(ThemeUtils.FRAME_BORDER_COLOR); + } else { + g.setColor(ThemeUtils.FRAME_BORDER_DISABLED_COLOR); + } + + drawXpBorder(g, x, y, w, h); + + + Color col = null; + if (isActive) { + col = ThemeUtils.FRAME_CAPTION_COLOR; + } else { + col = ThemeUtils.FRAME_CAPTION_DISABLED_COLOR; + } + g.setColor(col); + + drawXpCaption(g, x, y, w, h, col); + + } + + + private void drawXpBorder(Graphics g, int x, int y, int w, int h) { + // left + g.drawLine(x, y + 6, x, y + h - 1); + g.drawLine(x + 2, y + titleHeight, x + 2, y + h - 3); + // right + g.drawLine(x + w - 1, y + 6, x + w - 1, y + h - 1); + g.drawLine(x + w - 3, y + titleHeight, x + w - 3, y + h - 3); + // bottom + g.drawLine(x + 2, y + h - 3, x + w - 3, y + h - 3); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + if (robot != null) { + int wx = window.getLocationOnScreen().x - 4; + int wy = window.getLocationOnScreen().y; + Rectangle screenRect = new Rectangle(wx, wy, 4, 4); + g.drawImage(robot.createScreenCapture(screenRect), x, y, null); + wx = window.getLocationOnScreen().x + window.getWidth() + 1; + screenRect = new Rectangle(wx, wy, 4, 4); + g.drawImage(robot.createScreenCapture(screenRect), x + w - 4, y, null); + } else { + g.setColor(ThemeUtils.BACK_COLOR); + g.fillRect(0, 0, w, 3); + } + if (isActive) { + g.setColor(ThemeUtils.FRAME_CAPTION_COLOR); + } else { + g.setColor(ThemeUtils.FRAME_CAPTION_DISABLED_COLOR); + } + // left + g.drawLine(x + 1, y + titleHeight, x + 1, y + h - 2); + // right + g.drawLine(x + w - 2, y + titleHeight, x + w - 2, y + h - 2); + // bottom + g.drawLine(x + 1, y + h - 2, x + w - 2, y + h - 2); + Color c = null; + if (isActive) { + c = ThemeUtils.FRAME_BORDER_COLOR; + } else { + c = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + } + g.setColor(ColorRoutines.getAlphaColor(c, 82)); + g.drawLine(x, y + 3, x, y + 3); + g.drawLine(x + w - 1, y + 3, x + w - 1, y + 3); + g.setColor(ColorRoutines.getAlphaColor(c, 156)); + g.drawLine(x, y + 4, x, y + 4); + g.drawLine(x + w - 1, y + 4, x + w - 1, y + 4); + g.setColor(ColorRoutines.getAlphaColor(c, 215)); + g.drawLine(x, y + 5, x, y + 5); + g.drawLine(x + w - 1, y + 5, x + w - 1, y + 5); + } + + + private void drawXpCaption(Graphics g, int x, int y, int w, int h, Color c) { + if (titleHeight == ThemeUtils.FRAME_INTERNAL_TITLE_HEIGHT) { + drawXpInternalCaption(g, x, y, w, h, c); + return; + } + int spread1 = ThemeUtils.FRAME_SPREAD_DARK_DISABLED; + int spread2 = ThemeUtils.FRAME_SPREAD_LIGHT_DISABLED; + int y2 = y; + Color borderColor = null; + drawFirstCaption(g, borderColor, spread1, spread2, x, y2, w); + Color c2 = ColorRoutines.darken(c, 4 * spread1); + drawSecondCaption(g, c2, c, spread2, x, y2, w); + c2 = ColorRoutines.darken(c, 6 * spread1); + drawThirdLine(g, c2, c, spread1, spread2, x, y2, w); + CaptionKey key = new CaptionKey(isActive, titleHeight); + Object value = cache.get(key); + if (value != null) { + g.drawImage((Image) value, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + window); + g.drawImage((Image) value, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + window); + buttonUpperColor = ColorRoutines.darken(c, 4 * spread1); + buttonLowerColor = ColorRoutines.lighten(c, 10 * spread2); + return; + } + Image img = new BufferedImage(1, titleHeight, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + drawLines(img, imgGraphics, borderColor, spread1, spread2, c); + if (isActive) { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_COLOR); + } else { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_DISABLED_COLOR); + } + imgGraphics.drawLine(0, 28, 1, 28); + imgGraphics.dispose(); + g.drawImage(img, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + window); + g.drawImage(img, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + window); + cache.put(key, img); + } + + + private void drawThirdLine(Graphics g, Color c2, Color c, int spread1, int spread2, int x, int y2, int w) { + g.setColor(c2); + g.drawLine(x + 2, y2, x + 2, y2); + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + // darker border + g.setColor(c); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + // blend from lightest color + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.lighten(c, 7 * spread2)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.lighten(c, 3 * spread2)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + g.setColor(c); + g.drawLine(x + 6, y2, x + 6, y2); + g.drawLine(x + w - 7, y2, x + w - 7, y2); + y2++; + g.setColor(ColorRoutines.darken(c, 2 * spread1)); + g.drawLine(x + 5, y2, x + 6, y2); // left + g.drawLine(x + x + w - 7, y2, x + w - 6, y2); // right + // darker border + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + // blend from lightest color + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.lighten(c, 5 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(c); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + y2++; + g.setColor(ColorRoutines.darken(c, 4 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + } + + private void drawSecondCaption(Graphics g, Color c2, Color c, int spread2, int x, int y2, int w) { + g.setColor(c2); + g.drawLine(x + 3, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 4, y2); // right + // blend + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.getAlphaColor(c2, 23)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + // 3 + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 4, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 5, y2); // right + // darker border + g.setColor(c); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + } + + private void drawFirstCaption(Graphics g, Color borderColor, int spread1, int spread2, int x, int y2, int w) { + if (isActive) { + borderColor = ThemeUtils.FRAME_BORDER_COLOR; + spread1 = ThemeUtils.FRAME_SPREAD_DARK; + spread2 = ThemeUtils.FRAME_SPREAD_LIGHT; + } else { + borderColor = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + } + // always paint the semi-transparent parts +// 1 + // blend + g.setColor(ColorRoutines.getAlphaColor(borderColor, 82)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 156)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 215)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + y2++; + } + + + private void drawLines(Image img, Graphics imgGraphics, Color borderColor, int spread1, int spread2, Color c) { + imgGraphics.setColor(borderColor); + imgGraphics.drawLine(0, 0, 1, 0); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 1, 1, 1); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 2, 1, 2); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 3, 1, 3); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 4, 1, 4); + buttonUpperColor = ColorRoutines.darken(c, 4 * spread1); + imgGraphics.setColor(buttonUpperColor); + imgGraphics.drawLine(0, 5, 1, 5); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 6, 1, 6); + imgGraphics.drawLine(0, 7, 1, 7); + imgGraphics.setColor(ColorRoutines.darken(c, 3 * spread1)); + imgGraphics.drawLine(0, 8, 1, 8); + imgGraphics.drawLine(0, 9, 1, 9); + imgGraphics.drawLine(0, 10, 1, 10); + imgGraphics.drawLine(0, 11, 1, 11); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 12, 1, 12); + imgGraphics.drawLine(0, 13, 1, 13); + imgGraphics.drawLine(0, 14, 1, 14); + imgGraphics.setColor(ColorRoutines.darken(c, spread1)); + imgGraphics.drawLine(0, 15, 1, 15); + imgGraphics.drawLine(0, 16, 1, 16); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 17, 1, 17); + imgGraphics.drawLine(0, 18, 1, 18); + imgGraphics.setColor(ColorRoutines.lighten(c, 2 * spread2)); + imgGraphics.drawLine(0, 19, 1, 19); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 20, 1, 20); + imgGraphics.setColor(ColorRoutines.lighten(c, 5 * spread2)); + imgGraphics.drawLine(0, 21, 1, 21); + imgGraphics.setColor(ColorRoutines.lighten(c, 6 * spread2)); + imgGraphics.drawLine(0, 22, 1, 22); + imgGraphics.setColor(ColorRoutines.lighten(c, 8 * spread2)); + imgGraphics.drawLine(0, 23, 1, 23); + imgGraphics.setColor(ColorRoutines.lighten(c, 9 * spread2)); + imgGraphics.drawLine(0, 24, 1, 24); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 25, 1, 25); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 26, 1, 26); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 27, 1, 27); + } + + private void drawXpInternalCaption(Graphics g, int x, int y, int w, int h, Color c) { + int spread1 = ThemeUtils.FRAME_SPREAD_DARK_DISABLED; + int spread2 = ThemeUtils.FRAME_SPREAD_LIGHT_DISABLED; + int y2 = y; + Color borderColor = null; + paintCaptionLine(g, borderColor, spread1, spread2, x, y2, w); + Color c2 = ColorRoutines.darken(c, 4 * spread1); + paintFirstLine(g, c2, c, spread2, x, y2, w); + c2 = ColorRoutines.darken(c, 6 * spread1); + paintSecondLine(g, c2, c, spread1, spread2, x, y2, w); + // now either paint from cache or create cached image + CaptionKey key = new CaptionKey(isActive, titleHeight); + Object value = cache.get(key); + if (value != null) { + // image is cached - paint and return + g.drawImage((Image) value, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + window); + g.drawImage((Image) value, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + window); + buttonUpperColor = ColorRoutines.darken(c, 4 * spread1); + buttonLowerColor = ColorRoutines.lighten(c, 10 * spread2); + + return; + } + Image img = new BufferedImage(1, titleHeight, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + paintCaptionImage(imgGraphics, borderColor, spread1, spread2, c); + if (isActive) { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_COLOR); + } else { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_DISABLED_COLOR); + } + imgGraphics.drawLine(0, 24, 1, 24); + imgGraphics.dispose(); + g.drawImage(img, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + window); + g.drawImage(img, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + window); + cache.put(key, img); + } + + private void paintCaptionImage(Graphics imgGraphics, Color borderColor, int spread1, int spread2, Color c) { + imgGraphics.setColor(borderColor); + imgGraphics.drawLine(0, 0, 1, 0); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 1, 1, 1); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 2, 1, 2); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 3, 1, 3); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 4, 1, 4); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 5, 1, 5); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 6, 1, 6); + imgGraphics.setColor(ColorRoutines.darken(c, 3 * spread1)); + imgGraphics.drawLine(0, 7, 1, 7); + imgGraphics.drawLine(0, 8, 1, 8); + imgGraphics.drawLine(0, 9, 1, 9); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 10, 1, 10); + imgGraphics.drawLine(0, 11, 1, 11); + imgGraphics.setColor(ColorRoutines.darken(c, spread1)); + imgGraphics.drawLine(0, 12, 1, 12); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 13, 1, 13); + imgGraphics.drawLine(0, 14, 1, 14); + imgGraphics.setColor(ColorRoutines.lighten(c, 2 * spread2)); + imgGraphics.drawLine(0, 15, 1, 15); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 16, 1, 16); + imgGraphics.setColor(ColorRoutines.lighten(c, 5 * spread2)); + imgGraphics.drawLine(0, 17, 1, 17); + imgGraphics.setColor(ColorRoutines.lighten(c, 6 * spread2)); + imgGraphics.drawLine(0, 18, 1, 18); + imgGraphics.setColor(ColorRoutines.lighten(c, 8 * spread2)); + imgGraphics.drawLine(0, 19, 1, 19); + imgGraphics.setColor(ColorRoutines.lighten(c, 9 * spread2)); + imgGraphics.drawLine(0, 20, 1, 20); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 21, 1, 21); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 22, 1, 22); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 23, 1, 23); + } + + + private void paintSecondLine(Graphics g, Color c2, Color c, int spread1, int spread2, int x, int y2, int w) { + g.setColor(c2); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + // blend + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + g.setColor(c); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.lighten(c, 7 * spread2)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.lighten(c, 3 * spread2)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + g.setColor(c); + g.drawLine(x + 6, y2, x + 6, y2); + g.drawLine(x + w - 7, y2, x + w - 7, y2); + y2++; + g.setColor(ColorRoutines.darken(c, 2 * spread1)); + g.drawLine(x + 5, y2, x + 6, y2); // left + g.drawLine(x + x + w - 7, y2, x + w - 6, y2); // right + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.lighten(c, 5 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(c); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + y2++; + g.setColor(ColorRoutines.darken(c, 4 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + } + + private void paintFirstLine(Graphics g, Color c2, Color c, int spread2, int x, int y2, int w) { + g.setColor(c2); + g.drawLine(x + 3, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 4, y2); // right + // blend + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.getAlphaColor(c2, 23)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + // 3 + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 4, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 5, y2); // right + // darker border + g.setColor(c); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + } + + + private void paintCaptionLine(Graphics g, Color borderColor, int spread1, int spread2, int x, int y2, int w) { + + if (isActive) { + borderColor = ThemeUtils.FRAME_BORDER_COLOR; + spread1 = ThemeUtils.FRAME_SPREAD_DARK; + spread2 = ThemeUtils.FRAME_SPREAD_LIGHT; + } else { + borderColor = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + } + + // always paint the semi-transparent parts +// 1 + // blend + g.setColor(ColorRoutines.getAlphaColor(borderColor, 82)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 156)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 215)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + y2++; + } + + + /** + * @see javax.swing.border.Border#getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c) { + Window w = SwingUtilities.getWindowAncestor(c); + + if (w != null && (w instanceof Frame)) { + Frame f = (Frame) w; + + // if the frame is maximized, the border should not be visible + if (f.getExtendedState() == (f.getExtendedState() | Frame.MAXIMIZED_BOTH)) { + return new Insets(0, 0, 0, 0); + } + } + + return new Insets(0, ThemeUtils.FRAME_BORDER_WIDTH, + ThemeUtils.FRAME_BORDER_WIDTH, ThemeUtils.FRAME_BORDER_WIDTH); + } + + /** + * CaptionKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + */ + static class CaptionKey { + + private boolean isActive; + private int titleHeight; + + CaptionKey(boolean isActive, int titleHeight) { + this.isActive = isActive; + this.titleHeight = titleHeight; + } + + public boolean equals(Object o) { + if (o == null){ + return false; + } + if (!(o instanceof CaptionKey)) { + return false; + } + + CaptionKey other = (CaptionKey) o; + + return isActive == other.isActive && + titleHeight == other.titleHeight; + } + + public int hashCode() { + return (isActive ? 1 : 2) * titleHeight; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/borders/UIInternalFrameBorder.java b/designer_base/src/com/fr/design/gui/borders/UIInternalFrameBorder.java new file mode 100644 index 0000000000..1c5218b5c0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/borders/UIInternalFrameBorder.java @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.borders; + +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + + +import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-5 + * Time: 下午3:13 + */ +public class UIInternalFrameBorder extends AbstractBorder implements UIResource { + private static HashMap cache = new HashMap(); + + public static Color frameUpperColor, frameLowerColor; + public static Color disabledUpperColor, disabledLowerColor; + private JInternalFrame frame; + private boolean isPalette; + private int titleHeight; + + /** + * indicates whether the internal frame is active + */ + private boolean isActive; + + /** + * @see javax.swing.border.Border#paintBorder(Component, Graphics, int, int, int, int) + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + frame = (JInternalFrame) c; + + if (ThemeUtils.FRAME_IS_TRANSPARENT) { + frame.setOpaque(false); + } + + isActive = frame.isSelected(); + isPalette = (frame.getClientProperty("isPalette") == Boolean.TRUE); + + if (isPalette) { + titleHeight = ThemeUtils.FRAME_PALETTE_TITLE_HEIGHT; + } else { + titleHeight = ThemeUtils.FRAME_INTERNAL_TITLE_HEIGHT; + } + + if (isActive) { + g.setColor(ThemeUtils.FRAME_BORDER_COLOR); + } else { + g.setColor(ThemeUtils.FRAME_BORDER_DISABLED_COLOR); + } + + drawXpBorder(g, x, y, w, h); + + + Color col = null; + if (isActive) { + col = ThemeUtils.FRAME_CAPTION_COLOR; + } else { + col = ThemeUtils.FRAME_CAPTION_DISABLED_COLOR; + } + g.setColor(col); + drawXpCaption(g, x, y, w, h, col); + } + + + private void drawXpBorder(Graphics g, int x, int y, int w, int h) { + // left + g.drawLine(x, y + 6, x, y + h - 1); + g.drawLine(x + 2, y + titleHeight, x + 2, y + h - 3); + // right + g.drawLine(x + w - 1, y + 6, x + w - 1, y + h - 1); + g.drawLine(x + w - 3, y + titleHeight, x + w - 3, y + h - 3); + // bottom + g.drawLine(x + 2, y + h - 3, x + w - 3, y + h - 3); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + + if (isActive) { + g.setColor(ThemeUtils.FRAME_CAPTION_COLOR); + } else { + g.setColor(ThemeUtils.FRAME_CAPTION_DISABLED_COLOR); + } + + // left + g.drawLine(x + 1, y + titleHeight, x + 1, y + h - 2); + // right + g.drawLine(x + w - 2, y + titleHeight, x + w - 2, y + h - 2); + // bottom + g.drawLine(x + 1, y + h - 2, x + w - 2, y + h - 2); + + // outer blend over 3 px + Color c = null; + if (isActive) { + c = ThemeUtils.FRAME_BORDER_COLOR; + } else { + c = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + } + + g.setColor(ColorRoutines.getAlphaColor(c, 82)); + g.drawLine(x, y + 3, x, y + 3); + g.drawLine(x + w - 1, y + 3, x + w - 1, y + 3); + g.setColor(ColorRoutines.getAlphaColor(c, 156)); + g.drawLine(x, y + 4, x, y + 4); + g.drawLine(x + w - 1, y + 4, x + w - 1, y + 4); + g.setColor(ColorRoutines.getAlphaColor(c, 215)); + g.drawLine(x, y + 5, x, y + 5); + g.drawLine(x + w - 1, y + 5, x + w - 1, y + 5); + } + + + private void drawXpCaption(Graphics g, int x, int y, int w, int h, Color c) { + // Note: this method is equal to TinyFrameBorder.drawXpInternalCaption() + if (isPalette) { + drawXpPaletteCaption(g, x, y, w, h, c); + return; + } + int spread1 = ThemeUtils.FRAME_SPREAD_DARK_DISABLED; + int spread2 = ThemeUtils.FRAME_SPREAD_LIGHT_DISABLED; + int y2 = y; + Color borderColor = null; + if (isActive) { + borderColor = ThemeUtils.FRAME_BORDER_COLOR; + spread1 = ThemeUtils.FRAME_SPREAD_DARK; + spread2 = ThemeUtils.FRAME_SPREAD_LIGHT; + } else { + borderColor = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + } + // always paint the semi-transparent parts + // 1 + // blend + drawFirstLine(g, x, y, w, h, y2, spread1, spread2, c, borderColor); + // 4 + // darker border + drawSecondLine(g, x, y, w, h, y2, spread1, spread2, c); + // now either paint from cache or create cached image + CaptionKey key = new CaptionKey(isActive, titleHeight); + Object value = cache.get(key); + if (value != null) { + g.drawImage((Image) value, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + frame); + g.drawImage((Image) value, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + frame); + if (isActive) { + frameUpperColor = ColorRoutines.darken(c, 4 * spread1); + frameLowerColor = ColorRoutines.lighten(c, 10 * spread2); + } else { + disabledUpperColor = ColorRoutines.darken(c, 4 * spread1); + disabledLowerColor = ColorRoutines.lighten(c, 10 * spread2); + } + return; + } + Image img = new BufferedImage(1, titleHeight, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + drawImageLine(imgGraphics, borderColor, c, spread1, spread2); + drawImageLast(img, imgGraphics, g, x, y, w, key); + } + + private void drawImageLast(Image img, Graphics imgGraphics, Graphics g, int x, int y, int w, CaptionKey key) { + // 25 + if (isActive) { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_COLOR); + } else { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_DISABLED_COLOR); + } + imgGraphics.drawLine(0, 24, 1, 24); + + // dispose of image graphics + imgGraphics.dispose(); + + // paint image + g.drawImage(img, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + frame); + g.drawImage(img, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + frame); + + // add the image to the cache + cache.put(key, img); + } + + private void drawImageLine(Graphics imgGraphics, Color borderColor, Color c, int spread1, int spread2) { + imgGraphics.setColor(borderColor); + imgGraphics.drawLine(0, 0, 1, 0); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 1, 1, 1); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 2, 1, 2); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 3, 1, 3); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 4, 1, 4); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 5, 1, 5); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 6, 1, 6); + imgGraphics.setColor(ColorRoutines.darken(c, 3 * spread1)); + imgGraphics.drawLine(0, 7, 1, 7); + imgGraphics.drawLine(0, 8, 1, 8); + imgGraphics.drawLine(0, 9, 1, 9); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 10, 1, 10); + imgGraphics.drawLine(0, 11, 1, 11); + imgGraphics.setColor(ColorRoutines.darken(c, spread1)); + imgGraphics.drawLine(0, 12, 1, 12); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 13, 1, 13); + imgGraphics.drawLine(0, 14, 1, 14); + imgGraphics.setColor(ColorRoutines.lighten(c, 2 * spread2)); + imgGraphics.drawLine(0, 15, 1, 15); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 16, 1, 16); + imgGraphics.setColor(ColorRoutines.lighten(c, 5 * spread2)); + imgGraphics.drawLine(0, 17, 1, 17); + imgGraphics.setColor(ColorRoutines.lighten(c, 6 * spread2)); + imgGraphics.drawLine(0, 18, 1, 18); + imgGraphics.setColor(ColorRoutines.lighten(c, 8 * spread2)); + imgGraphics.drawLine(0, 19, 1, 19); + imgGraphics.setColor(ColorRoutines.lighten(c, 9 * spread2)); + imgGraphics.drawLine(0, 20, 1, 20); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 21, 1, 21); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 22, 1, 22); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 23, 1, 23); + } + + private void drawFirstLine(Graphics g, int x, int y, int w, int h, int y2, int spread1, int spread2, Color c, Color borderColor) { + g.setColor(ColorRoutines.getAlphaColor(borderColor, 82)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 156)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 215)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + y2++; + // 2 + Color c2 = ColorRoutines.darken(c, 4 * spread1); + g.setColor(c2); + g.drawLine(x + 3, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 4, y2); // right + // blend + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.getAlphaColor(c2, 23)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + // 3 + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 4, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 5, y2); // right + // darker border + g.setColor(c); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + c2 = ColorRoutines.darken(c, 6 * spread1); + g.setColor(c2); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + // blend + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + } + + private void drawSecondLine(Graphics g, int x, int y, int w, int h, int y2, int spread1, int spread2, Color c) { + g.setColor(c); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + // blend from lightest color + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.lighten(c, 7 * spread2)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.lighten(c, 3 * spread2)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + g.setColor(c); + g.drawLine(x + 6, y2, x + 6, y2); + g.drawLine(x + w - 7, y2, x + w - 7, y2); + y2++; + g.setColor(ColorRoutines.darken(c, 2 * spread1)); + g.drawLine(x + 5, y2, x + 6, y2); // left + g.drawLine(x + x + w - 7, y2, x + w - 6, y2); // right + // darker border + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + // blend from lightest color + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.lighten(c, 5 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(c); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + y2++; + // 6 + // lighten little + g.setColor(ColorRoutines.darken(c, 4 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + } + + private void drawXpPaletteCaption(Graphics g, int x, int y, int w, int h, Color c) { + int y2 = y; + int spread1 = ThemeUtils.FRAME_SPREAD_DARK_DISABLED; + int spread2 = ThemeUtils.FRAME_SPREAD_LIGHT_DISABLED; + Color borderColor = null; + if (isActive) { + borderColor = ThemeUtils.FRAME_BORDER_COLOR; + spread1 = ThemeUtils.FRAME_SPREAD_DARK; + spread2 = ThemeUtils.FRAME_SPREAD_LIGHT; + } else { + borderColor = ThemeUtils.FRAME_BORDER_DISABLED_COLOR; + } + // always paint the semi-transparent parts + paintFirstLine(g, x, y, w, h, y2, spread1, spread2, c, borderColor); + // blend from lightest color + paintSecondLine(g, x, y, w, h, y2, spread1, spread2, c); + // now either paint from cache or create cached image + CaptionKey key = new CaptionKey(isActive, titleHeight); + Object value = cache.get(key); + + if (value != null) { + // image is cached - paint and return + g.drawImage((Image) value, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + frame); + g.drawImage((Image) value, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + frame); + + // store button colors + if (isActive) { + frameUpperColor = ColorRoutines.darken(c, 4 * spread1); + frameLowerColor = ColorRoutines.lighten(c, 10 * spread2); + } else { + disabledUpperColor = ColorRoutines.darken(c, 4 * spread1); + disabledLowerColor = ColorRoutines.lighten(c, 10 * spread2); + } + + return; + } + + Image img = new BufferedImage(1, titleHeight, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + paintImageLine(imgGraphics, borderColor, c, spread1, spread2); + paintImageLast(img, imgGraphics, g, x, y, w, key); + } + + + private void paintImageLast(Image img, Graphics imgGraphics, Graphics g, int x, int y, int w, CaptionKey key) { + // 21 + if (isActive) { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_COLOR); + } else { + imgGraphics.setColor(ThemeUtils.FRAME_LIGHT_DISABLED_COLOR); + } + imgGraphics.drawLine(0, 20, 1, 20); + + // dispose of image graphics + imgGraphics.dispose(); + + // paint image + g.drawImage(img, + x + 6, y, x + w - 6, y + 5, + 0, 0, 1, 5, + frame); + g.drawImage(img, + x + 1, y + 5, x + w - 1, y + titleHeight, + 0, 5, 1, titleHeight, + frame); + + // add the image to the cache + cache.put(key, img); + + } + + private void paintImageLine(Graphics imgGraphics, Color borderColor, Color c, int spread1, int spread2) { + imgGraphics.setColor(borderColor); + imgGraphics.drawLine(0, 0, 1, 0); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 1, 1, 1); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 2, 1, 2); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 3, 1, 3); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 4, 1, 4); + imgGraphics.setColor(ColorRoutines.darken(c, 4 * spread1)); + imgGraphics.drawLine(0, 5, 1, 5); + imgGraphics.drawLine(0, 6, 1, 6); + imgGraphics.setColor(ColorRoutines.darken(c, 3 * spread1)); + imgGraphics.drawLine(0, 7, 1, 7); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 8, 1, 8); + imgGraphics.setColor(ColorRoutines.darken(c, spread1)); + imgGraphics.drawLine(0, 9, 1, 9); + imgGraphics.setColor(c); + imgGraphics.drawLine(0, 10, 1, 10); + imgGraphics.setColor(ColorRoutines.lighten(c, 2 * spread2)); + imgGraphics.drawLine(0, 11, 1, 11); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 12, 1, 12); + imgGraphics.setColor(ColorRoutines.lighten(c, 5 * spread2)); + imgGraphics.drawLine(0, 13, 1, 13); + imgGraphics.setColor(ColorRoutines.lighten(c, 6 * spread2)); + imgGraphics.drawLine(0, 14, 1, 14); + imgGraphics.setColor(ColorRoutines.lighten(c, 8 * spread2)); + imgGraphics.drawLine(0, 15, 1, 15); + imgGraphics.setColor(ColorRoutines.lighten(c, 9 * spread2)); + imgGraphics.drawLine(0, 16, 1, 16); + imgGraphics.setColor(ColorRoutines.lighten(c, 10 * spread2)); + imgGraphics.drawLine(0, 17, 1, 17); + imgGraphics.setColor(ColorRoutines.lighten(c, 4 * spread2)); + imgGraphics.drawLine(0, 18, 1, 18); + imgGraphics.setColor(ColorRoutines.darken(c, 2 * spread1)); + imgGraphics.drawLine(0, 19, 1, 19); + } + + private void paintSecondLine(Graphics g, int x, int y, int w, int h, int y2, int spread1, int spread2, Color c) { + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.lighten(c, 7 * spread2)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.lighten(c, 3 * spread2)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + g.setColor(c); + g.drawLine(x + 6, y2, x + 6, y2); + g.drawLine(x + w - 7, y2, x + w - 7, y2); + y2++; + // 5 + g.setColor(ColorRoutines.darken(c, 2 * spread1)); + g.drawLine(x + 5, y2, x + 6, y2); // left + g.drawLine(x + x + w - 7, y2, x + w - 6, y2); // right + // darker border + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + // blend from lightest color + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.lighten(c, 5 * spread2)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(c); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + y2++; + // 6 + // lighten little + g.setColor(ColorRoutines.darken(c, 4 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2);/**/ + } + + private void paintFirstLine(Graphics g, int x, int y, int w, int h, int y2, int spread1, int spread2, Color c, Color borderColor) { + // 1 + g.setColor(ColorRoutines.getAlphaColor(borderColor, 82)); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 156)); + g.drawLine(x + 4, y2, x + 4, y2); + g.drawLine(x + w - 5, y2, x + w - 5, y2); + g.setColor(ColorRoutines.getAlphaColor(borderColor, 215)); + g.drawLine(x + 5, y2, x + 5, y2); + g.drawLine(x + w - 6, y2, x + w - 6, y2); + y2++; + // 2 + Color c2 = ColorRoutines.darken(c, 4 * spread1); + g.setColor(c2); + g.drawLine(x + 3, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 4, y2); // right + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.getAlphaColor(c2, 23)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + g.setColor(ColorRoutines.lighten(c, 10 * spread2)); + g.drawLine(x + 4, y2, x + 5, y2); // left + g.drawLine(x + w - 6, y2, x + w - 5, y2); // right + // darker border + g.setColor(c); + g.drawLine(x + 3, y2, x + 3, y2); + g.drawLine(x + w - 4, y2, x + w - 4, y2); + c2 = ColorRoutines.darken(c, 6 * spread1); + g.setColor(c2); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.getAlphaColor(c2, 139)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + y2++; + // 4 + // darker border + g.setColor(c); + g.drawLine(x + 2, y2, x + 2, y2); + g.drawLine(x + w - 3, y2, x + w - 3, y2); + g.setColor(ColorRoutines.darken(c, 6 * spread1)); + g.drawLine(x + 1, y2, x + 1, y2); + g.drawLine(x + w - 2, y2, x + w - 2, y2); + } + + + /** + * @see javax.swing.border.Border#getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c) { + JInternalFrame frame = (JInternalFrame) c; + + // if the frame is maximized, the border should not be visible + if (frame.isMaximum()) { + return new Insets(0, 0, 0, 0); + } + + return new Insets(0, ThemeUtils.FRAME_BORDER_WIDTH, + ThemeUtils.FRAME_BORDER_WIDTH, ThemeUtils.FRAME_BORDER_WIDTH); + } + + + /** + * CaptionKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + */ + static class CaptionKey { + + private boolean isActive; + private int titleHeight; + + CaptionKey(boolean isActive, int titleHeight) { + this.isActive = isActive; + this.titleHeight = titleHeight; + } + + public boolean equals(Object o) { + if (o == null){ + return false; + } + if (!(o instanceof CaptionKey)){ + return false; + } + + CaptionKey other = (CaptionKey) o; + + return isActive == other.isActive && + titleHeight == other.titleHeight; + } + + public int hashCode() { + return (isActive ? 1 : 2) * titleHeight; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/borders/UITableHeaderBorder.java b/designer_base/src/com/fr/design/gui/borders/UITableHeaderBorder.java new file mode 100644 index 0000000000..df6e9fa517 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/borders/UITableHeaderBorder.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.borders; + +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-6 + * Time: 下午3:37 + */ +public class UITableHeaderBorder extends AbstractBorder implements UIResource { + protected static final Insets INSETS_XP = new Insets(3, 0, 3, 2); + protected Color color1, color2, color3, color4, color5; + + public Insets getBorderInsets(Component c) { + return INSETS_XP; + + } + + public Insets getBorderInsets(Component c, Insets insets) { + insets.left = INSETS_XP.left; + insets.top = INSETS_XP.top; + insets.right = INSETS_XP.right; + insets.bottom = INSETS_XP.bottom; + + return insets; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + if (color1 == null) { + color1 = ColorRoutines.darken(c.getBackground(), 5); + color2 = ColorRoutines.darken(c.getBackground(), 10); + color3 = ColorRoutines.darken(c.getBackground(), 15); + color4 = ThemeUtils.TABLE_HEADER_DARK_COLOR; + color5 = ThemeUtils.TABLE_HEADER_LIGHT_COLOR; + } + + // paint 3 bottom lines + g.setColor(color1); + g.drawLine(x, y + h - 3, x + w - 1, y + h - 3); + + g.setColor(color2); + g.drawLine(x, y + h - 2, x + w - 1, y + h - 2); + + g.setColor(color3); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + + // paint separator + g.setColor(color4); + g.drawLine(x + w - 2, y + 3, x + w - 2, y + h - 5); + + g.setColor(color5); + g.drawLine(x + w - 1, y + 3, x + w - 1, y + h - 5); + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/borders/UITableHeaderRolloverBorder.java b/designer_base/src/com/fr/design/gui/borders/UITableHeaderRolloverBorder.java new file mode 100644 index 0000000000..fd4eebb680 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/borders/UITableHeaderRolloverBorder.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.borders; + +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-6 + * Time: 下午3:36 + */ +public class UITableHeaderRolloverBorder extends UITableHeaderBorder { + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + if (color1 == null) { + color1 = ThemeUtils.TABLE_HEADER_ROLLOVER_COLOR; + color2 = ColorRoutines.lighten(color1, 25); + } + + g.setColor(color1); + g.drawLine(x, y + h - 3, x + w - 1, y + h - 3); // top + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); // bottom + + g.setColor(color2); + g.drawLine(x, y + h - 2, x + w - 1, y + h - 2); // mid + + // don't paint separator + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/borders/UITableScrollPaneBorder.java b/designer_base/src/com/fr/design/gui/borders/UITableScrollPaneBorder.java new file mode 100644 index 0000000000..21b333d288 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/borders/UITableScrollPaneBorder.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.borders; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-7 + * Time: 上午9:25 + */ +public class UITableScrollPaneBorder extends AbstractBorder implements UIResource { + private static final Insets INSETS = new Insets(1, 1, 1, 1); + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + g.setColor(ThemeUtils.TABLE_BORDER_LIGHT_COLOR); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); // right + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); // bottom + + g.setColor(ThemeUtils.TABLE_BORDER_DARK_COLOR); + g.drawLine(x, y, x, y + h - 1); // left + g.drawLine(x, y, x + w - 1, y); // top + } + + public Insets getBorderInsets(Component c) { + return INSETS; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/borders/UITextFieldBorder.java b/designer_base/src/com/fr/design/gui/borders/UITextFieldBorder.java new file mode 100644 index 0000000000..b173eb8065 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/borders/UITextFieldBorder.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.borders; + +import com.fr.design.utils.DrawRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-5 + * Time: 下午2:49 + */ +public class UITextFieldBorder extends AbstractBorder implements UIResource { + private Insets insets; + + public UITextFieldBorder() { + insets = ThemeUtils.TEXT_INSETS; + } + + public UITextFieldBorder(Insets insets) { + this.insets = insets; + } + + /** + * Gets the border insets for a given component. + * + * @param c The component to get its border insets. + * @return Always returns the same insets as defined in insets. + */ + public Insets getBorderInsets(Component c) { + return insets; + } + + /** + * Use the skin to paint the border + * + * @see javax.swing.border.Border#paintBorder(Component, Graphics, int, int, int, int) + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + drawXpBorder(c, g, x, y, w, h); + } + + private void drawXpBorder(Component c, Graphics g, int x, int y, int w, int h) { + if (!c.isEnabled()) { + DrawRoutines.drawBorder( + g, ThemeUtils.TEXT_BORDER_DISABLED_COLOR, x, y, w, h); + } else { + DrawRoutines.drawBorder( + g, ThemeUtils.TEXT_BORDER_COLOR, x, y, w, h); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/chart/BaseChartPropertyPane.java b/designer_base/src/com/fr/design/gui/chart/BaseChartPropertyPane.java new file mode 100644 index 0000000000..2bedd08dbe --- /dev/null +++ b/designer_base/src/com/fr/design/gui/chart/BaseChartPropertyPane.java @@ -0,0 +1,25 @@ +package com.fr.design.gui.chart; + +import com.fr.base.chart.BaseChartCollection; +import com.fr.design.designer.TargetComponent; +import com.fr.design.mainframe.BaseWidgetPropertyPane; +import com.fr.design.mainframe.DockingView; + +/** + * 图表属性界面 抽象, 用于多工程协作.. + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-7-10 上午09:12:11 + */ +public abstract class BaseChartPropertyPane extends DockingView { + + public abstract void setSureProperty(); + + /** + * 设置是否支持单元格数据. + */ + public abstract void setSupportCellData(boolean supportCellData); + + public abstract void populateChartPropertyPane(BaseChartCollection collection, TargetComponent ePane); + + public abstract void setWidgetPropertyPane(BaseWidgetPropertyPane pane); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/chart/MiddleChartComponent.java b/designer_base/src/com/fr/design/gui/chart/MiddleChartComponent.java new file mode 100644 index 0000000000..6a572c7087 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/chart/MiddleChartComponent.java @@ -0,0 +1,25 @@ +package com.fr.design.gui.chart; + +import javax.swing.JComponent; + +import com.fr.base.chart.BaseChart; +import com.fr.base.chart.BaseChartCollection; +import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.stable.core.PropertyChangeListener; + +/** + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-7-10 上午09:19:36 + */ +public abstract class MiddleChartComponent extends JComponent { + + public abstract void populate(BaseChartCollection cc); + + public abstract BaseChartCollection update(); + + public abstract void reset(); + + public abstract BaseChart getEditingChart(); + + public abstract void addStopEditingListener(PropertyChangeListener list); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/chart/MiddleChartDialog.java b/designer_base/src/com/fr/design/gui/chart/MiddleChartDialog.java new file mode 100644 index 0000000000..ace74f6462 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/chart/MiddleChartDialog.java @@ -0,0 +1,28 @@ +package com.fr.design.gui.chart; + +import java.awt.Dialog; +import java.awt.Frame; + +import com.fr.base.chart.BaseChartCollection; +import com.fr.design.dialog.BasicDialog; + +/** + * * 抽象的, 用于多工程间协作, 封装一层 图表新建的对话框, 配合属性表确定: 先单独只要一种图表类型的对话框. + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-7-10 上午10:07:56 + */ +public abstract class MiddleChartDialog extends BasicDialog{ + + public MiddleChartDialog(Dialog parent) { + super(parent); + } + + public MiddleChartDialog(Frame owner) { + super(owner); + } + + public abstract BaseChartCollection getChartCollection(); + + public abstract void populate(BaseChartCollection cc); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/columnrow/ColumnRowPane.java b/designer_base/src/com/fr/design/gui/columnrow/ColumnRowPane.java new file mode 100644 index 0000000000..c599c5ce81 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/columnrow/ColumnRowPane.java @@ -0,0 +1,258 @@ +package com.fr.design.gui.columnrow; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridLayout; + +import javax.swing.JFormattedTextField; +import javax.swing.JPanel; +import javax.swing.JSpinner.DefaultEditor; +import javax.swing.SpinnerListModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.AbstractDocument; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DocumentFilter; + +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.ispinner.UIBasicSpinner; +import com.fr.design.gui.ispinner.UpperCaseSpinner; +import com.fr.general.ComparatorUtils; +import com.fr.stable.ColumnRow; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * the component to edit ColumnRow + * + * @editor zhou 2012-3-22下午3:55:53 + */ +public class ColumnRowPane extends JPanel implements UIObserver { + + private static final long serialVersionUID = 1L; + private static String[] columnarray = new String[1000]; + private static String[] rowarray = new String[5000]; + + + protected UpperCaseSpinner columnSpinner; + protected UIBasicSpinner rowSpinner; + + static { + for (int i = 1; i < 1000; i++) { + columnarray[i - 1] = StableUtils.convertIntToABC(i); + } + for (int i = 1; i < 5000; i++) { + rowarray[i - 1] = StringUtils.EMPTY + i; + } + } + + protected DocumentListener d = new DocumentListener() { + + + @Override + public void removeUpdate(DocumentEvent e) { + String rolText = ((DefaultEditor) columnSpinner.getEditor()).getTextField().getText(); + String rowText = ((DefaultEditor) rowSpinner.getEditor()).getTextField().getText(); + if (rolText == null || rolText.length() == 0 || rowText == null || rowText.length() == 0) { + return; + } + int col = StableUtils.convertABCToInt(rolText) - 1; + int row = Integer.parseInt(rowText) - 1; + setColumnRow(ColumnRow.valueOf(col, row)); + } + + @Override + public void insertUpdate(DocumentEvent e) { + int col = StableUtils.convertABCToInt(((DefaultEditor) columnSpinner.getEditor()).getTextField().getText()) - 1; + int row = Integer.parseInt(((DefaultEditor) rowSpinner.getEditor()).getTextField().getText()) - 1; + setColumnRow(ColumnRow.valueOf(col, row)); + } + + @Override + public void changedUpdate(DocumentEvent e) { + + } + }; + + + private UIObserverListener uiObserverListener; + private ColumnRow cr; + + + public ColumnRowPane() { + this.initComponents(); + iniListener(); + } + + + /** + * 初始化元素 + */ + public void initComponents() { + this.setLayout(new GridLayout(0, 2, 0, 0)); + initColSpinner(); + this.add(columnSpinner, BorderLayout.WEST); + initRowSpinner(); + this.add(rowSpinner); + this.addDocumentListener(d); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + + protected void initRowSpinner() { + rowSpinner = new UIBasicSpinner((new SpinnerListModel(rowarray))) { + public boolean shouldResponseChangeListener() { + return false; + } + + }; + rowSpinner.setPreferredSize(new Dimension(60, 24)); + JFormattedTextField rftf = GUICoreUtils.getSpinnerTextField(rowSpinner); + if (rftf != null) { + rftf.setColumns(4); // specify more width than we need + rftf.setHorizontalAlignment(UITextField.LEFT); + } + } + + protected void initColSpinner() { + SpinnerListModel columnSpinnerListModel = new SpinnerListModel(columnarray); + columnSpinner = new UpperCaseSpinner(columnSpinnerListModel) { + public boolean shouldResponseChangeListener() { + return false; + } + }; + columnSpinner.setPreferredSize(new Dimension(60, 24)); + JFormattedTextField cftf = GUICoreUtils.getSpinnerTextField(columnSpinner); + if (cftf != null) { + cftf.setColumns(3); // specify more width than we need + cftf.setHorizontalAlignment(UITextField.LEFT); + } + + ((AbstractDocument) cftf.getDocument()).setDocumentFilter(new DocumentFilter() { + public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { + fb.insertString(offset, string.toUpperCase(), attr); + } + + public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException { + if (string != null) { + string = string.toUpperCase(); + } + fb.replace(offset, length, string, attr); + } + }); + } + + protected void addDocumentListener(DocumentListener l) { + ((DefaultEditor) columnSpinner.getEditor()).getTextField().getDocument().addDocumentListener(l); + ((DefaultEditor) rowSpinner.getEditor()).getTextField().getDocument().addDocumentListener(l); + } + + private void removeDocumentListener(DocumentListener l) { + ((DefaultEditor) columnSpinner.getEditor()).getTextField().getDocument().removeDocumentListener(l); + ((DefaultEditor) rowSpinner.getEditor()).getTextField().getDocument().removeDocumentListener(l); + } + + /** + * columnSpinner与rowSpinner应该整体考虑,设置ColumnRow应该只触发一次事件 + * + * @param columnRow + */ + public void setColumnRow(ColumnRow columnRow) { + if (!ComparatorUtils.equals(cr, columnRow)) { + setGlobalName(); + removeDocumentListener(d); + cr = columnRow; + addDocumentListener(d); + fireChanged(); + } + } + + public void setGlobalName(){ + + } + + public void populate(ColumnRow columnRow) { + cr = columnRow; + int column = columnRow.getColumn(); + if (column < 0) { + column = 0; + } + removeDocumentListener(d); + columnSpinner.setValue(StableUtils.convertIntToABC(column + 1)); + int row = columnRow.getRow(); + // shoc 小于0就蹦了 + if (row < 0) { + row = 0; + } + rowSpinner.setValue("" + (row + 1)); + addDocumentListener(d); + fireChanged(); + } + + + public ColumnRow update() { + return cr; + } + + /** + * 添加一个listener到listenerList中 + * @param l 监听 + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + * 从listenerList中移除一个listener + * @param l 监听 + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + // august: Process the listeners last to first + protected void fireChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + /** + * 给组件登记一个观察者监听事件 + * @param listener 监听 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * 组件是否需要响应添加的观察者事件 + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/columnrow/ColumnRowVerticalPane.java b/designer_base/src/com/fr/design/gui/columnrow/ColumnRowVerticalPane.java new file mode 100644 index 0000000000..0b68ededf5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/columnrow/ColumnRowVerticalPane.java @@ -0,0 +1,43 @@ +package com.fr.design.gui.columnrow; + +import java.awt.BorderLayout; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; + + +/** + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2011-12-29 下午02:28:43 + * 类说明: 行列选择界面 只是和ColumnRowPane的布局不同. + */ +public class ColumnRowVerticalPane extends ColumnRowPane { + + private static final long serialVersionUID = 2222494927594030309L; + + public ColumnRowVerticalPane( ) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel pane = FRGUIPaneFactory.createYBoxEmptyBorderPane(); + this.add(pane, BorderLayout.NORTH); + + JPanel colPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + colPane.add(new UILabel(Inter.getLocText("Column") + ":")); + pane.add(colPane); + + initColSpinner(); + colPane.add(columnSpinner); + + JPanel rowPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + pane.add(rowPane); + + rowPane.add(new UILabel(Inter.getLocText("Row") + ":")); + initRowSpinner(); + rowPane.add(rowSpinner); + + this.addDocumentListener(d); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/AbstractNameableCreator.java b/designer_base/src/com/fr/design/gui/controlpane/AbstractNameableCreator.java new file mode 100644 index 0000000000..36a760b5b1 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/AbstractNameableCreator.java @@ -0,0 +1,111 @@ +package com.fr.design.gui.controlpane; + +import com.fr.base.BaseUtils; +import com.fr.design.beans.BasicBeanPane; +import com.fr.general.ComparatorUtils; +import com.fr.general.NameObject; + +import javax.swing.*; + + +public abstract class AbstractNameableCreator implements NameableCreator { + protected String menuName; + protected Icon menuIcon; + protected Class clazzOfObject; + protected Class clazzOfInitCase; + protected Class clazzOfEditor; + + public AbstractNameableCreator(String menuName, Class clazz, Class clazzOfEditor) { + this.menuName = menuName; + this.clazzOfObject = clazz; + this.clazzOfInitCase = clazz; + this.clazzOfEditor = clazzOfEditor; + } + + public AbstractNameableCreator(String menuName, String iconPath, Class clazz) { + this.menuName = menuName; + this.menuIcon = BaseUtils.readIcon(iconPath); + this.clazzOfObject = clazz; + this.clazzOfInitCase = clazz; + } + + public AbstractNameableCreator(String menuName, String iconPath, Class clazz, Class clazzOfEditor) { + this.menuName = menuName; + this.menuIcon = BaseUtils.readIcon(iconPath); + this.clazzOfObject = clazz; + this.clazzOfEditor = clazzOfEditor; + this.clazzOfInitCase = clazz; + } + + public AbstractNameableCreator(String menuName, String iconPath, Class clazz, Class clazz4Init, Class clazzOfEditor) { + this.menuName = menuName; + this.menuIcon = BaseUtils.readIcon(iconPath); + this.clazzOfObject = clazz; + this.clazzOfEditor = clazzOfEditor; + this.clazzOfInitCase = clazz; + this.clazzOfInitCase = clazz4Init; + } + + /** + * get menuName + * @return + */ + public String menuName() { + return this.menuName; + } + + /** + * get menuIcon + * @return + */ + public Icon menuIcon() { + return this.menuIcon; + } + + /** + * get clazzOfEditor + * @return + */ + public Class getUpdatePane() { + return this.clazzOfEditor; + } + + /** + * + * @param ob + * @return + */ + public Object acceptObject2Populate(Object ob) { + if (ob instanceof NameObject) { + ob = ((NameObject)ob).getObject(); + } + if (clazzOfObject != null && clazzOfObject.isInstance(ob)) { + doSthChanged4Icon(ob); + return ob; + } + + return null; + } + + protected void doSthChanged4Icon(Object ob){ + + } + + /** + * + * @return + */ + public String createTooltip(){ + return null; + } + + public boolean isNeedParameterWhenPopulateJControlPane(){ + return false; + } + + public boolean equals(Object obj) { + return obj instanceof AbstractNameableCreator + && ComparatorUtils.equals(menuName, ((AbstractNameableCreator) obj).menuName) + && ComparatorUtils.equals(clazzOfObject, ((AbstractNameableCreator) obj).clazzOfObject); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/ControlPane.java b/designer_base/src/com/fr/design/gui/controlpane/ControlPane.java new file mode 100644 index 0000000000..1b7de127be --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/ControlPane.java @@ -0,0 +1,38 @@ +package com.fr.design.gui.controlpane; + +import java.util.Enumeration; + +import javax.swing.JTree; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import com.fr.design.dialog.BasicPane; + +public abstract class ControlPane extends BasicPane{ + + public void expandAll(JTree tree, boolean expand) { + TreeNode root = (TreeNode) tree.getModel().getRoot(); + expandAll(tree, new TreePath(root), expand); + } + + private void expandAll(JTree tree, TreePath parent, boolean expand) { + // Traverse children + TreeNode node = (TreeNode) parent.getLastPathComponent(); + if (node.getChildCount() >= 0) { + for (Enumeration e = node.children(); e.hasMoreElements();) { + TreeNode n = (TreeNode) e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + expandAll(tree, path, expand); + } + } + + // Expansion or collapse must be done bottom-up + if (expand) { + tree.expandPath(parent); + } else { + tree.collapsePath(parent); + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/JControlPane.java b/designer_base/src/com/fr/design/gui/controlpane/JControlPane.java new file mode 100644 index 0000000000..e58a136150 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/JControlPane.java @@ -0,0 +1,1026 @@ +package com.fr.design.gui.controlpane; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.design.data.tabledata.tabledatapane.GlobalMultiTDTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.GlobalTreeTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.MultiTDTableDataPane; +import com.fr.design.data.tabledata.tabledatapane.TreeTableDataPane; +import com.fr.design.actions.UpdateAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.gui.ilist.JNameEdList; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.design.gui.ilist.ModNameActionListener; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.menu.*; +import com.fr.design.dialog.BasicPane; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Nameable; +import com.fr.stable.core.PropertyChangeAdapter; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Comparator; + +public abstract class JControlPane extends BasicPane implements UnrepeatedNameHelper { + public static final String LIST_NAME = "JControl_List"; + private static final int SHORT_WIDTH = 30; //每加一个short Divider位置加30 + + private ShortCut4JControlPane[] shorts; + private NameableCreator[] creators; + protected JNameEdList nameableList; + protected JControlUpdatePane controlUpdatePane; + + private ToolBarDef toolbarDef; + private UIToolbar toolBar; + + // peter:这是整体的一个cardLayout Pane + private CardLayout cardLayout; + private JPanel cardPane; + protected int editingIndex; + protected String selectedName; + private boolean isNameRepeated = false; + + public JControlPane() { + this.initComponentPane(); + } + + /** + * 生成添加按钮的NameableCreator + * @return 按钮的NameableCreator + */ + public abstract NameableCreator[] createNameableCreators(); + + protected void initComponentPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.creators = this.createNameableCreators(); + this.controlUpdatePane = new JControlUpdatePane(); + + // p: edit card layout + this.cardLayout = new CardLayout(); + cardPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardPane.setLayout(this.cardLayout); + // p:选择的Label + UILabel selectLabel = new UILabel(); + cardPane.add(selectLabel, "SELECT"); + cardPane.add(controlUpdatePane, "EDIT"); + // SplitPane + JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, getLeftPane(), cardPane); + mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor())); + mainSplitPane.setOneTouchExpandable(true); + + this.add(mainSplitPane, BorderLayout.CENTER); + mainSplitPane.setDividerLocation(getLeftPreferredSize()); + this.checkButtonEnabled(); + } + + + protected JPanel getLeftPane(){ + // LeftPane + JPanel leftPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + + initNameList(leftPane); + + shorts = this.createShortcuts(); + if (ArrayUtils.isEmpty(shorts)) { + return leftPane; + } + + toolbarDef = new ToolBarDef(); + for (ShortCut4JControlPane sj : shorts) { + toolbarDef.addShortCut(sj.getShortCut()); + } + toolBar = ToolBarDef.createJToolBar(); + toolbarDef.updateToolBar(toolBar); + leftPane.add(toolBar, BorderLayout.NORTH); + return leftPane; + } + + + private void initNameList(JPanel leftPane) { + nameableList = createJNameList(); + nameableList.setName(LIST_NAME); + leftPane.add(new UIScrollPane(nameableList), BorderLayout.CENTER); + + + nameableList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + nameableList.addMouseListener(listMouseListener); + nameableList.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent evt) { + // richie:避免多次update和populate大大降低效率 + if (!evt.getValueIsAdjusting()) { + // shoc 切换的时候加检验 + if (hasInvalid(false)) { + return; + } + JControlPane.this.controlUpdatePane.update(); + JControlPane.this.controlUpdatePane.populate(); + JControlPane.this.checkButtonEnabled(); + } + } + }); + } + + public JNameEdList createJNameList() { + JNameEdList nameEdList = new JNameEdList(new DefaultListModel()) { + protected void doAfterLostFocus() { + JControlPane.this.updateControlUpdatePane(); + } + }; + nameEdList.setCellRenderer(new NameableListCellRenderer()); + return nameEdList; + } + + public void updateControlUpdatePane() { + controlUpdatePane.update(); + } + + protected void doWhenPopulate(BasicBeanPane beanPane){ + + } + + protected int getLeftPreferredSize() { + return shorts.length * SHORT_WIDTH; + } + + protected ShortCut4JControlPane[] createShortcuts() { + return new ShortCut4JControlPane[]{ + addItemShortCut(), + removeItemShortCut(), + copyItemShortCut(), + moveUpItemShortCut(), + moveDownItemShortCut(), + sortItemShortCut() + }; + } + + protected ShortCut4JControlPane addItemShortCut() { + ShortCut addItemShortCut; + if (creators.length == 1) { + addItemShortCut = new AddItemUpdateAction(creators); + } else { + addItemShortCut = new AddItemMenuDef(creators); + } + return new AbsoluteEnableShortCut(addItemShortCut); + } + + protected ShortCut4JControlPane removeItemShortCut() { + return new NormalEnableShortCut(new RemoveItemAction()); + } + + protected ShortCut4JControlPane copyItemShortCut() { + return new NormalEnableShortCut(new CopyItemAction()); + } + + protected ShortCut4JControlPane moveUpItemShortCut() { + return new NormalEnableShortCut(new MoveUpItemAction()); + } + + protected ShortCut4JControlPane moveDownItemShortCut() { + return new NormalEnableShortCut(new MoveDownItemAction()); + } + + protected ShortCut4JControlPane sortItemShortCut() { + return new NormalEnableShortCut(new SortItemAction()); + } + + public void setNameListEditable(boolean editable) { + this.nameableList.setEditable(editable); + } + + public Nameable[] update() { + java.util.List res = new java.util.ArrayList(); + this.controlUpdatePane.update(); + DefaultListModel listModel = (DefaultListModel) this.nameableList.getModel(); + for (int i = 0, len = listModel.getSize(); i < len; i++) { + res.add(((ListModelElement) listModel.getElementAt(i)).wrapper); + } + + return res.toArray(new Nameable[res.size()]); + } + + public void populate(Nameable[] nameableArray) { + DefaultListModel listModel = (DefaultListModel) this.nameableList.getModel(); + listModel.removeAllElements(); + if (ArrayUtils.isEmpty(nameableArray)) { + return; + } + + for (Nameable aNameableArray : nameableArray) { + listModel.addElement(new ListModelElement(aNameableArray)); + } + + if (listModel.size() > 0) { + this.nameableList.setSelectedIndex(0); + } + this.checkButtonEnabled(); + } + + /** + * 添加名字改变时的listener + * + * @param l 名字改变时的监听 + */ + public void addModNameActionListener(ModNameActionListener l) { + this.nameableList.addModNameActionListener(l); + } + + /** + * 添加Editinglistener + * + * @param l 监听 + */ + public void addEditingListner(PropertyChangeAdapter l) { + this.nameableList.addEditingListner(l); + } + + /* + * 刷新当前的选中的UpdatePane + */ + protected void populateSelectedValue() { + JControlPane.this.controlUpdatePane.populate(); + } + + /** + * 根据name,选中JNameEdList中的item + */ + public void setSelectedName(String name) { + DefaultListModel listModel = (DefaultListModel) this.nameableList.getModel(); + for (int i = 0, len = listModel.getSize(); i < len; i++) { + Nameable item = ((ListModelElement) listModel.getElementAt(i)).wrapper; + if (ComparatorUtils.equals(name, item.getName())) { + this.nameableList.setSelectedIndex(i); + break; + } + } + } + + public String getEditingName() { + return this.nameableList.getEditingName(); + } + + public Object getEditingType() { + return this.nameableList.getAllTypes()[editingIndex]; + } + + public void setWarnigText(int index) { + this.nameableList.setWarnigText(index); + } + + /** + * 获取选中的名字 + */ + public String getSelectedName() { + ListModelElement el = (ListModelElement) this.nameableList.getSelectedValue(); + + return el == null ? null : el.wrapper.getName(); + } + + /** + * 刷新 NameableCreator + * + * @param creators 生成器 + */ + public void refreshNameableCreator(NameableCreator[] creators) { + this.creators = creators; + shorts = this.createShortcuts(); + toolbarDef.clearShortCuts(); + for (ShortCut4JControlPane sj : shorts) { + toolbarDef.addShortCut(sj.getShortCut()); + } + + toolbarDef.updateToolBar(toolBar); + toolBar.validate(); + toolBar.repaint(); + this.repaint(); + } + + protected boolean isNameRepeted(java.util.List[] list, String name) { + for (int i = 0; i < list.length; i++) { + if (list[i].contains(name)) { + isNameRepeated = true; + return true; + } + } + isNameRepeated = false; + return false; + } + + /** + * 名字是否重复 + * @return 重复则返回true + */ + public boolean isNameRepeated() { + return isNameRepeated; + } + + /** + * 添加 Nameable + * + * @param nameable 添加的Nameable + * @param index 序号 + */ + public void addNameable(Nameable nameable, int index) { + JNameEdList nameEdList = JControlPane.this.nameableList; + DefaultListModel model = (DefaultListModel) nameEdList.getModel(); + + ListModelElement el = new ListModelElement(nameable); + model.add(index, el); + nameableList.setSelectedIndex(index); + nameableList.ensureIndexIsVisible(index); + + nameEdList.repaint(); + } + + /** + * 是否重命名 + * @return 是则true + */ + public boolean isContainsRename() { + String rename = Inter.getLocText("FR-Please_Rename") + "!"; + String[] names = this.nameableList.getAllNames(); + for (int i = names.length - 1; i >= 0; i--) { + if (ComparatorUtils.equals(names[i], rename)) { + return true; + } + } + return false; + } + + protected DefaultListModel getModel() { + return (DefaultListModel) JControlPane.this.nameableList.getModel(); + } + + private String createUnrepeatedCopyName(String suffix) { + DefaultListModel model = this.getModel(); + String[] names = new String[model.getSize()]; + for (int i = 0; i < model.size(); i++) { + names[i] = ((ListModelElement) model.get(i)).wrapper.getName(); + } + String lastName = "CopyOf" + suffix; + while (ArrayUtils.contains(names, lastName)) { + lastName = "CopyOf" + lastName; + } + return lastName; + } + + + /** + * 生成不重复的名字 + * + * @param prefix 名字前缀 + * @return 名字 + */ + public String createUnrepeatedName(String prefix) { + DefaultListModel model = this.getModel(); + Nameable[] all = new Nameable[model.getSize()]; + for (int i = 0; i < model.size(); i++) { + all[i] = ((ListModelElement) model.get(i)).wrapper; + } + // richer:生成的名字从1开始. kunsnat: 添加属性从0开始. + int count = all.length + 1; + while (true) { + String name_test = prefix + count; + boolean repeated = false; + for (int i = 0, len = model.size(); i < len; i++) { + Nameable nameable = all[i]; + if (ComparatorUtils.equals(nameable.getName(), name_test)) { + repeated = true; + break; + } + } + + if (!repeated) { + return name_test; + } + + count++; + } + } + + /** + * 增加项的UpdateAction + */ + protected class AddItemUpdateAction extends UpdateAction { + final NameableCreator creator; + + public AddItemUpdateAction(NameableCreator[] creators) { + this.creator = creators[0]; + this.setName(Inter.getLocText("FR-Action_Add")); + this.setMnemonic('A'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/add.png")); + } + + public void actionPerformed(ActionEvent e) { + Nameable nameable = creator.createNameable(JControlPane.this); + + JControlPane.this.addNameable(nameable, getModel().getSize()); + } + } + + /* + * 增加项的MenuDef + */ + protected class AddItemMenuDef extends MenuDef { + public AddItemMenuDef(NameableCreator[] creators) { + this.setName(Inter.getLocText("FR-Action_Add")); + this.setMnemonic('A'); + this.setIconPath("/com/fr/design/images/control/addPopup.png"); + wrapActionListener(creators); + } + + private void wrapActionListener(NameableCreator[] creators) { + for (final NameableCreator creator : creators) { + if (!whetherAdd(creator.menuName())){ + continue; + } + boolean isTrue = ComparatorUtils.equals(creator.menuName(), Inter.getLocText("Datasource-Stored_Procedure")) || + ComparatorUtils.equals(creator.menuName(), Inter.getLocText("DS-Relation_TableData")) || ComparatorUtils.equals(creator.menuName(), Inter.getLocText("DS-Multi_Dimensional_Database")); + if (isTrue) { + this.addShortCut(new LineSeparator()); + } + this.addShortCut(new UpdateAction() { + { + this.setName(creator.menuName()); + Icon icon = creator.menuIcon(); + if (icon != null) { + this.setSmallIcon(icon); + } + } + + public void actionPerformed(ActionEvent e) { + if (hasInvalid(true)) { + return; + } + + Nameable nameable = creator.createNameable(JControlPane.this); + + JControlPane.this.addNameable(nameable, getModel().getSize()); + } + }); + } + } + + private boolean whetherAdd(String itemName){ + JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if (jTemplate == null) { + return false; + } + //先屏蔽掉这个,之后还有别的 + String[] names = {Inter.getLocText("FR-Hyperlink_Chart_Float")}; + for (String name : names){ + if(!jTemplate.isJWorkBook() && ComparatorUtils.equals(itemName, name)){ + return false; + } + } + String formName = Inter.getLocText("Hyperlink-Form_link"); + return !(jTemplate.isJWorkBook() && ComparatorUtils.equals(itemName, formName)); + } + } + + /* + * 移除item + */ + private class RemoveItemAction extends UpdateAction { + public RemoveItemAction() { + this.setName(Inter.getLocText("FR-Action_Remove")); + this.setMnemonic('R'); + this.setSmallIcon(BaseUtils + .readIcon("/com/fr/base/images/cell/control/remove.png")); + } + + public void actionPerformed(ActionEvent evt) { + try { + JControlPane.this.nameableList.getCellEditor() + .stopCellEditing(); + } catch (Exception ignored) { + } + // bug:在选中一个NameObject并删除,会遗留下Name. + doBeforeRemove(); + if (GUICoreUtils.removeJListSelectedNodes(SwingUtilities + .getWindowAncestor(JControlPane.this), nameableList)) { + checkButtonEnabled(); + doAfterRemove(); + } + } + } + + /* + * CopyItem + */ + private class CopyItemAction extends UpdateAction { + public CopyItemAction() { + this.setName(Inter.getLocText("FR-Action_Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils + .readIcon("/com/fr/base/images/cell/control/copy.png")); + } + + public void actionPerformed(ActionEvent evt) { + // p:选中的值. + ListModelElement selectedValue = (ListModelElement) nameableList.getSelectedValue(); + if (selectedValue == null) { + return; + } + + controlUpdatePane.update(); + + Nameable selectedNameable = selectedValue.wrapper; + + // p: 用反射机制实现 + try { + Nameable newNameable = (Nameable) BaseUtils.cloneObject(selectedNameable); + newNameable.setName(createUnrepeatedCopyName(selectedNameable.getName())); + + JControlPane.this.addNameable(newNameable, nameableList.getSelectedIndex() + 1); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } + } + + /* + * 上移Item + */ + private class MoveUpItemAction extends UpdateAction { + public MoveUpItemAction() { + this.setName(Inter.getLocText("Utils-Move_Up")); + this.setMnemonic('U'); + this.setSmallIcon(BaseUtils + .readIcon("/com/fr/design/images/control/up.png")); + } + + public void actionPerformed(ActionEvent evt) { + int selectedIndex = nameableList.getSelectedIndex(); + if (selectedIndex == -1) { + return; + } + + // 上移 + if (selectedIndex > 0) { + DefaultListModel listModel = (DefaultListModel) nameableList + .getModel(); + + Object selecteObj1 = listModel.get(selectedIndex - 1); + listModel.set(selectedIndex - 1, listModel.get(selectedIndex)); + listModel.set(selectedIndex, selecteObj1); + + nameableList.setSelectedIndex(selectedIndex - 1); + nameableList.ensureIndexIsVisible(selectedIndex - 1); + } + } + } + + /* + * 下移Item + */ + private class MoveDownItemAction extends UpdateAction { + public MoveDownItemAction() { + this.setName(Inter.getLocText("Utils-Move_Down")); + this.setMnemonic('D'); + this.setSmallIcon(BaseUtils + .readIcon("/com/fr/design/images/control/down.png")); + } + + public void actionPerformed(ActionEvent evt) { + int selectedIndex = nameableList.getSelectedIndex(); + if (selectedIndex == -1) { + return; + } + + if (selectedIndex < nameableList.getModel().getSize() - 1) { + DefaultListModel listModel = (DefaultListModel) nameableList + .getModel(); + + Object selecteObj1 = listModel.get(selectedIndex + 1); + listModel.set(selectedIndex + 1, listModel.get(selectedIndex)); + listModel.set(selectedIndex, selecteObj1); + + nameableList.setSelectedIndex(selectedIndex + 1); + nameableList.ensureIndexIsVisible(selectedIndex + 1); + } + } + } + + private class SortItemAction extends UpdateAction { + private boolean isAtoZ = false; + + public SortItemAction() { + this.setName(Inter.getLocText("FR-Action_Sort")); + this.setMnemonic('S'); + this.setSmallIcon(BaseUtils + .readIcon("/com/fr/design/images/control/sortAsc.png")); + } + + public void actionPerformed(ActionEvent evt) { + // p:选中的值. + Object selectedValue = nameableList.getSelectedValue(); + + DefaultListModel listModel = (DefaultListModel) nameableList + .getModel(); + Nameable[] nameableArray = new Nameable[listModel.getSize()]; + if (nameableArray.length <= 0) { + return; + } + + for (int i = 0; i < listModel.getSize(); i++) { + nameableArray[i] = ((ListModelElement) listModel.getElementAt(i)).wrapper; + } + + // p:排序. + if (isAtoZ) { + Comparator nameableComparator = new Comparator() { + public int compare(Nameable o1, Nameable o2) { + return -ComparatorUtils.compare(o1.getName(), o2 + .getName()); + } + }; + isAtoZ = !isAtoZ; + Arrays.sort(nameableArray, nameableComparator); + } else { + Comparator nameableComparator = new Comparator() { + public int compare(Nameable o1, Nameable o2) { + return ComparatorUtils.compare(o1.getName(), o2 + .getName()); + } + }; + isAtoZ = !isAtoZ; + Arrays.sort(nameableArray, nameableComparator); + } + + for (int i = 0; i < nameableArray.length; i++) { + listModel.set(i, new ListModelElement(nameableArray[i])); + } + + // p:需要选中以前的那个值. + if (selectedValue != null) { + nameableList.setSelectedValue(selectedValue, true); + } + + checkButtonEnabled(); + // p:需要repaint. + nameableList.repaint(); + } + } + + /* + * JNameEdList的鼠标事件 + */ + private MouseListener listMouseListener = new MouseAdapter() { + public void mouseReleased(MouseEvent evt) { + nameableList.stopEditing(); + if (evt.getClickCount() >= 2 + && SwingUtilities.isLeftMouseButton(evt)) { + editingIndex = nameableList.getSelectedIndex(); + selectedName = nameableList.getNameAt(editingIndex); + nameableList.editItemAt(nameableList.getSelectedIndex()); + } + // peter:处理右键的弹出菜单 + if (!SwingUtilities.isRightMouseButton(evt)) { + return; + } + + // peter: 注意,在checkButtonEnabled()方法里面,设置了所有的Action的Enabled. + checkButtonEnabled(); + + // p:右键菜单. + JPopupMenu popupMenu = new JPopupMenu(); + + for (ShortCut4JControlPane sj : shorts) { + sj.getShortCut().intoJPopupMenu(popupMenu); + } + + // peter: 只有弹出菜单有子菜单的时候,才需要弹出来. + GUICoreUtils.showPopupMenu(popupMenu, nameableList, evt.getX() - 1, + evt.getY() - 1); + } + + public void mouseMoved(MouseEvent e) { + + } + }; + + /** + * 检查按钮可用状态 Check button enabled. + */ + public void checkButtonEnabled() { + int selectedIndex = nameableList.getSelectedIndex(); + if (selectedIndex == -1) { + this.cardLayout.show(cardPane, "SELECT"); + } else { + this.cardLayout.show(cardPane, "EDIT"); + } + for (ShortCut4JControlPane sj : this.shorts) { + sj.checkEnable(); + } + } + + protected void doBeforeRemove(){ + + } + + protected void doAfterRemove(){ + + } + + public NameableCreator[] creators() { + return creators == null ? new NameableCreator[0] : creators; + } + + /* + * Nameable的ListCellRenerer + */ + private class NameableListCellRenderer extends + DefaultListCellRenderer { + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, + cellHasFocus); + + if (value instanceof ListModelElement) { + Nameable wrappee = ((ListModelElement) value).wrapper; + this.setText(((ListModelElement) value).wrapper.getName()); + + boolean iconSet = false; + for (NameableCreator creator : JControlPane.this.creators) { + if (creator.menuIcon() != null && creator.acceptObject2Populate(wrappee) != null) { + this.setIcon(creator.menuIcon()); + this.setToolTipText(creator.createTooltip()); + iconSet = true; + break; + } + } + if (!iconSet) { + this.setIcon(BaseUtils.readIcon("/com/fr/base/images/oem/cpt.png")); + } + } + + return this; + } + } + + public class AbsoluteEnableShortCut extends ShortCut4JControlPane { + public AbsoluteEnableShortCut(ShortCut shortCut) { + this.shortCut = shortCut; + } + + /** + * 检查是否可用 + */ + public void checkEnable() { + this.shortCut.setEnabled(true); + } + } + + public class NormalEnableShortCut extends ShortCut4JControlPane { + public NormalEnableShortCut(ShortCut shortCut) { + this.shortCut = shortCut; + } + + /** + * 检查是否可用 + */ + public void checkEnable() { + this.shortCut.setEnabled(getModel() + .getSize() > 0 + && JControlPane.this.nameableList.getSelectedIndex() != -1); + } + } + + public class SortEnableShortCut extends ShortCut4JControlPane { + public SortEnableShortCut(ShortCut shortCut) { + this.shortCut = shortCut; + } + + /** + * 检查是否可用 + */ + @Override + public void checkEnable() { + this.shortCut.setEnabled(getModel().getSize() > 1); + } + + } + + public class MoveUpEnableShortCut extends ShortCut4JControlPane { + public MoveUpEnableShortCut(ShortCut shortCut) { + this.shortCut = shortCut; + } + + /** + * 检查是否可用 + */ + @Override + public void checkEnable() { + this.shortCut.setEnabled(getModel().getSize() > 1 + && JControlPane.this.nameableList.getSelectedIndex() > 0); + } + + } + + public class MoveDownEnableShortCut extends ShortCut4JControlPane { + public MoveDownEnableShortCut(ShortCut shortCut) { + this.shortCut = shortCut; + } + + /** + * 检查是否可用 + */ + @Override + public void checkEnable() { + this.shortCut.setEnabled(getModel().getSize() > 1 + && JControlPane.this.nameableList.getSelectedIndex() < JControlPane.this.nameableList.getModel().getSize() - 1); + } + + } + + private class JControlUpdatePane extends JPanel { + private CardLayout card; + private JPanel cardPane; + private BasicBeanPane[] updatePanes; + + private ListModelElement elEditing; + + public JControlUpdatePane() { + initUpdatePane(); + } + + private void initUpdatePane() { + if (creators == null) { + return; + } + card = new CardLayout(); + cardPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + cardPane.setLayout(card); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(cardPane); + int len = creators.length; + updatePanes = new BasicBeanPane[len]; + } + + public void populate() { + ListModelElement el = (ListModelElement) JControlPane.this.nameableList.getSelectedValue(); + if (el == null) { + return; + } + + elEditing = el; + + for (int i = 0, len = updatePanes.length; i < len; i++) { + Object ob2Populate = creators[i].acceptObject2Populate(el.wrapper); + if (ob2Populate != null) { + if (updatePanes[i] == null) { + if (isMulti(creators[i].getUpdatePane()) || isTree(creators[i].getUpdatePane())) { + updatePanes[i] = createPaneByCreators(creators[i], el.wrapper.getName()); + } else { + updatePanes[i] = createPaneByCreators(creators[i]); + } + cardPane.add(updatePanes[i], String.valueOf(i)); + } + card.show(cardPane, String.valueOf(i)); + updatePanes[i].populateBean(ob2Populate); + doWhenPopulate(updatePanes[i]); + break; + } + } + } + + public boolean isMulti(Class _class){ + return ComparatorUtils.equals(_class, GlobalMultiTDTableDataPane.class) || ComparatorUtils.equals(_class, MultiTDTableDataPane.class); + } + + public boolean isTree(Class _class){ + return ComparatorUtils.equals(_class, GlobalTreeTableDataPane.class) || ComparatorUtils.equals(_class, TreeTableDataPane.class); + } + + public void update() { + for (int i = 0; i < updatePanes.length; i++) { + BasicBeanPane pane = updatePanes[i]; + + if (pane != null && pane.isVisible()) { + Object bean = pane.updateBean(); + if (i < JControlPane.this.creators.length) { + JControlPane.this.creators[i].saveUpdatedBean(elEditing, bean); + } + } + } + } + + public void checkValid() throws Exception { + if (updatePanes != null) { + for (int i = 0; i < updatePanes.length; i++) { + if (updatePanes[i] != null) { + updatePanes[i].checkValid(); + } + } + } + } + } + + protected BasicBeanPane createPaneByCreators(NameableCreator creator) { + try { + return creator.getUpdatePane().newInstance(); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + protected BasicBeanPane createPaneByCreators(NameableCreator creator, String string) { + Constructor constructor = null; + try { + constructor = creator.getUpdatePane().getDeclaredConstructor(new Class[]{String.class}); + constructor.setAccessible(true); + return (BasicBeanPane) constructor.newInstance(string); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + + } + + // 选项添加个数有限制等情况下 要求能控制快捷按钮的状态 + protected void setToolbarDefEnable(int shortCutIndex, int itemIndex, boolean enabled) { + if (this.toolbarDef.getShortCutCount() > shortCutIndex) { + ShortCut sc = this.toolbarDef.getShortCut(shortCutIndex); + if (sc instanceof AddItemMenuDef) { + AddItemMenuDef am = (AddItemMenuDef) sc; + if (am.getShortCutCount() > itemIndex) { + am.getShortCut(itemIndex).setEnabled(enabled); + } + } + } + } + + /** + * 检查是否符合规范 + * + * @throws Exception + */ + public void checkValid() throws Exception { + this.controlUpdatePane.checkValid(); + } + + private int getInValidIndex() { + BasicBeanPane[] p = controlUpdatePane.updatePanes; + if (p != null) { + for (int i = 0; i < p.length; i++) { + if (p[i] != null) { + try { + p[i].checkValid(); + } catch (Exception e) { + return i; + } + } + } + } + return -1; + } + + private boolean hasInvalid(boolean isAdd) { + int idx = JControlPane.this.getInValidIndex(); + if (isAdd || nameableList.getSelectedIndex() != idx) { + try { + checkValid(); + } catch (Exception exp) { + JOptionPane.showMessageDialog(JControlPane.this, exp.getMessage()); + nameableList.setSelectedIndex(idx); + return true; + } + } + return false; + } + + + /** + * 设置选中项 + * + * @param index 选中项的序列号 + */ + public void setSelectedIndex(int index) { + nameableList.setSelectedIndex(index); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/NameObjectCreator.java b/designer_base/src/com/fr/design/gui/controlpane/NameObjectCreator.java new file mode 100644 index 0000000000..e7697183af --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/NameObjectCreator.java @@ -0,0 +1,54 @@ +package com.fr.design.gui.controlpane; + +import com.fr.general.NameObject; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.stable.Nameable; + + +public class NameObjectCreator extends AbstractNameableCreator { + + /* + * alex:这里的构造函数为什么传Class而不是传实例呢? + * 因为不应该NameObjectCreator初始化的时候就把BasicBeanPane初始化,而应该在需要用到这个面板的时候再做BasicBeanPane的初始化操作 + */ + public NameObjectCreator(String menuName, Class clazz, Class updatePane) { + super(menuName, clazz, updatePane); + } + + public NameObjectCreator(String menuName, String iconPath, Class clazz) { + super(menuName, iconPath, clazz); + } + + public NameObjectCreator(String menuName, String iconPath, Class clazz, Class updatePane) { + super(menuName, iconPath, clazz, updatePane); + } + + public NameObjectCreator(String menuName, String iconPath, Class clazz, Class clazz4Init, Class updatePane) { + super(menuName, iconPath, clazz, clazz4Init, updatePane); + } + + /** + * create Nameable + * @param helper + * @return + */ + public Nameable createNameable(UnrepeatedNameHelper helper) { + try { + return new NameObject(helper.createUnrepeatedName(this.menuName()), clazzOfInitCase.newInstance()); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * save update bean + * @param wrapper + * @param bean + */ + public void saveUpdatedBean(ListModelElement wrapper, Object bean) { + ((NameObject)wrapper.wrapper).setObject(bean); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/NameableCreator.java b/designer_base/src/com/fr/design/gui/controlpane/NameableCreator.java new file mode 100644 index 0000000000..f497be1e6c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/NameableCreator.java @@ -0,0 +1,25 @@ +package com.fr.design.gui.controlpane; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.stable.Nameable; + +import javax.swing.*; + +public interface NameableCreator { + public String menuName(); + + public Icon menuIcon(); + + public String createTooltip(); + + public Nameable createNameable(UnrepeatedNameHelper helper); + + public Class getUpdatePane(); + + public Object acceptObject2Populate(Object ob); + + public void saveUpdatedBean(ListModelElement wrapper, Object bean); + + public boolean isNeedParameterWhenPopulateJControlPane(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/NameableSelfCreator.java b/designer_base/src/com/fr/design/gui/controlpane/NameableSelfCreator.java new file mode 100644 index 0000000000..4b06b74ca4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/NameableSelfCreator.java @@ -0,0 +1,23 @@ +package com.fr.design.gui.controlpane; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ilist.ListModelElement; +import com.fr.stable.Nameable; + + +public abstract class NameableSelfCreator extends AbstractNameableCreator { + + public NameableSelfCreator(String menuName, Class clazz, Class updatePane) { + super(menuName, clazz, updatePane); + } + + public NameableSelfCreator(String menuName, String iconPath, Class clazz, Class updatePane) { + super(menuName, iconPath, clazz, updatePane); + } + + @Override + public void saveUpdatedBean(ListModelElement wrapper, Object bean) { + wrapper.wrapper = (Nameable)bean; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/ObjectJControlPane.java b/designer_base/src/com/fr/design/gui/controlpane/ObjectJControlPane.java new file mode 100644 index 0000000000..fb944b93b5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/ObjectJControlPane.java @@ -0,0 +1,76 @@ +package com.fr.design.gui.controlpane; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.fr.design.beans.BasicBeanPane; + +/** + * 生成带参数的BasicBeanPane + * + * @author zhou + * @since 2012-4-5上午9:29:20 + */ +public abstract class ObjectJControlPane extends JControlPane { + private Object object; + + public ObjectJControlPane() { + this(null); + } + + public ObjectJControlPane(Object object) { + super(); + this.object = object; + } + + @Override + protected BasicBeanPane createPaneByCreators(NameableCreator creator) { + try { + if (object == null) { + return super.createPaneByCreators(creator); + } else if (object.getClass().isArray()) { + return creator.getUpdatePane().getConstructor(object.getClass()).newInstance(object); + } else { + Constructor constructor = getConstructor(creator.getUpdatePane(), object.getClass()); + return constructor == null ? super.createPaneByCreators(creator) : constructor.newInstance(object); + } + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + /** + * 传进BasicBeanPane的构造函数的参数,可能是 + * + * @param clazz + * @param cls + * @return + */ + private Constructor getConstructor(Class clazz, Class cls) { + Constructor constructor = null; + try { + constructor = clazz.getConstructor(cls); + } catch (SecurityException e) { + } catch (NoSuchMethodException e) { + } + if (constructor != null) { + return constructor; + } else { + if (cls.getName() == Object.class.getName()) { + return null; + } + return getConstructor(clazz, cls.getSuperclass()); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/ShortCut4JControlPane.java b/designer_base/src/com/fr/design/gui/controlpane/ShortCut4JControlPane.java new file mode 100644 index 0000000000..ec6e876347 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/ShortCut4JControlPane.java @@ -0,0 +1,16 @@ +package com.fr.design.gui.controlpane; + +import com.fr.design.menu.ShortCut; + +public abstract class ShortCut4JControlPane { + protected ShortCut shortCut; + + public ShortCut getShortCut() { + return shortCut; + } + + /** + * 检查是否可用 + */ + public abstract void checkEnable(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/controlpane/UnrepeatedNameHelper.java b/designer_base/src/com/fr/design/gui/controlpane/UnrepeatedNameHelper.java new file mode 100644 index 0000000000..b5c6541d0a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/controlpane/UnrepeatedNameHelper.java @@ -0,0 +1,5 @@ +package com.fr.design.gui.controlpane; + +public interface UnrepeatedNameHelper { + public String createUnrepeatedName(String prefix); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/CustomWidgetOption.java b/designer_base/src/com/fr/design/gui/core/CustomWidgetOption.java new file mode 100644 index 0000000000..7aee33dab4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/CustomWidgetOption.java @@ -0,0 +1,48 @@ +package com.fr.design.gui.core; + +import javax.swing.Icon; + +import com.fr.base.FRContext; +import com.fr.form.ui.Widget; + +public class CustomWidgetOption extends WidgetOption { + private static final long serialVersionUID = -8144214820100962842L; + private String optionName; + private Icon optionIcon; + private Class widgetClass; + + public CustomWidgetOption(String optionName, Icon optionIcon, Class widgetClass) { + this.optionName = optionName; + this.optionIcon = optionIcon; + this.widgetClass = widgetClass; + } + @Override + public Widget createWidget() { + Class cls = widgetClass(); + try { + Widget ins = cls.newInstance(); + return ins ; + } catch (InstantiationException e) { + FRContext.getLogger().error(e.getMessage(), e); + } catch (IllegalAccessException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + return null; + } + @Override + public String optionName() { + return this.optionName; + } + + @Override + public Icon optionIcon() { + return this.optionIcon; + } + + @Override + public Class widgetClass() { + return this.widgetClass; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/UIFurtherTabComponent.java b/designer_base/src/com/fr/design/gui/core/UIFurtherTabComponent.java new file mode 100644 index 0000000000..7dc6d615f5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/UIFurtherTabComponent.java @@ -0,0 +1,24 @@ +package com.fr.design.gui.core; + +/** + * 带render功能 + * + * @author zhou + * @since 2012-5-28下午4:27:24 + */ +public interface UIFurtherTabComponent extends UITabComponent { + + /** + * set the SelectedItem by the element + * + * @param ob + */ + public void setSelectedItem(T element); + + /** + * get the SelectedItem + * + * @return + */ + public T getSelectedItem(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/UISelectedComponent.java b/designer_base/src/com/fr/design/gui/core/UISelectedComponent.java new file mode 100644 index 0000000000..b28275f8f5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/UISelectedComponent.java @@ -0,0 +1,32 @@ +package com.fr.design.gui.core; + +import javax.swing.event.ChangeListener; + +/** + * 这个接口说明一个基本组件是可以选择的 + * + * @author zhou + * @since 2012-5-17下午4:38:17 + */ +public interface UISelectedComponent { + /** + * isSelected + * + * @return + */ + public boolean isSelected(); + + /** + * setSelected + * + * @param isSelected + */ + public void setSelected(boolean isSelected); + + /** + * the selected changed listener + * @param l + */ + void addChangeListener(ChangeListener l); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/UITabComponent.java b/designer_base/src/com/fr/design/gui/core/UITabComponent.java new file mode 100644 index 0000000000..5d7fc8b3be --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/UITabComponent.java @@ -0,0 +1,35 @@ +package com.fr.design.gui.core; + +import javax.swing.event.ChangeListener; + +/** + * 这个接口说明一个基本组件是类似于tabbedpane的形式 + * + * @author zhou + * @since 2012-5-17下午4:46:00 + */ +public interface UITabComponent { + /** + * 获取当前选中的tab + * + * @return + */ + public int getSelectedIndex(); + + /** + * 设置选中的tab + * + * @param newSelectedIndex + */ + public void setSelectedIndex(int newSelectedIndex); + + /** + * Adds a ChangeListener to the listener list. + */ + public void addChangeListener(ChangeListener l); + + /** + * removes a ChangeListener from the listener list. + */ + public void removeChangeListener(ChangeListener l); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/UserDefinedWidgetOption.java b/designer_base/src/com/fr/design/gui/core/UserDefinedWidgetOption.java new file mode 100644 index 0000000000..6347309f3c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/UserDefinedWidgetOption.java @@ -0,0 +1,36 @@ +package com.fr.design.gui.core; + +import javax.swing.Icon; + +import com.fr.base.BaseUtils; +import com.fr.form.ui.NameWidget; +import com.fr.form.ui.Widget; + +public class UserDefinedWidgetOption extends WidgetOption { + + private String widgetConfigName; + + public UserDefinedWidgetOption(String name) { + this.widgetConfigName = name; + } + + @Override + public Widget createWidget() { + return new NameWidget(widgetConfigName); + } + + @Override + public Icon optionIcon() { + return BaseUtils.readIcon("/com/fr/design/images/data/user_widget.png"); + } + + @Override + public String optionName() { + return widgetConfigName; + } + + @Override + public Class widgetClass() { + return NameWidget.class; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/WidgetConstants.java b/designer_base/src/com/fr/design/gui/core/WidgetConstants.java new file mode 100644 index 0000000000..633a85ebf3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/WidgetConstants.java @@ -0,0 +1,78 @@ +package com.fr.design.gui.core; + +import com.fr.general.Inter; + +public class WidgetConstants { + + //没有控件 + public static final int NONE = -1; + + // TextEditor + public static final int TEXT = 0; + + // ComboBox + public static final int COMBOBOX = 1; + // NumberEditor + public static final int NUMBER = 2; + + // DateEditor + public static final int DATE = 3; + + public static final int COMBOCHECKBOX = 5; + + // TreeEditor + public static final int TREE = 6; + + // TreeComboBoxEditor + public static final int TREECOMBOBOX = 7; + + // ListEditor + public static final int LIST = 8; + + public static final int RADIO = 9; + + public static final int RADIOGROUP = 10; + // CheckBox + public static final int CHECKBOX = 11; + // CheckBoxGroup + public static final int CHECKBOXGROUP = 12; + + // FileEditor +// public static final int FILE = 13; +// public static final String NAME_FILE = Inter.getLocText("File"); + + public static final int BUTTON = 14; + + // TextArea & Password + public static final int TEXTAREA = 15; + + public static final int PASSWORD = 16; + + public static final int TABLETREE = 17; + + public static final int IFRAME = 18; + + public static final int MULTI_FILE = 19; + + // 默认控件 + public static final String DEFAULT_WIDGETCONFIG = Inter.getLocText("Widget-Form_Widget_Config"); + + // 报表控件,与默认控件不同,比如label,table,SEARCH等,这里是不需要的 + public static final String REPORT_WIDGETCONFIG = Inter.getLocText("Widget-Default_Widget_Config"); + + public static final String FORM_CHARTWIDGET = Inter.getLocText("Widget-Chart_Widget_Config"); + + // 表单容器控件 + public static final String FORM_WIDGETCONTAINER = Inter.getLocText("Widget-Form_Widget_Container"); + + public static final String POLY_REPORT_WIDGET = Inter.getLocText("Poly-Report_Component"); + // 服务器预定义控件 + public static final String USER_DEFINED_WIDGETCONFIG = Inter.getLocText("Widget-User_Defined_Widget_Config"); + + // 服务器组合控件 + public static final String COMB_WIDGETCONFIG = Inter.getLocText("Widget-Comb_Widget_Config"); + + // 服务器自定义控件 + public static final String CUSTOM_WIDGETCONFIG = Inter.getLocText("Widget-Custom_Widget_Config"); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/WidgetOption.java b/designer_base/src/com/fr/design/gui/core/WidgetOption.java new file mode 100644 index 0000000000..e6326aa252 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/WidgetOption.java @@ -0,0 +1,228 @@ +package com.fr.design.gui.core; + +import com.fr.base.BaseUtils; +import com.fr.form.ui.*; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import java.io.Serializable; +import java.util.ArrayList; + +public abstract class WidgetOption implements Serializable { + + private static final long serialVersionUID = -5213215153654191184L; + + private static final java.util.List STATIC_WIDGET_OPTION_LIST = new java.util.ArrayList(); + + public WidgetOption() { + STATIC_WIDGET_OPTION_LIST.add(this); + } + + /** + * 名字 + * + * @return 名字 + */ + public abstract String optionName(); + + /** + * 图标 + * + * @return 图标 + */ + public abstract Icon optionIcon(); + + /** + * 类 + * + * @return 类 + */ + public abstract Class widgetClass(); + + /** + * 创建控件 + * + * @return 控件 + */ + public abstract Widget createWidget(); + + public boolean equals(Object obj) { + return obj instanceof WidgetOption && ComparatorUtils.equals(((WidgetOption) obj).optionName(), optionName()); + } + + /** + * 这个name的hashcode + * + * @return 这个name的hashcode + */ + public int hashCode() { + return optionName().hashCode(); + } + + public static WidgetOption getToolBarButton(Class cls) { + for (int i = 0, len = STATIC_WIDGET_OPTION_LIST.size(); i < len; i++) { + if (STATIC_WIDGET_OPTION_LIST.get(i).widgetClass() == cls) { + return STATIC_WIDGET_OPTION_LIST.get(i); + } + } + return null; + } + + public static String getWidgetType(Widget widget) { + WidgetOption wo = getToolBarButton(widget.getClass()); + return wo == null ? null : wo.optionName(); + } + + public static Icon getWidgetIcon(Widget widget) { + WidgetOption wo = getToolBarButton(widget.getClass()); + return wo == null ? null : wo.optionIcon(); + } + + /* + * 预定义控件 + */ + public static WidgetOption[] getPredefinedWidget() { + java.util.List list = new ArrayList(); + WidgetManagerProvider mgr = WidgetManager.getProviderInstance(); + java.util.Iterator nameIt = mgr.getWidgetConfigNameIterator(); + while (nameIt.hasNext()) { + String name = nameIt.next(); + WidgetConfig widgetConfig = mgr.getWidgetConfig(name); + if (widgetConfig instanceof UserDefinedWidgetConfig) { + list.add(WidgetOptionFactory.createByWidgetClass(name, BaseUtils.readIcon("/com/fr/design/images/data/user_widget.png"), + ((UserDefinedWidgetConfig) widgetConfig).getWidget().getClass())); + } + } + return list.toArray(new WidgetOption[list.size()]); + } + + /* + * 应用与报表设计的控件 + */ + public static WidgetOption[] getReportWidgetInstance() { + return new WidgetOption[]{TEXTEDITOR, TEXTAREA, NUMBEREDITOR, PASSWORD, BUTTON, CHECKBOX, RADIOGROUP, CHECKBOXGROUP, COMBOBOX, + COMBOCHECKBOX, DATEEDITOR, MULTI_FILEEDITOR, LIST, IFRAMEDITOR, TREECOMBOBOX, TREE}; + } + + + /** + * 报表工具栏的控件 + * + * @return 报表工具栏控件 + */ + public static WidgetOption[] getReportParaWidgetIntance() { + return new WidgetOption[]{TEXTEDITOR, LABEL, FREEBUTTON, COMBOBOX, COMBOCHECKBOX, DATEEDITOR, + NUMBEREDITOR, TREECOMBOBOX, RADIOGROUP, CHECKBOXGROUP, TEXTAREA, PASSWORD, CHECKBOX, TREE}; + } + + /** + * 表单工具栏控件 + * + * @return 表单工具栏控件 + */ + public static WidgetOption[] getFormWidgetIntance() { + return new WidgetOption[]{TEXTEDITOR, LABEL, FREEBUTTON, COMBOBOX, COMBOCHECKBOX, DATEEDITOR, + NUMBEREDITOR, TREECOMBOBOX, RADIOGROUP, CHECKBOXGROUP, TEXTAREA, PASSWORD, CHECKBOX, TREE, MULTI_FILEEDITOR}; + } + + public static final WidgetOption DATEEDITOR = WidgetOptionFactory.createByWidgetClass(Inter.getLocText(new String[]{"Date", "Widget"}), + BaseUtils.readIcon("/com/fr/web/images/form/resources/date_16.png"), + DateEditor.class); + + public static final WidgetOption TREE = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("Form-View_Tree"), + BaseUtils.readIcon("/com/fr/web/images/form/resources/tree_16.png"), TreeEditor.class); + + public static final WidgetOption TREECOMBOBOX = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer_Tree-ComboBox"), BaseUtils.readIcon("/com/fr/web/images/form/resources/comboboxtree.png"), + TreeComboBoxEditor.class); + + public static final WidgetOption CHECKBOXGROUP = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-CheckBoxGroup", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/checkbox_group_16.png"), CheckBoxGroup.class); + + public static final WidgetOption RADIOGROUP = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-RadioGroup", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/button_group_16.png"), + RadioGroup.class); + + public static final WidgetOption NUMBEREDITOR = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Number", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/number_field_16.png"), NumberEditor.class); + + public static final WidgetOption LABEL = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Label", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/label_16.png"), + Label.class); + + public static final WidgetOption BUTTON = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-Button", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/button_16.png"), + Button.class); + + public static final WidgetOption FREEBUTTON = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-Button", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/button_16.png"), + FreeButton.class); + + public static final WidgetOption MULTI_FILEEDITOR = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"File", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/files_up.png"), + MultiFileEditor.class); + + public static final WidgetOption COMBOBOX = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-ComboBox", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/combo_box_16.png"), + ComboBox.class); + + public static final WidgetOption COMBOCHECKBOX = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-ComboCheckBox", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/combo_check_16.png"), + ComboCheckBox.class); + + public static final WidgetOption CHECKBOX = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-CheckBox", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/check_box_16.png"), + CheckBox.class); + + public static final WidgetOption LIST = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-List", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/list_16.png"), + ListEditor.class); + + public static final WidgetOption TABLETREE = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-TableTree", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/list_16.png"), + TableTree.class); + + public static final WidgetOption TEXTEDITOR = WidgetOptionFactory.createByWidgetClass(Inter.getLocText(new String[]{"Text", "Widget"}) + , BaseUtils.readIcon("/com/fr/web/images/form/resources/text_field_16.png"), + TextEditor.class); + + public static final WidgetOption TEXTAREA = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-TextArea", "Widget"}), BaseUtils.readIcon("/com/fr/web/images/form/resources/text_area_16.png"), + TextArea.class); + + public static final WidgetOption PASSWORD = WidgetOptionFactory.createByWidgetClass( + Inter.getLocText(new String[]{"Form-Password", "Widget"}), + BaseUtils.readIcon("/com/fr/web/images/form/resources/password_field_16.png"), Password.class); + + public static final WidgetOption IFRAMEDITOR = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer_Form-Iframe"), BaseUtils.readIcon("/com/fr/web/images/form/resources/iframe_16.png"), + IframeEditor.class); + +// public static final WidgetOption DATATABLE = WidgetOptionFactory.createByWidgetClass(Inter +// .getLocText("Form-DataTable"), BaseUtils.readIcon("/com/fr/web/images/form/resources/table_16.png"), +// DataTable.class); + +// public static final WidgetOption CHARTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("Chart") +// + Inter.getLocText("Widget"), ChartEditor.class); + + +// public static final WidgetOption ABSOLUTELAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter +// .getLocText("AbsoluteLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_absolute.png"), +// WAbsoluteLayout.class); +// +// public static final WidgetOption BORDERLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter +// .getLocText("BorderLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_border.png"), +// WBorderLayout.class); +// +// public static final WidgetOption CARDLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter +// .getLocText("CardLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/card_layout_16.png"), +// WCardLayout.class); +// +// public static final WidgetOption HORIZONTALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter +// .getLocText("Layout-HBox"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_h_16.png"), +// WHorizontalBoxLayout.class); +// +// public static final WidgetOption VERTICALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter +// .getLocText("VerticalBoxLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"), +// WVerticalBoxLayout.class); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/core/WidgetOptionFactory.java b/designer_base/src/com/fr/design/gui/core/WidgetOptionFactory.java new file mode 100644 index 0000000000..c9824867b9 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/core/WidgetOptionFactory.java @@ -0,0 +1,17 @@ +package com.fr.design.gui.core; + +import com.fr.base.BaseUtils; +import com.fr.form.ui.Widget; + +import javax.swing.*; + +public class WidgetOptionFactory { + + public static WidgetOption createByWidgetClass(String optionName, Class widgetClass) { + return new CustomWidgetOption(optionName, BaseUtils.readIcon("/com/fr/design/images/data/user_widget.png"), widgetClass); + } + + public static WidgetOption createByWidgetClass(String optionName, Icon optionIcon, Class widgetClass) { + return new CustomWidgetOption(optionName, optionIcon, widgetClass); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/date/CalendarNumberField.java b/designer_base/src/com/fr/design/gui/date/CalendarNumberField.java new file mode 100644 index 0000000000..8840b3acff --- /dev/null +++ b/designer_base/src/com/fr/design/gui/date/CalendarNumberField.java @@ -0,0 +1,108 @@ +package com.fr.design.gui.date; + +import com.fr.design.gui.itextfield.UINumberField; +import com.fr.general.Inter; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; + +/** + * Created with IntelliJ IDEA. + * User: 小灰灰 + * Date: 13-9-30 + * Time: 上午11:06 + * To change this template use File | Settings | File Templates. + */ +public class CalendarNumberField extends UINumberField { + + private static final int NUM_TEN = 10; + + public CalendarNumberField( double maxValue) { + super(2, 0, 0, maxValue); + this.setBorderPainted(false); + addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + setValue(getIntValue()); + } + }); + this.setFont(new Font(Inter.getLocText("Song_TypeFace"),0,12)); + } + + public void setValue(int value) { + if (value < 0) { + value = (int)getMaxValue(); + } + if (value > getMaxValue()) { + value = 0; + } + this.setText(getValueText(value)); + } + + public int getIntValue () { + if (this.getText().length() == 0) { + return 0; + } + return Integer.parseInt(getText()); + } + + private String getValueText(int value) { + String str; + if (value < NUM_TEN) { + str = "0" + value; + } else { + str = Integer.toString(value); + } + return str; + } + + + + public void setFieldDocument(){ + setDocument(new NumberDocument()); + } + + class NumberDocument extends PlainDocument { + public NumberDocument() { + } + + public void insertString(int offset, String s, AttributeSet a) throws BadLocationException { + String str = getText(0, getLength()); + + if (!s.matches("^[0-9]+$")) { + Toolkit.getDefaultToolkit().beep(); + return; + } + + String strNew = str.substring(0, offset) + s + str.substring(offset, getLength()); + + if (isOverMaxOrMinValue(strNew)) { + Toolkit.getDefaultToolkit().beep(); + return; + } + + setisContentChanged(true); + super.insertString(offset, s, a); + } + + private boolean isOverMaxOrMinValue( String strNew) { + return (Double.parseDouble(strNew)getMaxValue()); + } + } + + public Dimension getPreferredSize() { + return new Dimension(24, 11); + } + public boolean shouldResponseChangeListener() { + return false; + } + + public Insets getInsets() { + return new Insets(0, 6, 0, 4); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/date/JDateDocument.java b/designer_base/src/com/fr/design/gui/date/JDateDocument.java new file mode 100644 index 0000000000..39748b9cb6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/date/JDateDocument.java @@ -0,0 +1,329 @@ +package com.fr.design.gui.date; + +import java.awt.Toolkit; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import javax.swing.text.PlainDocument; + +/** + */ +public class JDateDocument extends PlainDocument{ + private JTextComponent textComponent; //日期输入文本框 + private SimpleDateFormat dateFormat; + + /****************************************************************** + ** 函数名称:JDateDocument + ** 功能描述:设置此文本框显示的默认值、格式限制和当前日期 + ** 入口参数: + ** tc : JTextComponent类型,当前操作的文本框 + ** dateFormat : SimpleDateFormat类型,当前操作文本框的格式限制 + ** initDateTime : String类型,当前日期 + ** 返回值:无 + ** 调用者:类JDateDocument + *******************************************************************/ + public JDateDocument(JTextComponent tc, SimpleDateFormat dateFormat) throws + UnsupportedOperationException{ + //当前日期构造 + this(tc, dateFormat, getCurrentDate(dateFormat)); + } + + public JDateDocument(JTextComponent tc, + SimpleDateFormat dateFormat, + String initDateTime) throws + UnsupportedOperationException{ + //设置当前日期格式 + setDateFormat(dateFormat); + //保存操作的文本框 + textComponent = tc; + //设置显示为当前日期,同时完成显示的格式化 + try{ + insertString(0, initDateTime, null); + } catch(BadLocationException ex){ + throw new UnsupportedOperationException(ex.getMessage()); + } + } + + /** + * 设置当前日期格式 + * @param dateFormat SimpleDateFormat + */ + public void setDateFormat(SimpleDateFormat dateFormat){ + this.dateFormat = dateFormat; + } + + /** + * 取得当前日期格式 + * @return SimpleDateFormat + */ + public SimpleDateFormat getDateFormat(){ + return dateFormat; + } + + /** + * 取得当前系统日时 + * @return String + */ + public static String getCurrentDate(SimpleDateFormat smFormat){ + return smFormat.format(new Date()); + } + + /****************************************************************** + ** 函数名称:public void insertString(int offset, String s, + ** AttributeSet attributeSet) throws BadLocationException + ** 功能描述:重载原方法,限制用户插入格式为日期格式 + ** 入口参数:offset: int型,插入位置 + ** s: String型,插入字符串 + ** attributeSet: AttributeSet型,属性集 + ** 返回值:无 + ** 调用者:类JDateDocument + *******************************************************************/ + public void insertString(int offset, String s, + AttributeSet attributeSet) throws BadLocationException{ + String toTest; //用于测试输入合法性的字符串 + //判断插入字符串长度 + if(s.length() == 1){ + //长度为1 + try{ + //限制输入为整数 + Integer.parseInt(s); + } catch(Exception ex){ + //错误则提示并返回 + Toolkit.getDefaultToolkit().beep(); + return; + } + //取得原始插入位置 + int newOffset = offset; + //如果插入位置为"/"," ","-"符号的前面,则移动到其后面插入(改变newOffset的值) + if(offset == 4 || offset == 7 || + offset == 10 || offset == 13 || + offset == 16){ + newOffset++; + textComponent.setCaretPosition(newOffset); + } + //如果插入位置为最后,则不插入 + if(offset == dateFormat.toPattern().length()){ + return; + } + //取得显示的时间,处理后得到要显示的字符串 + toTest = textComponent.getText(); + toTest = toTest.substring(0, newOffset) + s + + toTest.substring(newOffset + 1); + //如果要显示的字符串合法,则显示,否则给出提示并退出 + boolean isValid = isValidDate(toTest); + if(!isValid){ + Toolkit.getDefaultToolkit().beep(); + return; + } + //插入字符串 + super.remove(newOffset, 1); + super.insertString(newOffset, s, attributeSet); + } + //如果插入长度10 + else if(s.length() == 10 || s.length() == 19){ + //合法则显示,否则给出提示退出 + if(!isValidDate(s)){ + Toolkit.getDefaultToolkit().beep(); + return; + } + //插入字符串 + super.remove(0, getLength()); + super.insertString(0, s, attributeSet); + } + } + + /********************************************************************************** + ** 函数名称:public void remove(int offset, int length) throws BadLocationException + ** 功能描述:重载原方法,删除合适位置的字符串 + ** 入口参数:offset: int型,插入位置 + ** length: int型,删除长度 + ** 返回值:无 + ** 调用者:insertString(int, String,AttributeSet) + ***********************************************************************************/ + public void remove(int offset, int length) throws BadLocationException{ + //如果插入位置在"-"前,则回退一个光标位置 + //yyyy-MM-dd HH:mm:ss + if(offset == 4 || offset == 7 || + offset == 10 || offset == 13 || + offset == 16) + textComponent.setCaretPosition(offset - 1); + else + textComponent.setCaretPosition(offset); + } + + /********************************************************************************** + ** 函数名称:public boolean isLegalDate(String strDate) + ** 功能描述:判断插入的长度为10的字符串是否合法 + ** 入口参数:intY: int型,年的值 + ** intM: int型,月的值 + ** intD: int型,日的值 + ** 返回值:boolean型,真,表示是合法的,假,表示不合法 + ** 调用者:insertString(int, String,AttributeSet) + ***********************************************************************************/ + private boolean isValidDate(String strDate){ + int intY, intM, intD; //年,月,日,时,分,秒的值 + int intH = 0, intMi = 0, intS = 0; + int iCaretPosition; //光标位置 + int iPatternLen = getDateFormat().toPattern().length(); + //获取字符串 + if(strDate == null){ + return false; + } + strDate = strDate.trim(); + //如果为空,长度不对,则为非法,返回false + if(strDate.length() != iPatternLen){ + return false; + } + //如果是全角字符,则返回false + for(int i = 0; i < 10; i++){ + if(((int)strDate.charAt(i)) > 255){ + return false; + } + } + //取年,月,日的值 + try{ + intY = Integer.parseInt(strDate.substring(0, 4)); + intM = Integer.parseInt(strDate.substring(5, 7)); + intD = Integer.parseInt(strDate.substring(8, 10)); + } catch(Exception e){ + //失败则返回false + return false; + } +// System.err.println("int:intY="+intY+",intM="+intM+",intD="+intD); + iCaretPosition = textComponent.getCaretPosition(); + boolean isValid = true; + + //月越界 + if(intM > 12 || intM < 1){ + intM = Math.min(12, Math.max(1, intM)); + isValid = false; + } + //根据月份,判断日期输入,如越界,则修改 + if(intD < 1){ + intD = 1; + isValid = false; + } + switch(intM){ + case 4: + case 6: + case 9: + case 11: //最大天数为30天 + + //如果输入大于30,则修改为30 + if(intD > 30){ + intD = 30; + isValid = false; + } + break; + case 2: //2月份 + + //区别闰年 + if((intY % 4 == 0 && intY % 100 != 0) || intY % 400 == 0){ + //如果输入大于29,则修改为29 + if(intD > 29){ + intD = 29; + isValid = false; + } + } else{ + //如果输入大于28,则修改为28 + if(intD > 28){ + intD = 28; + isValid = false; + } + } + break; + default: //最大天数为31天 + + //如果输入大于31,则修改为31 + if(intD > 31){ + intD = 31; + isValid = false; + } + } +// System.err.println("out:intY="+intY+",intM="+intM+",intD="+intD); + + //yyyy-MM-dd HH:mm:ss + if(iPatternLen > 10){ + try{ + intH = Integer.parseInt(strDate.substring(11, 13)); + intMi = Integer.parseInt(strDate.substring(14, 16)); + intS = Integer.parseInt(strDate.substring(17)); + } catch(Exception e){ + return false; + } + //时越界 + if(intH > 23 || intH < 0){ + intH = Math.min(23, Math.max(0, intH)); + isValid = false; + } + //分越界 + if(intMi > 59 || intMi < 0){ + intMi = Math.min(59, Math.max(0, intMi)); + isValid = false; + } + //秒越界 + if(intS > 59 || intS < 0){ + intS = Math.min(59, Math.max(0, intS)); + isValid = false; + } + } + if(!isValid){ + textComponent.setText(toDateString(intY, intM, intD, intH, intMi, + intS)); + textComponent.setCaretPosition(iCaretPosition + 1); + } + return isValid; + } + + private String toDateString(int y, int m, int d, int h, int mi, int s){ + m = Math.max(1, Math.min(12, m)); + //最大天数为31天 + d = Math.max(1, Math.min(31, d)); + switch(m){ + case 4: + case 6: + case 9: + case 11: + d = Math.min(30, d); //最大天数为30天 + break; + case 2: + + //润年 + if((y % 4 == 0 && y % 100 != 0) || y % 400 == 0){ + d = Math.min(29, d); //最大天数为29天 + } else{ + d = Math.min(28, d); //最大天数为28天 + } + break; + } + h = Math.max(1, Math.min(24, h)); + mi = Math.max(1, Math.min(59, mi)); + s = Math.max(1, Math.min(59, s)); + + String strPattern = getDateFormat().toPattern(); + String strY = rPad0(4, "" + y); + String strM = rPad0(2, "" + m); + String strD = rPad0(2, "" + d); + + String strDate; + strDate = strY + strPattern.substring(4, 5) + + strM + strPattern.substring(7, 8) + strD; + if(strPattern.length() == 19){ + strDate += strPattern.substring(10, 11) + + rPad0(2, "" + h) + strPattern.substring(13, 14) + + rPad0(2, "" + mi) + strPattern.substring(16, 17) + + rPad0(2, "" + s); + } + return strDate; + } + + private String rPad0(int maxLen, String str){ + if(str.length() < maxLen){ + str = "0" + str; + } + return str; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/date/SingleObjectComboBoxModel.java b/designer_base/src/com/fr/design/gui/date/SingleObjectComboBoxModel.java new file mode 100644 index 0000000000..8d35dacfe8 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/date/SingleObjectComboBoxModel.java @@ -0,0 +1,72 @@ +package com.fr.design.gui.date; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.AbstractListModel; +import javax.swing.ComboBoxModel; + +import com.fr.base.FRContext; + +public class SingleObjectComboBoxModel extends AbstractListModel implements ComboBoxModel { + private SimpleDateFormat dateFormat; + private String selectedDate = ""; + + public SingleObjectComboBoxModel() { + } + + public SingleObjectComboBoxModel(SimpleDateFormat dateFormat) { + setDateFormat(dateFormat); + } + + public void setDateFormat(SimpleDateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + public SimpleDateFormat getDateFormat() { + return dateFormat; + } + + public void setSelectedItem(Object anItem) { + if (anItem == null) { + return; + } + if (anItem instanceof Date) { + try { + selectedDate = this.dateFormat.format((Date) anItem); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } else { + try { + String strDate = anItem.toString().trim(); + if (strDate.length() != 10 && strDate.length() != 19) { + return; + } + String pattern = dateFormat.toPattern(); + if (strDate.length() == 10 && pattern.length() == 19) { + strDate = strDate + selectedDate.substring(10); + } + dateFormat.parse(strDate); + selectedDate = strDate; + } catch (Exception ex) { + throw new UnsupportedOperationException( + "Invalid datetime: string [" + anItem + + "], format is [" + dateFormat.toPattern() + "]. "); + } + } + fireContentsChanged(this, -1, -1); + } + + public Object getSelectedItem() { + return selectedDate; + } + + public Object getElementAt(int index) { + return selectedDate; + } + + public int getSize() { + return 1; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/date/UICalendarPanel.java b/designer_base/src/com/fr/design/gui/date/UICalendarPanel.java new file mode 100644 index 0000000000..aeded09154 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/date/UICalendarPanel.java @@ -0,0 +1,756 @@ +package com.fr.design.gui.date; + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.RoundRectangle2D; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import javax.swing.*; + +import com.fr.base.BaseUtils; +import com.fr.base.background.GradientBackground; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class UICalendarPanel extends JPanel { + private static final Font FONT_SONG = new Font(Inter.getLocText("Song_TypeFace"),0,12); + private static final Font FONT_BLACK = new Font(Inter.getLocText("Black_Font"),0,12); + private static final int WEEKDAY_COUNT = 7; + private static final int TOTAL_DAYS_COUNT = 42; + + protected Color selectedBackground; + protected Color selectedForeground; + protected Color background; + protected Color foreground; + + private Calendar calendar = null; + private UILabel monthLabel = null; + private DayPane days = null; + private HMSPane hms = null; + private MouseListener dayBttListener = null; + private boolean isSupportDateChangeListener = false; + private java.util.Date selectedDate = null; + private boolean isTimePicker; + /** + * 年月格式 + */ + final SimpleDateFormat monthFormat + = new SimpleDateFormat("yyyy-MM"); + + public UICalendarPanel() { + this(new Date(), false); + } + + public UICalendarPanel(boolean isTimerPicker) { + this(new Date(), isTimerPicker); + } + + public UICalendarPanel(Date selectedDate, boolean isTimerPicker) { + this.selectedDate = selectedDate; + this.isTimePicker = isTimerPicker; + calendar = Calendar.getInstance(); + + selectedBackground = UIManager.getColor( + "ComboBox.selectionBackground"); + selectedForeground = UIManager.getColor( + "ComboBox.selectionForeground"); + background = UIManager.getColor("ComboBox.background"); + foreground = UIManager.getColor("ComboBox.foreground"); + + dayBttListener = createDayBttListener(); + + //renderer this + setPreferredSize(new Dimension(218, 179)); + setBackground(new Color(0xFFFFFF)); + setBorder(BorderFactory.createLineBorder(new Color(0x959595))); + + setLayout(FRGUIPaneFactory.createBorderLayout()); + add(BorderLayout.NORTH, createNorthPane()); + add(BorderLayout.CENTER, createCenterPane()); + if (isTimerPicker) { + setPreferredSize(new Dimension(218, 209)); + add(BorderLayout.SOUTH, createSouthPane()); + updateDays(); + updateHMS(); + } + + updateDays(); + } + + // << < yyyy/MM/dd > >> + private JPanel createNorthPane () { + JPanel pNorth = FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); + pNorth.setBackground(new Color(0xFFFFFF)); + pNorth.setPreferredSize(new Dimension(1, 22)); + + pNorth.add(Box.createHorizontalStrut(5)); + pNorth.add(createSkipButton(Calendar.YEAR, -1 , new Icon[] { + BaseUtils.readIcon("/com/fr/design/images/calender/year_reduce.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/year_reduce_hover.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/year_reduce_click.png") + })); + pNorth.add(Box.createHorizontalStrut(11)); + UILabel monthMinus = createSkipButton(Calendar.MONTH, -1, new Icon[]{ + BaseUtils.readIcon("/com/fr/design/images/calender/month_reduce.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/month_reduce_hover.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/month_reduce_click.png") + }); + monthMinus.setPreferredSize(new Dimension(20, 20)); + pNorth.add(monthMinus); + monthLabel = new UILabel("", UILabel.CENTER); + monthLabel.setBackground(new Color(0xFFFFFF)); + monthLabel.setForeground(new Color(0x000000)); + monthLabel.setFont(FONT_SONG); + pNorth.add(Box.createHorizontalGlue()); + pNorth.add(monthLabel); + pNorth.add(Box.createHorizontalGlue()); + + UILabel monthPlus = createSkipButton(Calendar.MONTH, 1, new Icon[]{ + BaseUtils.readIcon("/com/fr/design/images/calender/month_add.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/month_add_hover.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/month_add_click.png") + }); + monthPlus.setPreferredSize(new Dimension(20, 20)); + monthPlus.setHorizontalAlignment(SwingConstants.RIGHT); + pNorth.add(monthPlus); + pNorth.add(Box.createHorizontalStrut(11)); + pNorth.add(createSkipButton(Calendar.YEAR, 1 , new Icon[] { + BaseUtils.readIcon("/com/fr/design/images/calender/year_add.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/year_add_hover.png"), + BaseUtils.readIcon("/com/fr/design/images/calender/year_add_click.png") + })); + pNorth.add(Box.createHorizontalStrut(5)); + + return pNorth; + } + + + private JPanel createCenterPane() { + //星期日 星期一 星期二 星期三 星期四 星期五 星期六 + JPanel pWeeks = new JPanel(new GridLayout(1, 7, 1, 0)); + pWeeks.setPreferredSize(new Dimension(216, 22)); + pWeeks.setBackground(new Color(0xFFFFFF)); + pWeeks.setOpaque(true); + String[] strWeeks = new String[] {StringUtils.EMPTY, Inter.getLocText("Sun"), Inter.getLocText("Mon"), + Inter.getLocText("Tue"),Inter.getLocText("Wed"),Inter.getLocText("Thu"), + Inter.getLocText("Fri"),Inter.getLocText("Sat") + }; + for (int i = 1; i <= WEEKDAY_COUNT; i++) { + UILabel label = new UILabel(); + label.setHorizontalAlignment(UILabel.CENTER); + label.setForeground(new Color(0x4D4C4C)); + label.setFont(FONT_BLACK); + label.setText(strWeeks[i]); + pWeeks.add(label); + } + + //中间放日期的面板 + days = new DayPane(); + days.setOpaque(true); + days.setPreferredSize(new Dimension(216, 115)); + JPanel pCenter = FRGUIPaneFactory.createBorderLayout_S_Pane(); + pCenter.setOpaque(true); + pCenter.add(pWeeks, BorderLayout.NORTH); + pCenter.add(days, BorderLayout.CENTER); + + //显示今天的日期,直接单击图标跳到今天 + GradientPane pToday = new GradientPane(new GradientBackground(new Color(0x097BDA), new Color(0x40A3EE), GradientBackground.TOP2BOTTOM), false); + pToday.setPreferredSize(new Dimension(216, 18)); + pToday.setLayout(new BorderLayout()); + UIDayLabel lbToday = new UIDayLabel(new Date(), false); + lbToday.setForeground(new Color(0x000000)); + lbToday.addMouseListener(createTodayListener(pToday, lbToday)); + pToday.setBackground(new Color(0xF0F0F0)); + pToday.add(lbToday, BorderLayout.CENTER); + pCenter.add(pToday, BorderLayout.SOUTH); + + return pCenter; + } + + private JPanel createSouthPane () { + JPanel sPane = new JPanel(); + sPane.setPreferredSize(new Dimension(216, 30)); + sPane.setBackground(Color.WHITE); + sPane.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 6)); + UILabel timeLabel = new UILabel(Inter.getLocText("Time") + ":"); + timeLabel.setBorder(BorderFactory.createEmptyBorder(0,9,0,5)); + timeLabel.setFont(FONT_SONG); + sPane.add(timeLabel); + hms = new HMSPane(); + sPane.add(hms); + + UILabel gap = new UILabel(); + gap.setPreferredSize(new Dimension(26,1)); + sPane.add(gap); + + UIButton okButton = new UIButton(Inter.getLocText("OK")) { + public Dimension getPreferredSize() { + return new Dimension(32,18); + } + + public Insets getInsets() { + return new Insets(0, 0, 0, 0); + } + }; + okButton.setFont(FONT_SONG); + okButton.setVerticalAlignment(SwingConstants.CENTER); + okButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + hms.update(UICalendarPanel.this.calendar); + UICalendarPanel.this.selectedDate = UICalendarPanel.this.calendar.getTime(); + fireDateChanged(new ChangeEvent(UICalendarPanel.this.selectedDate)); + } + }); + + sPane.add(okButton); + + return sPane; + } + + public void resetHMSPaneSelectedNumberField() { + if (this.hms != null) { + this.hms.selectedNumberField = this.hms.hField; + this.hms.nextButton.requestFocus(); + } + } + + /** + * 创建上一月,下一月,上一年,下一年"按钮" + * @param field int + * @param amount int + * @return UILabel + */ + protected UILabel createSkipButton(final int field, final int amount,final Icon[] icons) { + if (icons.length != 3) { + return new UILabel(); + } + UILabel label = new UILabel(); + label.setIcon(icons[0]); + label.setRequestFocusEnabled(false); + label.addMouseListener(createSkipListener(label, field, amount, icons)); + return label; + } + + protected MouseListener createSkipListener(final UILabel label, final int field, + final int amount, final Icon[] icons) { + return new MouseAdapter() { + public void mouseReleased(MouseEvent e) { + label.setIcon(icons[1]); + calendar.add(field, amount); + updateDays(); + resetHMSPaneSelectedNumberField(); + } + + public void mouseEntered(MouseEvent e) { + label.setIcon(icons[1]); + } + + public void mouseExited(MouseEvent e) { + label.setIcon(icons[0]); + } + + public void mousePressed(MouseEvent e) { + label.setIcon(icons[2]); + } + }; + } + + /** + * 更新日期 + */ + protected void updateDays() { + //更新月份 + monthLabel.setText(monthFormat.format(calendar.getTime())); + days.removeAll(); + days.setFloatIndex(-1); + Calendar selectedCalendar = Calendar.getInstance(); + selectedCalendar.setTime(selectedDate); + Calendar setupCalendar = (Calendar) calendar.clone(); + setupCalendar.set(Calendar.DAY_OF_MONTH, 1); + int first = setupCalendar.get(Calendar.DAY_OF_WEEK); + setupCalendar.add(Calendar.DATE, -first); + + boolean isCurrentMonth = false; + for (int i = 0; i < TOTAL_DAYS_COUNT; i++) { + setupCalendar.add(Calendar.DATE, 1); + GradientPane gp = new GradientPane(new GradientBackground(new Color(0xFEFEFE), new Color(0xF3F2F3), GradientBackground.TOP2BOTTOM), true); + gp.setIndex(i); + gp.setLayout(new BorderLayout()); + gp.setBorder(null); + UIDayLabel label = new UIDayLabel(setupCalendar.getTime()); + label.setHorizontalAlignment(SwingConstants.RIGHT); + label.setBorder(BorderFactory.createEmptyBorder(0,0,0,9)); + label.addMouseListener(dayBttListener); + if ("1".equals(label.getText())) { + isCurrentMonth = !isCurrentMonth; + } + label.setEnabled(isCurrentMonth); + if (!isCurrentMonth) { + label.setForeground(new Color(0x6F6F6)); + } + //当前选择的日期 + if (setupCalendar.get(Calendar.DAY_OF_MONTH) == selectedCalendar.get(Calendar.DAY_OF_MONTH) && isCurrentMonth) { + gp.setGradientBackground(new GradientBackground(new Color(0x097BD9), new Color(0x41A3EE), GradientBackground.TOP2BOTTOM)); + gp.add(label, BorderLayout.CENTER); + days.add(gp); + days.setSelectedIndex(i); + this.selectedDate = label.getDate(); + this.calendar.setTime(this.selectedDate); + }else { + gp.add(label, BorderLayout.CENTER); + days.add(gp); + } + } + days.validate(); + } + + public void updateHMS() { + if (hms != null){ + hms.populate(this.calendar); + hms.validate(); + } + } + + protected MouseListener createTodayListener(final GradientPane jp, final UIDayLabel label) { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + jp.setBorder(BorderFactory.createLineBorder(new Color(0x3868AA))); + jp.setPaintGradientBackground(true); + jp.repaint(); + label.setForeground(new Color(0xFFFFFF)); + } + + @Override + public void mouseExited(MouseEvent e) { + jp.setBackground(new Color(0xF0F0F0)); + } + + @Override + public void mouseEntered(MouseEvent e) { + jp.setBackground(new Color(0xC8DDEE)); + } + + @Override + public void mouseReleased(MouseEvent e) { + jp.setBackground(new Color(0xF0F0F0)); + label.setForeground(new Color(0x000000)); + jp.setBorder(null); + jp.setPaintGradientBackground(false); + jp.repaint(); + if (isTimePicker) { + UICalendarPanel.this.setSelectedDate(label.getDate()); + updateDays(); + } else { + UICalendarPanel.this.isSupportDateChangeListener = true; + UICalendarPanel.this.setSelectedDate(label.getDate()); + UICalendarPanel.this.isSupportDateChangeListener = false; + } + resetHMSPaneSelectedNumberField(); + } + }; + } + + protected MouseListener createDayBttListener() { + return new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (isEnabled()) { + UIDayLabel com = (UIDayLabel) e.getComponent(); + GradientPane gp = (GradientPane)com.getParent(); + if (days.selectedIndex != -1) { + ((GradientPane)days.getComponent(days.selectedIndex)).setGradientBackground(new GradientBackground(new Color(0xFEFEFE), new Color(0xF3F2F3), GradientBackground.TOP2BOTTOM)); + } + gp.setGradientBackground(new GradientBackground(new Color(0x097BD9), new Color(0x41A3EE), GradientBackground.TOP2BOTTOM)); + days.setSelectedIndex(gp.getIndex()); + } + } + + + public void mouseReleased(MouseEvent e) { + UIDayLabel com = (UIDayLabel) e.getComponent(); + if (isTimePicker) { + UICalendarPanel.this.setSelectedDate(com.getDate()); + } else { + UICalendarPanel.this.isSupportDateChangeListener = true; + UICalendarPanel.this.setSelectedDate(com.getDate()); + UICalendarPanel.this.isSupportDateChangeListener = false; + } + resetHMSPaneSelectedNumberField(); + } + + public void mouseEntered(MouseEvent e) { + if (isEnabled()) { + JComponent com = (JComponent) e.getComponent(); + GradientPane gp = (GradientPane)com.getParent(); + if (gp.getIndex() == days.selectedIndex) { + return; + } + gp.setGradientBackground(new GradientBackground(new Color(0xFFFFFF), new Color(0xEAF4FC), GradientBackground.TOP2BOTTOM)); + days.setFloatIndex(gp.getIndex()); + } + + } + + public void mouseExited(MouseEvent e) { + if (isEnabled()) { + JComponent com = (JComponent) e.getComponent(); + GradientPane gp = (GradientPane)com.getParent(); + if (gp.getIndex() != days.selectedIndex) { + gp.setGradientBackground(new GradientBackground(new Color(0xFEFEFE), new Color(0xF3F2F3), GradientBackground.TOP2BOTTOM)); + } + days.setFloatIndex(-1); + days.repaint(); + } + } + }; + } + + protected EventListenerList listenerList = new EventListenerList(); + + public void addDateChangeListener(ChangeListener l) { + listenerList.add(ChangeListener.class, l); + } + + public void removeDateChangeListener(ChangeListener l) { + listenerList.remove(ChangeListener.class, l); + } + + protected void fireDateChanged(ChangeEvent e) { + Object[] listeners = listenerList.getListenerList(); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } + + public void setSelectedDate(Date selectedDate) { + this.selectedDate = selectedDate; + this.calendar.setTime(selectedDate); + updateDays(); + if (isSupportDateChangeListener) { + fireDateChanged(new ChangeEvent(selectedDate)); + } + } + + public void setSelectedHMS() { + hms.update(this.calendar); + } + + public Date getSelectedDate() { + return selectedDate; + } + + private class GradientPane extends JPanel { + + private int index; + private boolean isGradientBackground; + private GradientBackground gradientBackground; + + public GradientPane() { + + } + + public GradientPane(GradientBackground gradientBackground, boolean isGradientBackground) { + super(); + this.gradientBackground = gradientBackground; + this.isGradientBackground = isGradientBackground; + } + + public void paint(Graphics g){ + super.paint(g); + if (isGradientBackground && gradientBackground != null) { + gradientBackground.paint(g, new Rectangle(this.getWidth(), this.getHeight())); + } + paintChildren(g); + } + + public void setPaintGradientBackground(boolean flag) { + this.isGradientBackground = flag; + } + + public void setGradientBackground(GradientBackground gradientBackground) { + this.gradientBackground = gradientBackground; + } + + public void setIndex(int i) { + this.index = i; + } + + public int getIndex () { + return this.index; + } + + public void setForeground(Color c) { + super.setForeground(c); + if (getComponentCount() > 0) { + getComponent(0).setForeground(c); + } + } + } + + private class DayPane extends JPanel { + private Color floatColor = new Color(0xC5E2F9); + private Color selectedColor = new Color(0x41A3EE); + private int floateIndex; + private int selectedIndex; + + public DayPane() { + floateIndex = -1; + selectedIndex = -1; + this.setLayout(new GridLayout(6,7,1,1)); + this.setBackground(new Color(0xFFFFFF)); + this.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(0xDADADA))); + } + + public void paint (Graphics g) { + super.paint(g); + int width = 31; + int height = 19; + Color oldColor = g.getColor(); + g.setColor(new Color(0xDADADA)); + int start_x = 30; + int start_y = 19; + for (int i = 0; i < 6; i ++) { + g.drawLine(start_x, 0, start_x, getHeight()); + start_x += width; + } + for (int i = 0; i < 5; i ++){ + g.drawLine(0, start_y, getWidth(), start_y); + start_y += height; + } + + if (floateIndex > -1) { + g.setColor(floatColor); + paintChindPane(g, floateIndex); + } + if (selectedIndex > -1) { + g.setColor(selectedColor); + paintChindPane(g,selectedIndex); + } + g.setColor(oldColor); + } + + private void paintChindPane(Graphics g, int index) { + if (index%7 == 0 ) { + int y1 = index/7*19; + g.drawLine(0,y1,30,y1); + g.drawLine(0,y1 + 19, 30, y1 +19); + g.drawLine(30, y1, 30 ,y1 + 19); + }else if (index%7 == 6) { + int y1 = index/7*19; + g.drawLine(185,y1,216,y1); + g.drawLine(185,y1 + 19, 216, y1 +19); + g.drawLine(185, y1, 185 ,y1 + 19); + } else { + int x1 = index%7*31 -1; + int y1 = index/7*19; + g.drawRect(x1, y1, 31, 19); + } + } + + public void setFloatIndex(int index) { + this.floateIndex = index; + repaint(); + } + + public void setSelectedIndex(int index) { + if (this.selectedIndex != -1 && this.selectedIndex < getComponentCount()) { + this.getComponent(selectedIndex).setForeground(Color.black); + } + if (index != -1 && index < getComponentCount()) { + this.getComponent(index).setForeground(Color.white); + } + this.selectedIndex = index; + repaint(); + } + + } + + private class HMSPane extends JPanel{ + private boolean isRolOver; + private UIButton preButton; + private UIButton nextButton; + private CalendarNumberField hField; + private CalendarNumberField mField; + private CalendarNumberField sField; + private CalendarNumberField selectedNumberField; + + public HMSPane () { + this.setPreferredSize(new Dimension(101, 18)); + this.setLayout(new BorderLayout(0, 0)); + this.setBackground(null); + + initComponents(); + initListener(); + + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + isRolOver = false; + repaint(); + } + + @Override + public void mouseEntered(MouseEvent e) { + isRolOver = true; + repaint(); + } + }); + + } + + private void initComponents() { + JPanel jp = new JPanel(new FlowLayout(FlowLayout.LEFT,0,2)); + jp.setBackground(null); + jp.setBorder(null); + + hField = new CalendarNumberField(23); + mField = new CalendarNumberField(59); + sField = new CalendarNumberField(59); + selectedNumberField = hField; + + jp.add(hField); + jp.add(createGapLabel()); + jp.add(mField); + jp.add(createGapLabel()); + jp.add(sField); + + this.add(jp, BorderLayout.CENTER); + preButton = new UIButton(UIConstants.ARROW_UP_ICON){ + public boolean shouldResponseChangeListener() { + return false; + } + }; + preButton.setRoundBorder(true, Constants.LEFT); + nextButton = new UIButton(UIConstants.ARROW_DOWN_ICON){ + public boolean shouldResponseChangeListener() { + return false; + } + }; + nextButton.setRoundBorder(true, Constants.LEFT); + JPanel arrowPane = new JPanel(); + arrowPane.setPreferredSize(new Dimension(11, 18)); + arrowPane.setLayout(new GridLayout(2, 1)); + arrowPane.add(preButton); + arrowPane.add(nextButton); + this.add(arrowPane, BorderLayout.EAST); + } + + private void initListener() { + MouseAdapter backgroundAdapter = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + HMSPane.this.selectedNumberField = (CalendarNumberField)e.getComponent(); + } + + @Override + public void mouseExited(MouseEvent e) { + isRolOver = false; + HMSPane.this.repaint(); + } + + @Override + public void mouseEntered(MouseEvent e) { + isRolOver = true; + HMSPane.this.repaint(); + } + }; + hField.addMouseListener(backgroundAdapter); + mField.addMouseListener(backgroundAdapter); + sField.addMouseListener(backgroundAdapter); + nextButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + HMSPane.this.selectedNumberField.setValue(HMSPane.this.selectedNumberField.getIntValue() - 1); + HMSPane.this.selectedNumberField.requestFocus(); + HMSPane.this.selectedNumberField.selectAll(); + + } + }); + preButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + HMSPane.this.selectedNumberField.setValue(HMSPane.this.selectedNumberField.getIntValue() + 1); + HMSPane.this.selectedNumberField.requestFocus(); + HMSPane.this.selectedNumberField.selectAll(); + } + }); + } + + private UILabel createGapLabel () { + UILabel uiLabel = new UILabel(":"); + uiLabel.setHorizontalAlignment(SwingConstants.CENTER); + uiLabel.setBackground(null); + uiLabel.setBorder(null); + uiLabel.setPreferredSize(new Dimension(6,10)); + return uiLabel; + } + + public Insets getInsets() { + return new Insets(1,3,1,0); + } + + public void paint(Graphics g) { + super.paint(g); + paintBorder(g); + } + + public void paintBorder(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + if (isRolOver) { + Shape shape = new RoundRectangle2D.Double(1, 1, 86, 15, UIConstants.ARC, UIConstants.ARC); + GUIPaintUtils.paintBorderShadow(g2d, 3, shape, UIConstants.HOVER_BLUE, Color.white); + } else { + GUIPaintUtils.drawBorder(g2d, 0, 0, 101, 18, true, 3); + } + } + + public void populate(Calendar calendar){ + this.hField.setValue(calendar.get(Calendar.HOUR_OF_DAY)); + this.mField.setValue(calendar.get(Calendar.MINUTE)); + this.sField.setValue(calendar.get(Calendar.SECOND)); + } + + public void update(Calendar calendar) { + calendar.set(Calendar.HOUR_OF_DAY, hField.getIntValue()); + calendar.set(Calendar.MINUTE, mField.getIntValue()); + calendar.set(Calendar.SECOND, sField.getIntValue()); + } + } + + public static void main(String[] args){ + JFrame frame = new JFrame(); + + UICalendarPanel calendarPanel = new UICalendarPanel(); + final UITextField field = new UITextField(); + field.setPreferredSize(new Dimension(120, 25)); + calendarPanel.addDateChangeListener(new ChangeListener(){ + public void stateChanged(ChangeEvent e){ + Date selectedDate = (Date)e.getSource(); + SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd"); + field.setText(f.format(selectedDate)); + } + }); + frame.getContentPane().setLayout(FRGUIPaneFactory.createCenterFlowLayout()); + frame.getContentPane().add(field); + frame.getContentPane().add(calendarPanel); + frame.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/date/UIDatePicker.java b/designer_base/src/com/fr/design/gui/date/UIDatePicker.java new file mode 100644 index 0000000000..c2ee8ab312 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/date/UIDatePicker.java @@ -0,0 +1,286 @@ +package com.fr.design.gui.date; + +import com.fr.base.FRContext; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxUI; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.plaf.basic.ComboPopup; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.io.Serializable; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * UIDatePicker + */ +public class UIDatePicker extends UIComboBox implements Serializable { + /** + * 日期格式类型 + */ + public static final int STYLE_CN_DATE = 0; + public static final int STYLE_CN_DATE1 = 1; + public static final int STYLE_CN_DATETIME = 2; + public static final int STYLE_CN_DATETIME1 = 3; + public boolean isWillHide = false; + /** + * 日期格式类型 + */ + private int formatStyle = STYLE_CN_DATETIME; + /** + * 当前设置日期格式 + */ + private SimpleDateFormat dateFormat = null; + + /** + * 只有一个值的ComboBoxModel + */ + private SingleObjectComboBoxModel model = new SingleObjectComboBoxModel(); + JDateDocument dateDocument = null; + + /** + * 构造式 + */ + public UIDatePicker() throws UnsupportedOperationException { + this(STYLE_CN_DATE); + } + + public UIDatePicker(int formatStyle) throws UnsupportedOperationException { + this(formatStyle, new Date()); + } + + public UIDatePicker(int formatStyle, Date initialDatetime) throws UnsupportedOperationException { + this.setStyle(formatStyle); + //设置可编辑 + this.setEditable(true); + + this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + + //设置编辑器属性(只能输入正确日期) + JTextField textField = ((JTextField) getEditor().getEditorComponent()); + textField.setHorizontalAlignment(SwingConstants.CENTER); + dateDocument = new JDateDocument(textField, this.dateFormat); + textField.setDocument(dateDocument); + //设置Model为单值Model + this.setModel(model); + //设置当前选择日期 + this.setSelectedItem(initialDatetime == null ? new Date() : initialDatetime); + updateUI(); + } + + /** + * 设置日期格式 + * STYLE_CN_DATE + * STYLE_CN_DATE1 + * STYLE_CN_DATETIME + * STYLE_CN_DATETIME1 + * + * @param formatStyle int + */ + public void setStyle(int formatStyle) throws UnsupportedOperationException { + this.formatStyle = formatStyle; + dateFormat = getDateFormat(formatStyle); + model.setDateFormat(dateFormat); + if (dateDocument != null) { + dateDocument.setDateFormat(dateFormat); + } + } + + /** + * 取得指定类型的日期格式 + * + * @param formatStyle int + * @return SimpleDateFormat + * @throws UnsupportedOperationException + */ + private static SimpleDateFormat getDateFormat(int formatStyle) throws + UnsupportedOperationException { + switch (formatStyle) { + case STYLE_CN_DATE: + return new SimpleDateFormat("yyyy/MM/dd"); + case STYLE_CN_DATE1: + return new SimpleDateFormat("yyyy-MM-dd"); + case STYLE_CN_DATETIME: + return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + case STYLE_CN_DATETIME1: + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + default: + throw new UnsupportedOperationException( + "invalid formatStyle parameter!"); + } + } + + /** + * 取得日期格式 + * STYLE_CN_DATE + * STYLE_CN_DATE1 + * STYLE_CN_DATETIME + * STYLE_CN_DATETIME1 + * + * @return int + */ + public int getStyle() { + return formatStyle; + } + + /** + * 取得当前选择的日期 + * + * @return Date + */ + public Date getSelectedDate() throws ParseException { + synchronized (this) { + return dateFormat.parse(getSelectedItem().toString()); + } + } + + /** + * 设置当前选择的日期 + */ + public void setSelectedDate(Date date) throws ParseException { + this.setSelectedItem(dateFormat.format(date)); + } + + public void setSelectedItem(Object anObject) { + model.setSelectedItem(anObject); + super.setSelectedItem(anObject); + } + + /** + *

Title: UIDatePicker

+ *

Description: DatePopup 选择框弹出的日期选择面板

+ *

Copyright: Copyright (c) 2004

+ *

Company:

+ * + * @author Sunking + * @version 1.0 + */ + class DatePopup extends BasicComboPopup implements ChangeListener { + UICalendarPanel calendarPanel = null; + + public DatePopup(JComboBox box) { + super(box); + + setLayout(FRGUIPaneFactory.createBorderLayout()); + calendarPanel = new UICalendarPanel(formatStyle > 1); + calendarPanel.addDateChangeListener(this); + add(calendarPanel, BorderLayout.CENTER); + setBorder(BorderFactory.createEmptyBorder()); + } + + public void hide() { + if (isWillHide) { + super.hide(); + } + } + + public void show() { + if (isWillHide || UIDatePicker.this.isEnabled() == false) { + return; + } + if (calendarPanel != null) { + calendarPanel.resetHMSPaneSelectedNumberField(); + } + super.show(); + } + + /** + * 显示弹出面板 + */ + protected void firePropertyChange(String propertyName, + Object oldValue, + Object newValue) { + if (ComparatorUtils.equals(propertyName, "visible")) { + if (ComparatorUtils.equals(oldValue, Boolean.FALSE) + && ComparatorUtils.equals(newValue, Boolean.TRUE)) { //SHOW + try { + String strDate = comboBox.getSelectedItem().toString(); + synchronized (this) { + Date selectionDate = dateFormat.parse(strDate); + calendarPanel.setSelectedDate(selectionDate); + calendarPanel.updateHMS(); + } + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + } else if (ComparatorUtils.equals(oldValue, Boolean.TRUE) + && ComparatorUtils.equals(newValue, Boolean.FALSE)) { //HIDE + } + } + super.firePropertyChange(propertyName, oldValue, newValue); + } + + public void stateChanged(ChangeEvent e) { + if (calendarPanel.getSelectedDate() != null && dateFormat != null) { + String strDate = dateFormat.format(calendarPanel.getSelectedDate()); + if (comboBox.isEditable() && comboBox.getEditor() != null) { + comboBox.configureEditor(comboBox.getEditor(), strDate); + } + comboBox.setSelectedItem(strDate); + } + comboBox.repaint(); + setVisible(false); + } + } + + protected ComboBoxUI getUIComboBoxUI() { + return new UIComboBoxUI() { + protected ComboPopup createPopup() { + return new DatePopup(comboBox); + } + + public void mousePressed(MouseEvent e) { + if (UIDatePicker.this.isPopupVisible()) { + isWillHide = true; + UIDatePicker.this.hidePopup(); + } else { + isWillHide = false; + UIDatePicker.this.showPopup(); + } + } + }; + } + + + + //设置dataFormat + public void setDateFormat(SimpleDateFormat format){ + this.dateFormat = format; + } + + //获取dateFormat + public SimpleDateFormat getDateFormat(){ + return this.dateFormat; + } + + public JDateDocument getDateDocument(){ + return this.dateDocument; + } + + public static void main(String[] args) { + LayoutManager layoutManager = null; + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(layoutManager); + UIDatePicker bb = new UIDatePicker(); + if (args.length != 0) { + bb = new UIDatePicker(STYLE_CN_DATETIME); + } + bb.setEditable(true); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/date/UIDayLabel.java b/designer_base/src/com/fr/design/gui/date/UIDayLabel.java new file mode 100644 index 0000000000..3243227f0a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/date/UIDayLabel.java @@ -0,0 +1,49 @@ +package com.fr.design.gui.date; + +import java.awt.*; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fr.design.gui.ilable.UILabel; + +import com.fr.general.Inter; + +public class UIDayLabel extends UILabel { + + private Date date = null; + + /** + * 日期格式(TODAY/TIP用) + */ + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); + /** + * 日格式 + */ + final SimpleDateFormat dayFormat = new SimpleDateFormat("d"); + + public UIDayLabel(Date date) { + this(date, true); + } + + public UIDayLabel(Date date, boolean isSmallLabel) { + setHorizontalAlignment(UILabel.CENTER); + setFont(new Font(Inter.getLocText("Song_TypeFace"), 0, 12)); + this.date = date; + setPreferredSize(new Dimension(30, 18)); + if (isSmallLabel) { + setText(dayFormat.format(date)); + } else { + setText(Inter.getLocText("Today")+":" + dateFormat.format(new Date())); + } + } + + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/demo/ComboBoxDemo.java b/designer_base/src/com/fr/design/gui/demo/ComboBoxDemo.java new file mode 100644 index 0000000000..499243b45f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/demo/ComboBoxDemo.java @@ -0,0 +1,176 @@ +package com.fr.design.gui.demo; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.ArrayList; + +import javax.swing.DefaultListCellRenderer; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JTree; +import javax.swing.ListCellRenderer; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; + +import com.fr.base.FRContext; +import com.fr.design.gui.icombobox.filter.Filter; +import com.fr.design.gui.icombobox.ComboCheckBox; +import com.fr.design.gui.icombobox.DictionaryComboBox; +import com.fr.design.gui.icombobox.ExtendedComboBox; +import com.fr.design.gui.icombobox.FRTreeComboBox; +import com.fr.design.gui.icombobox.FilterComboBox; +import com.fr.design.gui.icombobox.LazyComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +/** + * Created by IntelliJ IDEA. + * User: Richer + * Date: 11-6-30 + * Time: 下午8:21 + */ +public class ComboBoxDemo extends JPanel { + public ComboBoxDemo() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + + Component[][] coms = new Component[][]{ + {new UILabel(Inter.getLocText("Form-ComboCheckBox")+":"), createComboCheckBox()}, + {new UILabel(Inter.getLocText(new String[]{"DS-Dictionary", "Form-ComboBox"})+":"), createDictComboBox()}, + {new UILabel(Inter.getLocText("long_data_can_not_show_fully")+":"), createExtendedComboBox()}, + {new UILabel(Inter.getLocText(new String[]{"Filter", "Form-ComboBox"})+":"), createFilterComboBox()}, + {new UILabel(Inter.getLocText("Form-ComboBox")+":"), createTreeComboBox()}, + {new UILabel(Inter.getLocText(new String[]{"Delay", "Load", "Form-ComboBox"})+":"), createLazyComboBox()} + }; + double[] rowSize = new double[coms.length]; + double[] columnSize = {p, f}; + for (int i = 0; i < rowSize.length; i++) { + rowSize[i] = p; + } + JPanel centerPane = TableLayoutHelper.createTableLayoutPane(coms, rowSize, columnSize); + add(centerPane, BorderLayout.CENTER); + } + + private ComboCheckBox createComboCheckBox() { + ComboCheckBox ccb = new ComboCheckBox(new Object[]{"张三", "李四", "王五", "赵六"}); + ccb.setRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value != null) { + if (value instanceof Object[]) { + Object[] objs = (Object[]) value; + String[] res = new String[objs.length]; + for (int i = 0, len = objs.length; i < len; i++) { + res[i] = objs[i].toString(); + } + setText(StringUtils.join(",", res)); + } + } + return this; + } + }); + return ccb; + } + + private DictionaryComboBox createDictComboBox() { + DictionaryComboBox dcb = new DictionaryComboBox( + new Integer[]{1, 2, 3, 4}, + new String[]{"一", "二", "三", "四"} + ); + return dcb; + } + + private ExtendedComboBox createExtendedComboBox() { + ExtendedComboBox ecb = new ExtendedComboBox(new String[]{ + "Hello world, alksdfjlaskdjflaskjdflaksdf", + "Hello world, alksdfjlaskdjflaskjdflaksdfasdfklajsdflkasjdflkasdf", + "Hello world, alksdfjlaskdjflaskjdflaksdfasdfklajsdflkasjdflkasdfaaaaaaaaaaaaaaaaaadfsdf", + "Hello world, 太长了,都看不全了jlaskdjflaskjdflaksdfasdfklajsdflkasjdflkasdfsdfgklsdjfgklsdfjgklsjdfgkljsdflkgjsdlfk"}); + return ecb; + } + + private FilterComboBox createFilterComboBox() { + ArrayList items = new ArrayList(); + items.add("abc"); + items.add("abcd"); + items.add("dfee"); + items.add("asdfg"); + items.add("cdefg"); + Filter filter = new Filter() { + @Override + public boolean accept(String prefix, Object object) { + return prefix == null || object != null && + object.toString().toLowerCase().startsWith(prefix.toLowerCase()); + } + }; + + FilterComboBox fcb = new FilterComboBox(filter, items); + return fcb; + } + + private FRTreeComboBox createTreeComboBox() { + + DefaultMutableTreeNode root = new DefaultMutableTreeNode("根节点"); + DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("子节点1"); + root.add(child1); + DefaultMutableTreeNode child11 = new DefaultMutableTreeNode("子节点1-1"); + child1.add(child11); + DefaultMutableTreeNode child12 = new DefaultMutableTreeNode("子节点1-2"); + child1.add(child12); + DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("子节点2"); + root.add(child2); + DefaultMutableTreeNode child21 = new DefaultMutableTreeNode("子节点2-1"); + child2.add(child21); + JTree tree = new JTree(root); + TreeCellRenderer treeCellRender = new DefaultTreeCellRenderer() { + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); + if (value instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; + Object userObj = node.getUserObject(); + setText(userObj + "-我是渲染器额外加的"); + } + return this; + } + }; + FRTreeComboBox tcb = new FRTreeComboBox(tree, treeCellRender, true, false); + ListCellRenderer listCellRenderer = new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof TreePath) { + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) ((TreePath) value).getLastPathComponent(); + setText(treeNode.getUserObject().toString()); + } + return this; + } + }; + tcb.setRenderer(listCellRenderer); + tcb.setOnlyLeafSelectable(false); + return tcb; + } + + private LazyComboBox createLazyComboBox() { + LazyComboBox lcb = new LazyComboBox() { + @Override + public Object[] load() { + // 睡5秒 + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return new Object[]{"11", "22", "33", "44", "55", "66"}; + } + }; + return lcb; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/demo/LabelDemo.java b/designer_base/src/com/fr/design/gui/demo/LabelDemo.java new file mode 100644 index 0000000000..87af245826 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/demo/LabelDemo.java @@ -0,0 +1,62 @@ +package com.fr.design.gui.demo; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import com.fr.design.gui.ilable.ActionLabel; +import com.fr.design.gui.ilable.MultilineLabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.general.Inter; + +/** + * Created by IntelliJ IDEA. + * User: Richer + * Date: 11-7-1 + * Time: 上午8:54 + */ +public class LabelDemo extends JPanel { + public LabelDemo() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + + Component[][] coms = new Component[][]{ + {new UILabel(Inter.getLocText(new String[]{"Hyperlink", "Label"})+":"), createActionLabel()}, + {new UILabel("多行字的标签:"), createMultilineLabel()} + }; + double[] rowSize = new double[coms.length]; + double[] columnSize = {p, f}; + for (int i = 0; i < rowSize.length; i++) { + rowSize[i] = p; + } + + + + JPanel centerPane = TableLayoutHelper.createTableLayoutPane(coms, rowSize, columnSize); + add(centerPane, BorderLayout.CENTER); + } + + private ActionLabel createActionLabel() { + ActionLabel al = new ActionLabel("点我,我看的反应"); + al.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog(LabelDemo.this, "我能对点击做出反应!"); + } + }); + return al; + } + + private MultilineLabel createMultilineLabel() { + MultilineLabel mll = new MultilineLabel("abc\n伊尔"); + return mll; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/demo/ListDemo.java b/designer_base/src/com/fr/design/gui/demo/ListDemo.java new file mode 100644 index 0000000000..90204d287f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/demo/ListDemo.java @@ -0,0 +1,42 @@ +package com.fr.design.gui.demo; + +import java.awt.BorderLayout; +import java.awt.Component; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.design.gui.ilist.CheckBoxList; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; + +/** + * Created by IntelliJ IDEA. + * User: Richer + * Date: 11-6-30 + * Time: 下午9:17 + */ +public class ListDemo extends JPanel { + public ListDemo() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + + Component[][] coms = new Component[][]{ + {new UILabel("复选框列表:"), createCheckBoxList()}, + }; + double[] rowSize = new double[coms.length]; + double[] columnSize = {p, f}; + for (int i = 0; i < rowSize.length; i++) { + rowSize[i] = p; + } + JPanel centerPane = TableLayoutHelper.createTableLayoutPane(coms, rowSize, columnSize); + add(centerPane, BorderLayout.CENTER); + } + + private CheckBoxList createCheckBoxList() { + CheckBoxList cbl = new CheckBoxList(new Object[] {"张三", "李四", "王五", "赵六"}); + return cbl; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/demo/LoadingPaneDemo.java b/designer_base/src/com/fr/design/gui/demo/LoadingPaneDemo.java new file mode 100644 index 0000000000..e4094a1db3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/demo/LoadingPaneDemo.java @@ -0,0 +1,55 @@ +/* + * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.demo; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JPanel; + +import com.fr.base.FRContext; +import com.fr.design.gui.frpane.LoadingBasicPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicDialog; + +/** + * Created by IntelliJ IDEA. + * user : Richer + * version: 6.5.5 + * Date : 11-7-1 + * Time : 下午3:32 + */ +public class LoadingPaneDemo extends JPanel { + public LoadingPaneDemo() { + setLayout(FRGUIPaneFactory.createCenterFlowLayout()); + UIButton btn = new UIButton("点我看效果"); + add(btn); + btn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + LoadingBasicPane lb = new LoadingBasicPane() { + protected void initComponents(JPanel container) { + for (int i = 0; i < 10; i++) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + container.add(new UIButton(i + "adfadwdadawdwad")); + } + } + + @Override + protected String title4PopupWindow() { + return "测试"; + } + }; + + BasicDialog dlg = lb.showWindow(null); + dlg.setVisible(true); + } + }); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/demo/MultiLineTooltipDemo.java b/designer_base/src/com/fr/design/gui/demo/MultiLineTooltipDemo.java new file mode 100644 index 0000000000..136da33f02 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/demo/MultiLineTooltipDemo.java @@ -0,0 +1,34 @@ +package com.fr.design.gui.demo; + +import java.awt.BorderLayout; + +import javax.swing.JPanel; +import javax.swing.JToolTip; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.itooltip.MultiLineToolTip; +import com.fr.design.layout.FRGUIPaneFactory; + +/** + * Created by IntelliJ IDEA. + * User: Richer + * Date: 11-6-30 + * Time: 下午9:14 + */ +public class MultiLineTooltipDemo extends JPanel { + public MultiLineTooltipDemo() { + setLayout(FRGUIPaneFactory.createBorderLayout()); + UIButton button = new UIButton("鼠标移动在此按钮上查看多行提示") { + + @Override + public JToolTip createToolTip() { + MultiLineToolTip tip = new MultiLineToolTip(); + tip.setComponent(this); + tip.setOpaque(false); + return tip; + } + }; + button.setToolTipText("Hello\nworld "); + add(button, BorderLayout.NORTH); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/demo/SwingComponentsDemo.java b/designer_base/src/com/fr/design/gui/demo/SwingComponentsDemo.java new file mode 100644 index 0000000000..b819c337fc --- /dev/null +++ b/designer_base/src/com/fr/design/gui/demo/SwingComponentsDemo.java @@ -0,0 +1,52 @@ +package com.fr.design.gui.demo; + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.DesignUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * Created by IntelliJ IDEA. + * User: Richer + * Date: 11-6-27 + * Time: 下午4:54 + */ +public class SwingComponentsDemo extends JFrame { + public SwingComponentsDemo() { + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + init(); + JPanel contentPane = (JPanel)getContentPane(); + contentPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + JTabbedPane tab = new JTabbedPane(); + contentPane.add(tab, BorderLayout.CENTER); + tab.addTab("下拉框", new ComboBoxDemo()); + tab.addTab("多行提示", new MultiLineTooltipDemo()); + tab.addTab("列表", new ListDemo()); + tab.addTab("标签", new LabelDemo()); + tab.addTab("加载耗时较多的面板", new LoadingPaneDemo()); + } + + private void init() { + DesignUtils.initLookAndFeel(); + setTitle("设计器组件演示"); + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JFrame f = new SwingComponentsDemo(); + f.setSize(500, 500); + f.setVisible(true); + GUICoreUtils.centerWindow(f); + f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + } + }); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java b/designer_base/src/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java new file mode 100644 index 0000000000..00c1f07952 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java @@ -0,0 +1,162 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.dialog.BasicPane; + +import javax.swing.*; +import java.awt.*; + + +/** + * 用于属性表中的面板,主要是为了给包含于这个面板内部的众多UI控件加监听事件,在UI控件改变的时候,通知模板做相应的变化 + */ +public abstract class AbstractAttrNoScrollPane extends BasicPane { + private static final int DEFAULT_HEIGHT = 250; + private static boolean hasChangeListener; + + protected JPanel leftContentPane; + protected Color original; + + private AttributeChangeListener listener; + private String globalName = ""; + + protected AbstractAttrNoScrollPane() { + initAll(); + } + + protected void initAll() { + enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + original = this.getBackground(); + this.setLayout(new BorderLayout()); + hasChangeListener = false; + initContentPane(); + initAllListeners(); + } + + /** + * 后台初始化所有事件. + */ + public void initAllListeners() { + initListener(AbstractAttrNoScrollPane.this); + } + + protected void initContentPane() { + leftContentPane = createContentPane(); + leftContentPane.setBorder(BorderFactory.createMatteBorder(10, 10, 0, 0, original)); + this.add(leftContentPane, BorderLayout.CENTER); + } + + protected abstract JPanel createContentPane(); + + /** + * august:不容易啊 还要用笔画图立个方程才计算出来 + */ + protected void adjustValues() { + doLayout(); + } + + protected void removeAttributeChangeListener() { + this.listener = null; + hasChangeListener = false; + } + + + protected void initListener(Container parentComponent) { + for (int i = 0; i < parentComponent.getComponentCount(); i++) { + Component tmpComp = parentComponent.getComponent(i); + + if (tmpComp instanceof Container) { + initListener((Container) tmpComp); + } + if (tmpComp instanceof GlobalNameObserver) { + ((GlobalNameObserver) tmpComp).registerNameListener(new GlobalNameListener() { + public void setGlobalName(String name) { + globalName = name; + } + + public String getGlobalName() { + return globalName; + } + }); + } + if (tmpComp instanceof UIObserver) { + ((UIObserver) tmpComp).registerChangeListener(new UIObserverListener() { + @Override + public void doChange() { + attributeChanged(); + } + }); + } + } + } + + /** + * 是否有改变监听 + * @return 是则返回true + */ + public static boolean isHasChangeListener() { + return hasChangeListener; + } + + /** + * 返回预定义的大小. + */ + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, DEFAULT_HEIGHT); + } + + + /** + * 返回绑定的属性事件. + * @param listener 增加监听 + */ + public void addAttributeChangeListener(AttributeChangeListener listener) { + this.listener = listener; + hasChangeListener = true; + } + + /** + * 响应属性事件. + */ + public void attributeChanged() { + synchronized (this) { + if (listener != null) { + listener.attributeChange(); + } + } + } + + /** + * 返回图标的路径 + */ + public abstract String getIconPath(); + + /** + * 界面标题 + * @return 标题 + */ + public abstract String title4PopupWindow(); + + /** + * 设置选中的ID, 用于双击展示界面. + */ + public void setSelectedByIds(int level, String... id) { + + } + + public String getGlobalName(){ + return globalName; + } + + /** + * 主要用于图表设计器 + * @return 是 + */ + public boolean isNeedPresentPaneWhenFilterData(){ + return true; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/AttributeChangeListener.java b/designer_base/src/com/fr/design/gui/frpane/AttributeChangeListener.java new file mode 100644 index 0000000000..f3d33c97fd --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/AttributeChangeListener.java @@ -0,0 +1,7 @@ +package com.fr.design.gui.frpane; + +public interface AttributeChangeListener { + + public void attributeChange(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/BaseHyperlinkGroup.java b/designer_base/src/com/fr/design/gui/frpane/BaseHyperlinkGroup.java new file mode 100644 index 0000000000..ed1f4a4846 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/BaseHyperlinkGroup.java @@ -0,0 +1,23 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.module.DesignModuleFactory; + +/** + * 基础的超级链接类型, 不包括图表相关超链. + * + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-6-26 下午04:46:02 + */ +public class BaseHyperlinkGroup implements HyperlinkGroupType { + + /** + * 返回支持的超级链接类型 + * + * @return + */ + public NameableCreator[] getHyperlinkCreators() { + return DesignModuleFactory.getCreators4Hyperlink(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/CommitTabbedPane.java b/designer_base/src/com/fr/design/gui/frpane/CommitTabbedPane.java new file mode 100644 index 0000000000..6c77442052 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/CommitTabbedPane.java @@ -0,0 +1,538 @@ +package com.fr.design.gui.frpane; + + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.write.submit.DBManipulationPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.javascript.Commit2DBJavaScriptPane; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.*; +import java.util.List; + +/** + * User: zheng + * Date: 14-3-28 + * Time: 下午3:24 + */ + +public class CommitTabbedPane extends JComponent implements MouseListener, MouseMotionListener { + + private Icon closeIcon = BaseUtils.readIcon("com/fr/design/images/gui/tab_delete.png"); + private static final Icon ADD_NORMAL = BaseUtils.readIcon("com/fr/design/images/gui/tab_add_normal.png"); + private static final Icon ADD_OVER = BaseUtils.readIcon("com/fr/design/images/gui/tab_add_hover.png"); + private static final Icon ADD_CLICK = BaseUtils.readIcon("com/fr/design/images/gui/tab_add_click.png"); + private static final Image DESIGN_IMAGE = BaseUtils.readImage("com/fr/design/images/sheet/left_right_btn.png"); + private static final Icon LEFT_ICON = BaseUtils.createIcon(DESIGN_IMAGE, 0, 0, 14, 14); + private static final Icon RIGHT_ICON = BaseUtils.createIcon(DESIGN_IMAGE, 14, 0, 14, 14); + private static final Icon DISABLED_LEFT_ICON = BaseUtils.createIcon(DESIGN_IMAGE, 0, 14, 14, 14); + private static final Icon DISABLED_RIGHT_ICON = BaseUtils.createIcon(DESIGN_IMAGE, 14, 14, 14, 14); + private Icon addIcon = ADD_NORMAL; + + private static final int TOOLBAR_HEIGHT = 16; // 按钮高度 + private static final int GAP = 5; //间隔 + private static final int SMALLGAP = 3; + + private static final int FIRST_TAB_POSITION = 20; + + + // 左移和右移按钮 + private UIButton leftButton; + private UIButton rightButton; + + private JPanel buttonPane; + + private List dbManipulationPaneList ; + + private Commit2DBJavaScriptPane commit2DBJavaScriptPane; + + // 能显示的tab个数 + private int showCount = 0; + + //选了30度和60度的特殊角度的x,y作为经过的两个点的坐标 + private double specialLocation1 = 2.5; + private double specialLocation2 = 4.330127; + + private int mouseOveredIndex = -1; + + private int selectedIndex = -1; + + private static final double CORNOR_RADIUS = 5.0; + + + //tab栏可以放下的每个tab的实际宽度 + private int tabWidth = 70; + + + //当前标签页栏存放的所有标签页的index + private int scrollIndex = 0; + private int lastOneIndex = 0; + + //添加标签位置 + private int addX = -1; + private int addY = -1; + + + //各删除标签位置 + private int[] closeIconStartX; + + + public CommitTabbedPane(Commit2DBJavaScriptPane commit2DBJavaScriptPane, List dbManipulationPaneList ){ + this.commit2DBJavaScriptPane = commit2DBJavaScriptPane; + this.dbManipulationPaneList = dbManipulationPaneList; + this.setLayout(new BorderLayout(0, 0)); + this.addMouseListener(this); + this.addMouseMotionListener(this); + this.setBorder(null); + this.setForeground(new Color(99, 99, 99)); + leftButton = new UIButton(LEFT_ICON) { + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, TOOLBAR_HEIGHT); + } + }; + leftButton.set4ToolbarButton(); + leftButton.setDisabledIcon(DISABLED_LEFT_ICON); + rightButton = new UIButton(RIGHT_ICON) { + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, TOOLBAR_HEIGHT); + } + }; + rightButton.set4ToolbarButton(); + rightButton.setDisabledIcon(DISABLED_RIGHT_ICON); + buttonPane = new JPanel(new BorderLayout(3, 0)); + buttonPane.add(rightButton, BorderLayout.EAST); + buttonPane.add(leftButton, BorderLayout.CENTER); + this.add(buttonPane, BorderLayout.EAST); + leftButton.addActionListener(createLeftButtonActionListener()); + rightButton.addActionListener(createRightButtonActionListener()); + + } + + private ActionListener createRightButtonActionListener(){ + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int tabCount = getTabCount(); + if (lastOneIndex < tabCount && lastOneIndex + showCount <= tabCount) { + scrollIndex += showCount; + lastOneIndex += showCount; + selectedIndex = lastOneIndex; + } else if(lastOneIndex < tabCount && lastOneIndex + showCount > tabCount){ + lastOneIndex = tabCount -1; + scrollIndex = lastOneIndex - showCount; + selectedIndex = lastOneIndex; + } + repaint(); + } + }; + } + + private ActionListener createLeftButtonActionListener() { + return new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if(scrollIndex >= showCount) { + scrollIndex -= showCount; + selectedIndex = scrollIndex; + lastOneIndex -= showCount; + } else if (scrollIndex > 0 && scrollIndex< showCount){ + scrollIndex =0; + selectedIndex = 0; + lastOneIndex = showCount; + + } + repaint(); + } + }; + } + + private void checkButton(boolean buttonEnabled) { + leftButton.setEnabled(buttonEnabled); + rightButton.setEnabled(buttonEnabled); + } + + public int getSelectedIndex(){ + return selectedIndex; + } + + public void paintComponent(Graphics g){ + super.paintComponent(g); + double maxWidth = getWidth() - buttonPane.getWidth(); + Graphics2D g2d = (Graphics2D) g; + paintBackgroundAndLine(g2d, maxWidth); + + } + + private void paintBackgroundAndLine(Graphics2D g2d, double maxWidth) { + //能画的个数 + showCount = (int) (maxWidth) / tabWidth; + //计算开始画的最小模板index和最大模板index + if (selectedIndex >= dbManipulationPaneList.size()) { + selectedIndex = dbManipulationPaneList.size() - 1; + } + if (selectedIndex < 0) { + selectedIndex = 0; + } + calMinAndMaxIndex(); + closeIconStartX = new int[lastOneIndex - scrollIndex + 1]; + + int startX = 0; + //从可以开始展示在tab面板上的tab开始画 + for (int i = scrollIndex; i <= lastOneIndex; i++) { + DBManipulationPane dbManipulationPane = (DBManipulationPane)dbManipulationPaneList.get(i); + String name ; + if (dbManipulationPane.getSubMitName() != null){ + name = dbManipulationPane.getSubMitName(); + } else { + name = createName(); + dbManipulationPane.setSubMitName(name); + } + if (i == selectedIndex) { + closeIconStartX[i - scrollIndex] = paintSelectedTab(g2d, startX,name, i); + } else { + closeIconStartX[i - scrollIndex] = paintUnSelectedTab(g2d,startX,name,i); + } + startX += tabWidth; + } + paintUnderLine(startX, maxWidth, g2d); + addX = startX + GAP; + addIcon.paintIcon(this,g2d,addX,0); + checkButton(getTabCount() > showCount); + } + + public int getTabCount(){ + return dbManipulationPaneList.size(); + } + + private String createName(){ + String prefix = Inter.getLocText("FR-Designer-CommitTab_Submit"); + int count = getTabCount(); + while (true) { + //从提交1开始 + count = count == 0 ? 1 : count; + String newName = prefix + count; + boolean repeated = false; + for (int i= 0;i < getTabCount();i++) { + if (ComparatorUtils.equals( ((DBManipulationPane)dbManipulationPaneList.get(i)).getSubMitName(), newName)) { + repeated = true; + break; + } + } + + if (!repeated) { + return newName; + } + + count++; + } + } + + + + private void paintUnderLine(double startX, double maxWidth, Graphics2D g2d) { + //画下面的那条线 + if (startX < maxWidth) { + GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, 2); + generalPath.moveTo((float) startX, (float) (getHeight() - 1)); + generalPath.lineTo((float) maxWidth, (float) (getHeight() - 1)); + g2d.fill(generalPath); + g2d.setPaint(UIConstants.LINE_COLOR); + g2d.draw(new Line2D.Double((float) startX, (float) (getHeight() - 1), (float) maxWidth , (float) (getHeight() - 1))); + } + } + + + private void calMinAndMaxIndex() { //如果个数大于最多能容纳的个数,则多余的进行处理 + + if (dbManipulationPaneList.size() > showCount) { + + if (selectedIndex >= lastOneIndex) { //所点击列表中的标签页处在标签页栏最后一个标签页之后,则标签页栏左移至所点击标签页出现 + scrollIndex = selectedIndex - showCount + 1; + lastOneIndex = selectedIndex; + if (scrollIndex <= 0) { + scrollIndex = 0; + lastOneIndex = showCount - 1; + } + } else if (selectedIndex <= scrollIndex) { //所点击列表中的标签页处在标签页栏第一个标签页之前,则标签页栏右移至所点击标签页出现 + + scrollIndex = selectedIndex; + lastOneIndex = scrollIndex + showCount - 1; + if (lastOneIndex > dbManipulationPaneList.size() - 1) { + lastOneIndex = dbManipulationPaneList.size() - 1; + } + } else { + if (selectedIndex >= dbManipulationPaneList.size() - 1) { + selectedIndex = dbManipulationPaneList.size() - 1; + lastOneIndex = selectedIndex; + scrollIndex = selectedIndex - showCount + 1; + } else { + lastOneIndex = scrollIndex + showCount - 1; + if (lastOneIndex > dbManipulationPaneList.size() - 1) { + lastOneIndex = dbManipulationPaneList.size() - 1; + } + } + } + } else { + scrollIndex = 0; + lastOneIndex = dbManipulationPaneList.size() - 1; + } + } + + + /** + * 画选中的tab + * + * @param g2d + * @param sheetName + * @return + */ + private int paintSelectedTab(Graphics2D g2d,int startX, String sheetName, int selfIndex) { + double[] x = {startX, startX, startX + tabWidth, startX + tabWidth, startX}; + double[] y = {-1, getHeight(), getHeight(), -1, -1}; + RoundRectangle2D.Double rect1 = new RoundRectangle2D.Double(startX, 1, this.getWidth(), this.getHeight(), 7, 7); + g2d.setPaint(new GradientPaint(1, 1, new Color(255, 255, 255), 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); + + GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length); + generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); + generalPath.curveTo(((float) x[0] + CORNOR_RADIUS - specialLocation1), (y[0] + CORNOR_RADIUS - specialLocation2), ((float) x[0] + CORNOR_RADIUS - specialLocation2), (y[0] + CORNOR_RADIUS - specialLocation1), (double) x[0], y[0] + CORNOR_RADIUS); + + for (int index = 1; index <= 2; index++) { + generalPath.lineTo((float) x[index], (float) y[index]); + } + + generalPath.lineTo((float) x[3], (float) y[3] + CORNOR_RADIUS); + generalPath.curveTo(((float) x[3] - CORNOR_RADIUS + specialLocation1), ((float) y[3] + CORNOR_RADIUS - specialLocation2), ((float) x[3] - CORNOR_RADIUS + specialLocation2), ((float) y[3] + CORNOR_RADIUS - specialLocation1), (float) x[3] - CORNOR_RADIUS, (float) y[3]); + generalPath.lineTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); + + generalPath.closePath(); + g2d.fill(generalPath); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setPaint(UIConstants.LINE_COLOR); + g2d.draw(new Arc2D.Double(x[0], y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0)); + g2d.draw(new Line2D.Double(x[0], y[0] + CORNOR_RADIUS, x[1], y[1])); + g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2])); + g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3] + CORNOR_RADIUS)); + g2d.draw(new Line2D.Double(x[0] + 3 ,0,x[2] - 3,0)); + g2d.draw(new Arc2D.Double(x[3] - CORNOR_RADIUS * 2, y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0)); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + // 画字符 + g2d.setPaint(getForeground()); + g2d.drawString(sheetName, startX + 2 * GAP, getHeight()-GAP); + int closePosition = startX + tabWidth - closeIcon.getIconWidth() - SMALLGAP; + int closeY = (getHeight() - closeIcon.getIconHeight()) / 2; + if (canClose() && mouseOveredIndex == selfIndex){ + closeIcon.paintIcon(this, g2d, closePosition, closeY); + } + return closePosition; + + } + + /** + * 画没有选中的tab + * + * @param g2d + * @param startX + * @param sheetName + * @return + */ + private int paintUnSelectedTab(Graphics2D g2d, int startX, String sheetName, int selfIndex) { + double[] x = {startX, startX, startX + tabWidth, startX + tabWidth, startX}; + double[] y = {-1, getHeight() - 1, getHeight() - 1, -1, -1}; + if (selfIndex == mouseOveredIndex) { + g2d.setPaint(new GradientPaint(1, 1, new Color(255, 255, 255), 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); + } else { + g2d.setPaint(new GradientPaint(1, 1, UIConstants.NORMAL_BACKGROUND, 1, getHeight() - 1, UIConstants.NORMAL_BACKGROUND)); + } + + + GeneralPath generalPath = new GeneralPath(Path2D.WIND_EVEN_ODD, x.length); + generalPath.moveTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); + generalPath.curveTo(((float) x[0] + CORNOR_RADIUS - specialLocation1), (y[0] + CORNOR_RADIUS - specialLocation2), ((float) x[0] + CORNOR_RADIUS - specialLocation2), (y[0] + CORNOR_RADIUS - specialLocation1), (double) x[0], y[0] + CORNOR_RADIUS); + + for (int index = 1; index <= 2; index++) { + generalPath.lineTo((float) x[index], (float) y[index]); + } + + generalPath.lineTo((float) x[3], (float) y[3] + CORNOR_RADIUS); + generalPath.curveTo(((float) x[3] - CORNOR_RADIUS + specialLocation1), ((float) y[3] + CORNOR_RADIUS - specialLocation2), ((float) x[3] - CORNOR_RADIUS + specialLocation2), ((float) y[3] + CORNOR_RADIUS - specialLocation1), (float) x[3] - CORNOR_RADIUS, (float) y[3]); + generalPath.lineTo((float) x[0] + CORNOR_RADIUS, (float) y[0]); + + generalPath.closePath(); + + g2d.fill(generalPath); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setPaint(UIConstants.LINE_COLOR); + + g2d.draw(new Arc2D.Double(x[0], y[0], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, 90, 0)); + g2d.draw(new Line2D.Double(x[0], y[0] + CORNOR_RADIUS, x[1], y[1])); + g2d.draw(new Line2D.Double(x[1], y[1], x[2], y[2])); + g2d.draw(new Line2D.Double(x[2], y[2], x[3], y[3] + CORNOR_RADIUS)); + g2d.draw(new Line2D.Double(x[0] + 3 ,0,x[2] - 3,0)); + g2d.draw(new Arc2D.Double(x[3] - CORNOR_RADIUS * 2, y[3], CORNOR_RADIUS * 2, CORNOR_RADIUS * 2, 90, -90, 0)); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + // 画字符 + g2d.setPaint(getForeground()); + g2d.drawString(sheetName, startX + 2 * GAP, getHeight() - GAP ); + int closeY = (getHeight() - closeIcon.getIconHeight()) / 2; + int closePosition = startX + tabWidth - closeIcon.getIconWidth() - SMALLGAP; + if (canClose() && mouseOveredIndex == selfIndex){ + closeIcon.paintIcon(this, g2d, closePosition, closeY); + } + return closePosition; + } + + + /** + * 鼠标按下 + * @param e 事件 + */ + public void mouseClicked(MouseEvent e) { + } + + /** + * 鼠标按下 + * @param e 事件 + */ + public void mousePressed(MouseEvent e) { + int x = e.getX(), y = e.getY(); + if (addX!= -1 && isOverAddIcon(x, y)){ + addIcon = ADD_CLICK; + commit2DBJavaScriptPane.createDBManipulationPane(); + selectedIndex = dbManipulationPaneList.size()-1; + commit2DBJavaScriptPane.updateCardPane(); + } else if (isOverCloseIcon(x)){ + int re = JOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(this), Inter.getLocText("FR-Designer-CommitTab_SureToDelete")+ "?", Inter.getLocText("FR-Designer-CommitTab_Remove") + , JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (re == JOptionPane.OK_OPTION) { + dbManipulationPaneList.remove(getTabIndex(x)); + commit2DBJavaScriptPane.setList(dbManipulationPaneList); + // 删除tab以后,获得第一个tab,再刷新一下,否则画面会停留在已删除的tab上,第一个tab是不可删除的 + selectedIndex = getTabIndex(FIRST_TAB_POSITION); + commit2DBJavaScriptPane.updateCardPane(); + + } + } else if (selectedIndex != getTabIndex(x)){ + selectedIndex = getTabIndex(x); + commit2DBJavaScriptPane.updateCardPane(); + } + repaint(); + } + + /** + * 鼠标离开 + * @param e 事件 + */ + public void mouseReleased(MouseEvent e) { + if(addX != -1 && isOverAddIcon(e.getX(), e.getY())){ + addIcon = ADD_NORMAL; + } + } + + /** + * 鼠标进入 + * @param e 事件 + */ + public void mouseEntered(MouseEvent e) { + } + + /** + * 鼠标离开 + * @param e 事件 + */ + public void mouseExited(MouseEvent e) { + mouseOveredIndex = -1; + repaint(); + } + + /** + * 鼠标拖动 + * @param e 事件 + */ + public void mouseDragged(MouseEvent e) { + } + + /** + * 鼠标移动 + * @param e 事件 + */ + public void mouseMoved(MouseEvent e) { + if(addX!= -1 && isOverAddIcon(e.getX(), e.getY())){ + addIcon = ADD_OVER; + } else { + mouseOveredIndex = getTabIndex(e.getX()); + addIcon = ADD_NORMAL; + } + repaint(); + } + + + /** + * 判断鼠标所在Tab + * @param evtX + * @return index + */ + private int getTabIndex ( int evtX ){ + int x = 0; + for( int i = scrollIndex;i <= lastOneIndex;i++){ + if(evtX > x && evtX <= x + tabWidth ){ + return i; + } + x = x + tabWidth; + } + return -1; + } + + /** + * 判断鼠标是否在添加按钮上 + * @param x 鼠标坐标x + * @param y 鼠标坐标y + * @return 返回鼠标是否在添加按钮上 + */ + private boolean isOverAddIcon(int x, int y){ + int addWidth = addIcon.getIconWidth(),addHeight = addIcon.getIconHeight(); + return x >= addX && x <= addX + addWidth && y > addY && y <= addY + addHeight; + } + + + /** + * 判断鼠标是否在关闭按钮上 + * @param evtX x + * @return 返回鼠标是否在关闭按钮上 + */ + private boolean isOverCloseIcon(int evtX) { + boolean isOverCloseIcon = false; + if( canClose()){ + for (int i = 0; i < closeIconStartX.length; i++) { + if (evtX >= closeIconStartX[i] && evtX <= closeIconStartX[i] + closeIcon.getIconWidth()) { + isOverCloseIcon = true; + break; + } + } + } + return isOverCloseIcon; + } + + /** + * 如果tab只剩下最后一个,则不画删除按钮 + * @return 返回当前tab还可否关闭 + */ + private boolean canClose(){ + return closeIconStartX.length > 1; + } + + /** + * 刷新tab,停留在第一个tab上面 + */ + public void refreshTab(){ + selectedIndex = getTabIndex(FIRST_TAB_POSITION); + commit2DBJavaScriptPane.updateCardPane(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/EditingStringListPane.java b/designer_base/src/com/fr/design/gui/frpane/EditingStringListPane.java new file mode 100644 index 0000000000..91b3685b1f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/EditingStringListPane.java @@ -0,0 +1,208 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.design.utils.gui.JListUtils; + +public abstract class EditingStringListPane extends BasicBeanPane> { + + private static final long serialVersionUID = 1L; + private DefaultListModel model; + private JList jlist; + private UIButton addButton; + private UIButton editButton; + private UIButton removeButton; + private UIButton moveUpButton; + private UIButton moveDownButton; + + public EditingStringListPane() { + super(); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + model = new DefaultListModel(); + jlist = new JList(model); + jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + jlist.setCellRenderer(new DefaultListCellRenderer() { + private static final long serialVersionUID = 1L; + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + this.setText(value.toString()); + return this; + } + + }); + + addButton = new UIButton(Inter.getLocText("Add")); + editButton = new UIButton(Inter.getLocText("Modify")); + removeButton = new UIButton(Inter.getLocText("Remove")); + moveUpButton = new UIButton(Inter.getLocText("Utils-Move_Up")); + moveDownButton = new UIButton(Inter.getLocText("Utils-Move_Down")); + + JPanel eastPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(1); + eastPane.add(editButton); + eastPane.add(removeButton); + eastPane.add(moveUpButton); + eastPane.add(moveDownButton); + this.add(GUICoreUtils.createBorderPane(eastPane, BorderLayout.NORTH), BorderLayout.EAST); + + JPanel centerPane = new JPanel(new BorderLayout(0, 5)); + this.add(centerPane, BorderLayout.CENTER); + JPanel northcenterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + northcenterPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5)); + northcenterPane.add(addButton, BorderLayout.EAST); + centerPane.add(northcenterPane, BorderLayout.NORTH); + centerPane.add(new JScrollPane(jlist), BorderLayout.CENTER); + + this.addListener(); + + this.addButton.setEnabled(false); + this.checkEnableState(); + } + + private void addListener() { + addListener1(); + + moveUpButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + JListUtils.upListSelectedIndex(jlist); + } + }); + moveDownButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + JListUtils.downListSelectedIndex(jlist); + } + }); + jlist.addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + Object selected = jlist.getSelectedValue(); + selectedChanged((String)selected); + } + }); + jlist.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + Object selected = jlist.getSelectedValue(); + selectedChanged((String)selected); + } + }); + } + + private void addListener1() { + addButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + String newvalue = getAddOrEditString(); + if (!model.contains(newvalue)) { + if (!StringUtils.isEmpty(newvalue)) { + model.add(model.size(), newvalue); + setAddEnabled(false); + } + } else { + JOptionPane.showMessageDialog(SwingUtilities.getWindowAncestor(EditingStringListPane.this), newvalue + Inter.getLocText("Already_exists_not_add_repeat")+"!"); + } + } + }); + editButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + int selectededIndex = jlist.getSelectedIndex(); + if (selectededIndex > -1) { + if (!StringUtils.isEmpty(getAddOrEditString())) { + model.setElementAt(getAddOrEditString(), selectededIndex); + } + } + } + }); + removeButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Object selected = jlist.getSelectedValue(); + if (selected != null) { + int re = JOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(EditingStringListPane.this), Inter.getLocText("sure_to_delete") + selected.toString() + "?"); + if (re == JOptionPane.OK_OPTION) { + JListUtils.removeSelectedListItems(jlist); + } + } + checkEnableState(); + } + }); + } + + public void checkEnableState() { + if (jlist.getSelectedIndex() < 0) { + setEditEnabled(false); + } else { + setEditEnabled(true); + } + } + + private void setEditEnabled(boolean enabled) { + this.removeButton.setEnabled(enabled); + this.editButton.setEnabled(enabled); + this.moveUpButton.setEnabled(enabled); + this.moveDownButton.setEnabled(enabled); + } + + public void setAddEnabled(boolean enabled) { + this.addButton.setEnabled(enabled); + } + + protected abstract void selectedChanged(String selected); + + protected abstract String getAddOrEditString(); + + @Override + protected String title4PopupWindow() { + return "iloveyou"; + } + + @Override + public void populateBean(List lists) { + for (String ob : lists) { + model.addElement(ob); + } + jlist.setSelectedIndex(0); + } + + @Override + public List updateBean() { + List lists = new ArrayList(); + for (int i = 0, len = model.size(); i < len; i++) { + lists.add((String)model.get(i)); + } + return lists; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupPane.java b/designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupPane.java new file mode 100644 index 0000000000..fe14127725 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupPane.java @@ -0,0 +1,90 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.actions.HyperlinkPluginAction; +import com.fr.design.actions.UpdateAction; +import com.fr.design.fun.HyperlinkProvider; +import com.fr.design.gui.controlpane.JControlPane; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.module.DesignModuleFactory; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.js.JavaScript; +import com.fr.js.NameJavaScript; +import com.fr.js.NameJavaScriptGroup; +import com.fr.plugin.PluginManager; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Nameable; + +import java.util.ArrayList; +import java.util.List; + +/** + * 超级链接 界面. + * + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-6-25 上午11:17:57 + */ +public class HyperlinkGroupPane extends JControlPane { + + /** + * 生成添加按钮的NameableCreator + * + * @return 返回Nameable按钮数组. + */ + public NameableCreator[] createNameableCreators() { + NameableCreator[] creators = DesignModuleFactory.getHyperlinkGroupType().getHyperlinkCreators(); + PluginManager.getInstance().setExtensionPoint(HyperlinkPluginAction.XML_TAG); + ArrayList templateArrayLisy = PluginManager.getInstance().getResultList(); +// if (templateArrayLisy.isEmpty()) { +// return creators; +// } + NameableCreator[] pluginCreators = new NameableCreator[templateArrayLisy.size()]; + for (int i = 0; i < templateArrayLisy.size(); i++) { + pluginCreators[i] = ((HyperlinkPluginAction) templateArrayLisy.get(i)).getHyperlinkCreator(); + } + HyperlinkProvider[] providers = ExtraDesignClassManager.getInstance().getHyperlinkProvider(); + List creatorList = new ArrayList(); + for (HyperlinkProvider provider : providers) { + NameableCreator nc = provider.createHyperlinkCreator(); + creatorList.add(nc); + } + return (NameableCreator[]) ArrayUtils.addAll(creatorList.toArray(new NameableCreator[creatorList.size()]), ArrayUtils.addAll(creators, pluginCreators)); + } + + /** + * 弹出列表的标题. + * + * @return 返回标题字符串. + */ + public String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Hyperlink"); + } + + public void populate(NameJavaScriptGroup nameHyperlink_array) { + java.util.List list = new ArrayList(); + if (nameHyperlink_array != null) { + for (int i = 0; i < nameHyperlink_array.size(); i++) { + list.add(new NameObject(nameHyperlink_array.getNameHyperlink(i).getName(), nameHyperlink_array.getNameHyperlink(i).getJavaScript())); + } + } + + this.populate(list.toArray(new NameObject[list.size()])); + } + + /** + * updateJs的Group + * + * @return 返回NameJavaScriptGroup + */ + public NameJavaScriptGroup updateJSGroup() { + Nameable[] res = this.update(); + NameJavaScript[] res_array = new NameJavaScript[res.length]; + for (int i = 0; i < res.length; i++) { + NameObject no = (NameObject) res[i]; + res_array[i] = new NameJavaScript(no.getName(), (JavaScript) no.getObject()); + } + + return new NameJavaScriptGroup(res_array); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupType.java b/designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupType.java new file mode 100644 index 0000000000..fbdb3441cb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/HyperlinkGroupType.java @@ -0,0 +1,18 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.gui.controlpane.NameableCreator; + +/** + * 超级链接 支持的类型 种类. + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-6-26 下午04:41:55 + */ +public interface HyperlinkGroupType { + + /** + * 返回支持的超级链接类型 + * @return NameableCreator[] + */ + public NameableCreator[] getHyperlinkCreators(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/ImgChoosePane.java b/designer_base/src/com/fr/design/gui/frpane/ImgChoosePane.java new file mode 100644 index 0000000000..bea968cea2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/ImgChoosePane.java @@ -0,0 +1,122 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.BaseUtils; +import com.fr.base.background.ImageBackground; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.style.background.image.ImageFileChooser; +import com.fr.design.style.background.image.ImagePreviewPane; +import com.fr.general.Inter; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +public class ImgChoosePane extends BasicPane { + + private ImagePreviewPane previewPane; + private UIButton chooseButton; + private UIButton clearButton; + private UILabel imgSizeLabel; + private ImageFileChooser imageFileChooser; + + public ImgChoosePane() { + this.initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel previewContainner = new JPanel(); + previewContainner.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("Preview"))); + + previewPane = new ImagePreviewPane(); + previewContainner.add(previewPane); + previewPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent evt) { + Image image = ((ImagePreviewPane) evt.getSource()).getImage(); + + if (image == null) { + imgSizeLabel.setText(""); + } else { +// imgSizeLabel.setText(Inter.getLocText("Size") + ": " + image.getWidth(null) + "px" +// + image.getHeight(null) + Inter.getLocText("px")); + imgSizeLabel.setText(Inter.getLocText(new String[]{"Size", "px", "px"}, + new String[]{": " + image.getWidth(null), image.getHeight(null) + ""})); + } + } + }); + + this.add(previewContainner, BorderLayout.CENTER); + + JPanel choosePane = new JPanel(new BorderLayout(0, 10)); + choosePane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + JPanel choosePane1 = new JPanel(new BorderLayout(0, 10)); + + initButton(); + choosePane.add(chooseButton, BorderLayout.NORTH); + + choosePane1.add(clearButton,BorderLayout.NORTH); + choosePane.add(choosePane1,BorderLayout.CENTER); + + imgSizeLabel = new UILabel(); + imgSizeLabel.setHorizontalAlignment(SwingConstants.CENTER); + choosePane1.add(imgSizeLabel,BorderLayout.CENTER); + this.add(choosePane,BorderLayout.EAST); + + imageFileChooser = new ImageFileChooser(); + } + + private void initButton() { + chooseButton = new UIButton(Inter.getLocText("Image-Select_Picture")); + chooseButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + + int returnVal = imageFileChooser.showOpenDialog(ImgChoosePane.this); + if (returnVal != JFileChooser.CANCEL_OPTION) { + File selectedFile = imageFileChooser.getSelectedFile(); + if (selectedFile != null && selectedFile.isFile()) { + Image image = BaseUtils.readImage(selectedFile.getPath()); + previewPane.setImage(image); + previewPane.repaint(); + } else { + previewPane.setImage(null); + } + } + } + }); + + clearButton = new UIButton(Inter.getLocText("Clear")); + clearButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + previewPane.setImage(null); + previewPane.repaint(); + } + }); + } + + public void populate(ImageBackground background) { + if(background != null && background.getImage() != null) { + previewPane.setImage(background.getImage()); + } + } + + public ImageBackground update() { + if(previewPane.getImage() == null) { + return null; + } + return new ImageBackground(previewPane.getImage()); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Image"); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/JTreeAutoBuildPane.java b/designer_base/src/com/fr/design/gui/frpane/JTreeAutoBuildPane.java new file mode 100644 index 0000000000..23c9429a5a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/JTreeAutoBuildPane.java @@ -0,0 +1,228 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.Formula; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.EditOrNewLabel; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.datapane.TreeTableDataComboBox; +import com.fr.design.data.datapane.preview.PreviewLabel; +import com.fr.data.impl.NameTableData; +import com.fr.data.impl.RecursionTableData; +import com.fr.data.impl.TableDataDictionary; +import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.design.DesignModelAdapter; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.editor.editor.*; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.List; + +public class JTreeAutoBuildPane extends BasicPane implements PreviewLabel.Previewable, EditOrNewLabel.Editable { + private TreeTableDataComboBox treeTableDataComboBox; + private ValueEditorPane valuePane; + private ValueEditorPane textPane; + private JPanel centerPane; + private JPanel selectTreeDataPanel; + + public JTreeAutoBuildPane() { + this.initComponent(); + } + + /** + * 初始化 + */ + public void initComponent() { + this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); + UILabel selectTreeDataLabel = new UILabel(Inter.getLocText("Select_A_Tree_DataSource_To_Build") + ": "); + treeTableDataComboBox = new TreeTableDataComboBox(DesignTableDataManager.getEditingTableDataSource()); + treeTableDataComboBox.setPreferredSize(new Dimension(180, 20)); + selectTreeDataPanel = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(); + selectTreeDataPanel.add(selectTreeDataLabel); + treeTableDataComboBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + tdChange(); + } + }); + selectTreeDataPanel.add(treeTableDataComboBox); + treeTableDataComboBox.setPreferredSize(new Dimension(200, 25)); + treeTableDataComboBox.setSelectedIndex(-1); + PreviewLabel pl = new PreviewLabel(this); + pl.setPreferredSize(new Dimension(25, 25)); + EditOrNewLabel enl = new EditOrNewLabel(this, this); + enl.setPreferredSize(new Dimension(25, 25)); + selectTreeDataPanel.add(pl); + selectTreeDataPanel.add(enl); + + this.add(selectTreeDataPanel, BorderLayout.NORTH); + + valuePane = ValueEditorPaneFactory.createValueEditorPane(new Editor[]{new ColumnNameEditor(), new ColumnIndexEditor()}); + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + formulaEditor.setEnabled(true); + textPane = ValueEditorPaneFactory.createValueEditorPane(new Editor[]{new ColumnNameEditor(), new ColumnIndexEditor(), formulaEditor}); + Component[][] coms = { + {new UILabel(Inter.getLocText("Actual_Value") + ":"), + valuePane}, + {new UILabel(Inter.getLocText("Display_Value") + ":"), + textPane}}; + + double p = TableLayout.PREFERRED; + + double[] rowSize = {p, p, p}; + double[] columnSize = {p, p}; + centerPane = TableLayoutHelper.createTableLayoutPane(coms, rowSize, + columnSize); + + this.add(centerPane, BorderLayout.CENTER); + tdChange(); + } + + private void tdChange() { + TableDataWrapper tableDataWrappe = this.treeTableDataComboBox.getSelectedItem(); + if (tableDataWrappe == null) { + return; + } + try { + List namelist = tableDataWrappe.calculateColumnNameList(); + String[] columnNames = new String[namelist.size()]; + namelist.toArray(columnNames); + valuePane.setEditors(new Editor[]{new ColumnNameEditor(columnNames), new ColumnIndexEditor(columnNames.length)}, columnNames[0]); + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + formulaEditor.setEnabled(true); + textPane.setEditors(new Editor[]{new ColumnNameEditor(columnNames), new ColumnIndexEditor(columnNames.length), formulaEditor}, columnNames[0]); + } catch (Exception e) { + valuePane.setEditors(new Editor[]{new OldColumnIndexEditor(100, Inter.getLocText("ColumnName"))}, 1); + FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula")); + formulaEditor.setEnabled(true); + textPane.setEditors(new Editor[]{new OldColumnIndexEditor(100, Inter.getLocText("ColumnName")), formulaEditor}, 1); + } + } + + public void populate(TableDataDictionary tableDataDict) { + if (tableDataDict == null) { + this.treeTableDataComboBox.setSelectedItem(""); + this.textPane.populate(1); + this.valuePane.populate(1); + return; + } else { + String _name = ""; + if (tableDataDict.getTableData() instanceof NameTableData) { + _name = ((NameTableData) tableDataDict.getTableData()).getName(); + } + this.treeTableDataComboBox.setSelectedTableDataByName(_name); + tdChange(); + // alex:因为显示到界面上的index是以1为始的,所以要加1 + if (!StringUtils.isEmpty(tableDataDict.getKeyColumnName())) { + this.valuePane.populate(tableDataDict.getKeyColumnName()); + } else { + this.valuePane.populate(tableDataDict.getKeyColumnIndex() + 1); + } + Object value = null; + if ((tableDataDict).getFormula() != null) { + value = (tableDataDict).getFormula(); + } else { + if (!StringUtils.isEmpty(tableDataDict.getValueColumnName())) { + value = tableDataDict.getValueColumnName(); + } else { + value = tableDataDict.getValueColumnIndex() + 1; + } + } + + this.textPane.populate(value); + } + } + + public TableDataDictionary update() { + TableDataDictionary tableDataDict = new TableDataDictionary(); + Object object = this.valuePane.update(StringUtils.EMPTY); + // alex:因为显示到界面上的index是以1为始的,所以要减1 + // carl:假如这里的序号要变,请考虑6.2的兼容 + + if (object instanceof Object[]) { + Object[] temp = (Object[]) object; + tableDataDict.setKeyColumnIndex(((Integer) temp[0]).intValue() - 1); + tableDataDict.setKeyColumnName((String) temp[1]); + } else if (object instanceof Integer) { + tableDataDict.setKeyColumnIndex((Integer) object - 1); + } else if (object instanceof String) { + tableDataDict.setKeyColumnName((String) object); + } + Object object_text = this.textPane.update(StringUtils.EMPTY); + if (object_text instanceof Object[]) { + Object[] temp = (Object[]) object_text; + if (temp[0] instanceof Formula) { + tableDataDict.setFormula((Formula) temp[0]); + } else { + tableDataDict.setValueColumnIndex(((Integer) temp[0]).intValue() - 1); + tableDataDict.setValueColumnName((String) temp[1]); + } + } else if (object_text instanceof Integer) { + tableDataDict.setValueColumnIndex((Integer) this.textPane.update() - 1); + } else if (object_text instanceof String) { + tableDataDict.setValueColumnName((String) object_text); + } else { + tableDataDict.setFormula(((Formula) object)); + } + + TableDataWrapper tableDataWrappe = this.treeTableDataComboBox.getSelectedItem(); + if (tableDataWrappe != null) { + tableDataDict.setTableData(new NameTableData(tableDataWrappe.getTableDataName())); + } + + return tableDataDict; + } + + @Override + protected String title4PopupWindow() { + return "Auto Build Tree"; + } + + /** + * 预览 + */ + public void preview() { + TableDataWrapper tableDataWrappe = treeTableDataComboBox.getSelectedItem(); + if (tableDataWrappe == null) { + return; + } + tableDataWrappe.previewData(); + } + + /** + * 编辑 + * @param jPanel 面板 + */ + public void edit(JPanel jPanel) { + RecursionTableData rtd = null; + String name = ""; + TableDataTreePane tdtp = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + if (treeTableDataComboBox.getSelectedItem() == null) { + //新建 + rtd = new RecursionTableData(); + name = TableDataTreePane.createUnrepeatedName(tdtp.getDataTree(), "Tree"); + } else { + //编辑 + rtd = treeTableDataComboBox.getSelcetedTableData(); + name = treeTableDataComboBox.getSelectedItem().getTableDataName(); + } + AbstractTableDataWrapper atdw = new TemplateTableDataWrapper(rtd, ""); + tdtp.dgEdit(atdw.creatTableDataPane(), name); + treeTableDataComboBox.refresh(); + treeTableDataComboBox.setSelectedTableDataByName(name); + textPane.populate(1); + valuePane.populate(1); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/JTreeControlPane.java b/designer_base/src/com/fr/design/gui/frpane/JTreeControlPane.java new file mode 100644 index 0000000000..f8878663bc --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/JTreeControlPane.java @@ -0,0 +1,270 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.BaseUtils; +import com.fr.data.impl.TreeNodeAttr; +import com.fr.data.impl.TreeNodeWrapper; +import com.fr.design.actions.UpdateAction; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.controlpane.ControlPane; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.controlpane.UnrepeatedNameHelper; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itoolbar.UIToolbar; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.menu.ToolBarDef; +import com.fr.form.ui.TreeEditor; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.stable.Nameable; + +import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; + +public class JTreeControlPane extends ControlPane { + // 添加一个treeNode + private AddTreeNodeAction addTreeNode; + // 移除一个treeNode + private RemoveTreeNodeAction removeTreeNode; + + private BasicBeanPane updatePane; + + private JTree tree; + private DefaultTreeModel defaultTreeModel; + + + boolean isEditor = false; + + private UICheckBox isPerformanceFirst; + + public JTreeControlPane(NameableCreator[] creators, BasicBeanPane updatePane, boolean isEditor) { + this.initComponents(creators, updatePane); + this.isEditor = isEditor; + } + + private void initComponents(NameableCreator[] creators, BasicBeanPane updatePane) { + this.setLayout(new BorderLayout(2, 2)); + this.updatePane = updatePane; + // LeftPane + JPanel leftPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel northPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(); + DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(Inter.getLocText("FR-Designer_Root")); + defaultTreeModel = new DefaultTreeModel(rootNode); + DefaultMutableTreeNode firstLayer = new DefaultMutableTreeNode(new NameObject(Inter.getLocText("FR-Designer_Gradation") + 1, new TreeNodeAttr())); + tree = new JTree(defaultTreeModel); + tree.setRootVisible(false); + ((DefaultMutableTreeNode) defaultTreeModel.getRoot()).getLastLeaf().add(firstLayer); + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + leftPane.add(new UIScrollPane(tree), BorderLayout.CENTER); + tree.addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + JTreeControlPane.this.updatePane.updateBean(); + refreshCurrentUpdatePane(); + checkButtonEnabled(); + } + }); + tree.setPreferredSize(new Dimension(170, 350)); + tree.setCellRenderer(renderer); + + // JTreeControlPane控制栏 + ToolBarDef toolbarDef = new ToolBarDef(); + toolbarDef.addShortCut(addTreeNode = new AddTreeNodeAction(creators)); + toolbarDef.addShortCut(removeTreeNode = new RemoveTreeNodeAction()); + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolbarDef.updateToolBar(toolBar); + leftPane.add(toolBar, BorderLayout.NORTH); + + + isPerformanceFirst = new UICheckBox(Inter.getLocText("FR-Designer_Performance_First")); + northPane.add(new UILabel(" ")); + northPane.add(isPerformanceFirst); + this.add(northPane, BorderLayout.NORTH); + this.add(leftPane, BorderLayout.WEST); + this.add(this.updatePane, BorderLayout.CENTER); + + this.checkButtonEnabled(); + } + + @Override + protected String title4PopupWindow() { + return "tree"; + } + + private void checkButtonEnabled() { + this.addTreeNode.setEnabled(true); + this.removeTreeNode.setEnabled(true); + + // richer:当选择了树根节点时,不能被删除、上移和下移 + DefaultMutableTreeNode root = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); + TreePath rootPath = new TreePath(defaultTreeModel.getPathToRoot(root)); + if (ComparatorUtils.equals(rootPath, tree.getSelectionPath())) { + this.removeTreeNode.setEnabled(false); + } + } + + public void populate(NameObject nameObject) { + // 重新添加tree节点的时候需要remove掉原来的所有子节点 + ((DefaultMutableTreeNode) defaultTreeModel.getRoot()).removeAllChildren(); + Object obj = nameObject.getObject(); + TreeNodeAttr[] treeNodeAttr = null; + if (obj instanceof TreeNodeAttr[]) { + treeNodeAttr = ((TreeNodeAttr[]) obj); + isPerformanceFirst.setSelected(false); + } else if (obj instanceof TreeEditor) { + TreeEditor treeEditor = (TreeEditor) obj; + treeNodeAttr = treeEditor.getTreeNodeAttr(); + isPerformanceFirst.setSelected(treeEditor.isPerformanceFirst()); + } else if (obj instanceof TreeNodeWrapper) { + treeNodeAttr = ((TreeNodeWrapper) obj).getTreeNodeAttrs(); + isPerformanceFirst.setSelected(((TreeNodeWrapper) obj).isPerformanceFirst()); + } + + int count = treeNodeAttr == null ? 0 : treeNodeAttr.length; + //将树的层次一层一层的加上去 + DefaultMutableTreeNode node4root = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); + for (int i = 0; i < count; i++) { + + DefaultMutableTreeNode node4add = new DefaultMutableTreeNode( + new NameObject(Inter.getLocText("FR-Designer_Gradation") + (i + 1), treeNodeAttr[i])); + node4root.add(node4add); + node4root = node4add; + } + + defaultTreeModel.reload(); + expandAll(tree, true); + tree.setSelectionRow(0); + } + + public NameObject update() { + if (isEditor) { + TreeEditor treeEditor = new TreeEditor(); + + treeEditor.setTreeNodeAttr(updateTreeNodeAttr()); + + treeEditor.setPerformanceFirst(isPerformanceFirst.isSelected()); + + return new NameObject("tree", treeEditor); + } else { + TreeNodeWrapper treeNodeWrapper = new TreeNodeWrapper(isPerformanceFirst.isSelected(), updateTreeNodeAttr()); + return new NameObject("tree", treeNodeWrapper); + } + } + + public TreeNodeAttr[] updateTreeNodeAttr() { + updatePane.updateBean(); + DefaultMutableTreeNode root = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); + List nodeList = new ArrayList(); + + for (; root != null; root = root.getNextNode()) { + if (!(root.getUserObject() instanceof NameObject)) { + continue; + } + NameObject no = (NameObject) root.getUserObject(); + if (no.getObject() instanceof TreeNodeAttr) { + nodeList.add((TreeNodeAttr) no.getObject()); + } + } + + return nodeList.toArray(new TreeNodeAttr[nodeList.size()]); + } + + public void refreshCurrentUpdatePane() { + TreePath selectTreePath = this.tree.getSelectionPath(); + if (selectTreePath != null) { + Object object = ((DefaultMutableTreeNode) selectTreePath.getLastPathComponent()).getUserObject(); + if (object != null) { + JTreeControlPane.this.updatePane.populateBean(object); + } + } + } + + + private class AddTreeNodeAction extends UpdateAction { + private NameableCreator creator; + + public AddTreeNodeAction(NameableCreator[] creators) { + this.creator = creators[0]; + this.setName(Inter.getLocText("FR-Designer_Add")); + this.setMnemonic('A'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/add.png")); + } + + public void actionPerformed(ActionEvent e) { + // TODO add tree node + final DefaultMutableTreeNode node = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); + Nameable nameable = creator.createNameable(new UnrepeatedNameHelper() { + + @Override + public String createUnrepeatedName(String prefix) { + DefaultMutableTreeNode innerNode = node; + int nodeCount = 0; + do { + nodeCount++; + } while ((innerNode = innerNode.getNextNode()) != null); + return prefix + nodeCount; + } + }); + + + node.getLastLeaf().add(new DefaultMutableTreeNode(nameable)); + defaultTreeModel.reload(); + TreePath path = new TreePath(defaultTreeModel.getPathToRoot(node.getLastLeaf())); + tree.setSelectionPath(path); + } + } + + private class RemoveTreeNodeAction extends UpdateAction { + public RemoveTreeNodeAction() { + this.setName(Inter.getLocText("FR-Designer_Remove")); + this.setMnemonic('R'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + } + + public void actionPerformed(ActionEvent e) { + // TODO remove tree node + int val = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Utils-Are_you_sure_to_remove_the_selected_item") + "?", + Inter.getLocText("FR-Designer_Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (val != JOptionPane.OK_OPTION) { + return; + } + TreePath selectionPath = tree.getSelectionPath(); + DefaultMutableTreeNode tmpNode = (DefaultMutableTreeNode) selectionPath.getLastPathComponent(); + tmpNode.removeFromParent(); + defaultTreeModel.reload(); + DefaultMutableTreeNode node = (DefaultMutableTreeNode) defaultTreeModel.getRoot(); + TreePath path = new TreePath(defaultTreeModel.getPathToRoot(node.getLastLeaf())); + tree.setSelectionPath(path); + } + } + + TreeCellRenderer renderer = new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + if (leaf) { + this.setIcon(BaseUtils.readIcon("com/fr/design/images/data/default_widget.png")); + } else { + this.setIcon(BaseUtils.readIcon("com/fr/design/images/data/arrow_branch.png")); + } + + if (value instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; + Object userObj = node.getUserObject(); + if (userObj instanceof NameObject) { + this.setText(((NameObject) userObj).getName()); + } + } + this.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0)); + return this; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/LimitedDocument.java b/designer_base/src/com/fr/design/gui/frpane/LimitedDocument.java new file mode 100644 index 0000000000..60d456f698 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/LimitedDocument.java @@ -0,0 +1,46 @@ +package com.fr.design.gui.frpane; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +public class LimitedDocument extends PlainDocument { + + private int maxLength = -1; + private String allowCharAsString = null; + + public LimitedDocument() { + super(); + } + + public LimitedDocument(int maxLength, String str) { + super(); + this.maxLength = maxLength; + allowCharAsString = str; + } + + @Override + public void insertString(int offset, String str, AttributeSet attrSet) + throws BadLocationException { + + if (str == null) { + return; + } + + if (allowCharAsString != null && str.length() == 1) { + if (allowCharAsString.indexOf(str) == -1) { + return; + } + } + + char[] charVal = str.toCharArray(); + String strOldValue = getText(0, getLength()); + byte[] tmp = strOldValue.getBytes(); + + if (maxLength != -1 && (tmp.length + charVal.length > maxLength)) { + return; + } + + super.insertString(offset, str, attrSet); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/ListenerUpdatePane.java b/designer_base/src/com/fr/design/gui/frpane/ListenerUpdatePane.java new file mode 100644 index 0000000000..6ade755f0c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/ListenerUpdatePane.java @@ -0,0 +1,48 @@ +package com.fr.design.gui.frpane; + + +import java.awt.BorderLayout; + +import com.fr.general.Inter; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.javascript.JavaScriptActionPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.event.Listener; + +public abstract class ListenerUpdatePane extends BasicBeanPane { + private JavaScriptActionPane actionPane; + + private Listener editing; + + public ListenerUpdatePane() { + this.initComponents(); + } + + protected void initComponents(){ + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.add(actionPane = createJavaScriptActionPane(), BorderLayout.CENTER); + } + + protected abstract JavaScriptActionPane createJavaScriptActionPane(); + + protected abstract boolean supportCellAction(); + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Event"); + } + + @Override + public void populateBean(Listener ob) { + editing = ob; + actionPane.reset(); + actionPane.populateBean(ob.getAction()); + } + + @Override + public Listener updateBean() { + editing.setAction(actionPane.updateBean()); + + return editing; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/LoadingBasicPane.java b/designer_base/src/com/fr/design/gui/frpane/LoadingBasicPane.java new file mode 100644 index 0000000000..32a2118076 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/LoadingBasicPane.java @@ -0,0 +1,84 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.CardLayout; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingConstants; +import javax.swing.SwingWorker; + +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; +import com.fr.design.utils.gui.LayoutUtils; + +/** + * @author richer + * @since 6.5.5 创建于2011-6-16 会显示正在加载的标志 + * august:改成不确定式 + */ +public abstract class LoadingBasicPane extends BasicPane { + private CardLayout card; + private JPanel container; + private JProgressBar progressBar; + public LoadingBasicPane() { + initCards(); + new SwingWorker() { + + @Override + protected Integer doInBackground() throws Exception { + initComponents(container); + return 0; + } + + @Override + protected void done() { + complete(); + LayoutUtils.layoutRootContainer(LoadingBasicPane.this); + card.show(LoadingBasicPane.this, "CONTAINER"); + } + + }.execute(); + } + + private void initCards() { + card = new CardLayout(); + setLayout(card); + JPanel loadingDisPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + String[] message = {"Loading","Please-Wait"}; + String[] operator = {",","..."}; + UILabel loadingPane = new UILabel(Inter.getLocText(message,operator) , SwingConstants.CENTER); + loadingDisPane.add(loadingPane, BorderLayout.CENTER); + progressBar = new JProgressBar(); + progressBar.setIndeterminate(true); + loadingDisPane.add(progressBar, BorderLayout.SOUTH); + + add("LOADING", loadingDisPane); + container = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + add("CONTAINER", container); + card.show(this, "LOADING"); + + + } + + protected void renameConnection(String oldName,String newName){ + + } + + protected void initComponents(JPanel container) { + + } + + /** + * 完成时 + */ + public void complete() { + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/LoadingBasicPaneTest.java b/designer_base/src/com/fr/design/gui/frpane/LoadingBasicPaneTest.java new file mode 100644 index 0000000000..eec6c91337 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/LoadingBasicPaneTest.java @@ -0,0 +1,41 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.frpane; + +import javax.swing.JPanel; + +import com.fr.base.FRContext; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.dialog.BasicDialog; +import com.fr.general.Inter; + +/** + * @author richer + * @since 6.5.5 创建于2011-6-16 + */ +public class LoadingBasicPaneTest { + + public static void main(String[] args) { + LoadingBasicPane lb = new LoadingBasicPane() { + protected void initComponents(JPanel container) { + for (int i = 0; i < 10; i++) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + container.add(new UIButton(i + "adfadwdadawdwad")); + } + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Test") ; + } + }; + BasicDialog dlg = lb.showWindow(null); + dlg.setVisible(true); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/ObjectProperiesPane.java b/designer_base/src/com/fr/design/gui/frpane/ObjectProperiesPane.java new file mode 100644 index 0000000000..4fb8a639b3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/ObjectProperiesPane.java @@ -0,0 +1,164 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.BaseUtils; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.Inter; +import com.fr.general.NameObject; +import com.fr.stable.ListMap; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Iterator; + + +public class ObjectProperiesPane extends BasicBeanPane { + private UIButton addButton; + private JPanel selectedItemPane; + private java.util.List propertyPaneList = new ArrayList(); + + public ObjectProperiesPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel buttonPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.addButton = new UIButton(Inter.getLocText("Add") + " " +Inter.getLocText("Property")); + buttonPane.add(this.addButton, BorderLayout.WEST); + this.add(buttonPane, BorderLayout.NORTH); + + this.addButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + addPropertyPane(new PropertyPane()); + ObjectProperiesPane.this.validate(); + ObjectProperiesPane.this.repaint(); + } + }); + + selectedItemPane = FRGUIPaneFactory.createY_AXISBoxInnerContainer_S_Pane(); +// selectedItemPane.setLayout(new BoxLayout(selectedItemPane,BoxLayout.Y_AXIS)); + + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + northPane.add(selectedItemPane, BorderLayout.NORTH); + + JScrollPane selectedItemScrollPane = new JScrollPane(); + selectedItemScrollPane.setViewportView(northPane); + selectedItemScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + this.add(selectedItemScrollPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return "property"; + } + + @Override + public void populateBean(ListMap propertyMap) { + this.selectedItemPane.removeAll(); + this.propertyPaneList.removeAll(propertyPaneList); + + Iterator iterator = propertyMap.entrySet().iterator(); + while (iterator.hasNext()) { + java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next(); + String key = (String)entry.getKey(); + Object obj = entry.getValue(); + PropertyPane propertyPane = new PropertyPane(); + propertyPane.populate(new NameObject(key, obj)); + addPropertyPane(propertyPane); + } + + ObjectProperiesPane.this.validate(); + ObjectProperiesPane.this.repaint(); + } + + /** + * set addButton enable state + * @param enable + */ + public void enableAddButton(boolean enable) { + this.addButton.setEnabled(enable); + } + + /** + * add propertyPane + * @param propertyPane + */ + public void addPropertyPane(PropertyPane propertyPane) { + this.selectedItemPane.add(propertyPane); + this.propertyPaneList.add(propertyPane); + } + + /** + * remove propertyPane + * @param propertyPane + */ + public void removePropertyPane(PropertyPane propertyPane) { + this.selectedItemPane.remove(propertyPane); + this.propertyPaneList.remove(propertyPane); + } + + @Override + public ListMap updateBean() { + ListMap propertyMap = new ListMap(); + + for (int i = 0; i < propertyPaneList.size(); i ++) { + NameObject nameO = ((PropertyPane)propertyPaneList.get(i)).update(); + propertyMap.put(nameO.getName(), nameO.getObject()); + } + + return propertyMap; + } + + public class PropertyPane extends JPanel { + private UITextField nameField; + private ValueEditorPane valueEditorPane; + + public PropertyPane () { + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + + UIButton cancel = new UIButton(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + cancel.setToolTipText(Inter.getLocText("Remove")); + cancel.addActionListener(cancleListener); + cancel.setMargin(new Insets(0, 0, 0, 0)); + this.add(cancel); + + this.add(new UILabel(Inter.getLocText("Name")+":")); + this.nameField = new UITextField(6); + this.add(this.nameField); + + this.add(new UILabel(Inter.getLocText("Value")+ ":")); + this.valueEditorPane = ValueEditorPaneFactory.createExtendedValueEditorPane(); + this.add(this.valueEditorPane); + } + + public void populate(NameObject nameObject) { + if (nameObject == null) { + return; + } + this.nameField.setText(nameObject.getName()); + this.valueEditorPane.populate(nameObject.getObject()); + } + + public NameObject update() { + NameObject nameO = new NameObject(); + nameO.setName(this.nameField.getText()); + nameO.setObject(this.valueEditorPane.update()); + return nameO; + } + + ActionListener cancleListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + removePropertyPane(PropertyPane.this); + ObjectProperiesPane.this.validate(); + ObjectProperiesPane.this.repaint(); + } + }; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/RegPane.java b/designer_base/src/com/fr/design/gui/frpane/RegPane.java new file mode 100644 index 0000000000..8e0ae5effb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/RegPane.java @@ -0,0 +1,489 @@ +package com.fr.design.gui.frpane; + +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.EventListener; +import java.util.EventObject; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.ListCellRenderer; + +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.form.ui.reg.CustomReg; +import com.fr.form.ui.reg.IDCardReg; +import com.fr.form.ui.reg.LengthReg; +import com.fr.form.ui.reg.MailReg; +import com.fr.form.ui.reg.MobileReg; +import com.fr.form.ui.reg.NoneReg; +import com.fr.form.ui.reg.PhoneReg; +import com.fr.form.ui.reg.PostCardReg; +import com.fr.form.ui.reg.RegExp; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +public class RegPane extends BasicPane { + public static final RegExp[] ALL_REG_TYPE = { + new NoneReg(), + //new RequiredReg(), + new LengthReg(), + //new FloatReg(), + new MailReg(), + new IDCardReg(), + new PostCardReg(), + new PhoneReg(), + new MobileReg(), + new CustomReg() + }; + + public static final RegExp[] TEXTAREA_REG_TYPE = { + new NoneReg(), + new LengthReg(), + new CustomReg() + }; + + public static final RegExp[] PASSWORD_REG_TYPE = TEXTAREA_REG_TYPE; + + private RegExp[] regType; + private UIComboBox regComboBox; + private CardLayout detailedCardLayout; + private RegLengthPane regLengthPane; + private RegPhonePane regPhonePane; + private DefaultRegPane defaultRegPane; + private CustomRegRexPane customRegRexPane; + + public RegPane() { + this(ALL_REG_TYPE); + } + + public RegPane(RegExp[] types) { + this.regType = types; + this.initComponents(); + } + + private void initComponents(){ + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + JPanel contentPane = FRGUIPaneFactory.createBoxFlowInnerContainer_S_Pane(); + this.add(contentPane); + contentPane.add(new UILabel(Inter.getLocText("FR-Designer_Input_Rule") + ":")); + regComboBox = new UIComboBox(regType); + regComboBox.setRenderer(listCellRender); + contentPane.add(regComboBox); + + final JPanel cardPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + detailedCardLayout = new CardLayout(); + cardPane.setLayout(detailedCardLayout); + cardPane.add((defaultRegPane = new DefaultRegPane()), "Default"); + cardPane.add((regLengthPane = new RegLengthPane()), "Length"); + cardPane.add((regPhonePane = new RegPhonePane()), "Phone"); + cardPane.add((customRegRexPane = new CustomRegRexPane()), "Custom"); + + this.add(cardPane); + regComboBox.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + RegExp regExp = (RegExp)regComboBox.getSelectedItem(); + if(regExp instanceof PhoneReg) { + Object selectItem = regPhonePane.dataTypeComboBox.getSelectedItem(); + String regString = selectItem == null ? StringUtils.EMPTY : selectItem.toString(); + firePhoneRegAction(regString); + detailedCardLayout.show(cardPane, "Phone"); + } + else { + if (regExp instanceof LengthReg){ + detailedCardLayout.show(cardPane, "Length"); + } else if (regExp instanceof CustomReg){ + detailedCardLayout.show(cardPane, "Custom"); + } else { + detailedCardLayout.show(cardPane, "Default"); + } + fireRegChangeAction(); + } + } + }); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Input_Rule"); + } + + private int getRegTypeIndex(RegExp regex) { + if (regex != null) { + for (int i = 0; i < regType.length; i++) { + if (regex.getClass().isInstance(regType[i])) { + return i; + } + } + } + + return 0; + } + + public void populate(RegExp regex) { + regComboBox.setSelectedIndex(getRegTypeIndex(regex)); + if (regex instanceof LengthReg) { + regLengthPane.populate(regex); + } else if (regex instanceof PhoneReg) { + regPhonePane.populate(regex); + } else if (regex instanceof CustomReg) { + customRegRexPane.populate(regex); + } else { + defaultRegPane.populate(regex); + } + } + + public RegExp update(){ + RegExp regExp = (RegExp)regComboBox.getSelectedItem(); + + if (regExp instanceof LengthReg){ + return regLengthPane.update(); + } else if(regExp instanceof PhoneReg) { + return regPhonePane.update(); + } else if(regExp instanceof NoneReg || regExp instanceof MailReg || regExp instanceof IDCardReg + || regExp instanceof PostCardReg || regExp instanceof PhoneReg || regExp instanceof MobileReg) { + return regExp; + } + else if (regExp instanceof CustomReg){ + if (customRegRexPane.isEmpty()) { + return new NoneReg(); + } + return customRegRexPane.update(); + } else { + return defaultRegPane.update(); + } + } + + private static abstract class DisplayPane extends BasicPane { + public abstract void populate(RegExp regRex); + + public abstract RegExp update(); + } + + private static class DefaultRegPane extends DisplayPane { + public RegExp regRex; + + public DefaultRegPane(){ + + } + + + @Override + protected String title4PopupWindow() { + return "Default"; + } + + @Override + public void populate(RegExp regRex) { + + } + + @Override + public RegExp update() { + + return this.regRex; + } + } + + /** + * 添加电话规则监听器 + * + * @param listener 监听器 + * + * + * @date 2014-12-3-下午7:30:55 + * + */ + public void addPhoneRegListener(PhoneRegListener listener) { + this.listenerList.add(PhoneRegListener.class, listener); + } + + /** + * 移除电话规则监听器 + * + * @param listener 监听器 + * + * + * @date 2014-12-3-下午7:30:55 + * + */ + public void removePhoneRegListener(PhoneRegListener listener) { + this.listenerList.remove(PhoneRegListener.class, listener); + } + + /** + * 添加正则监听器 + * + * @param listener 监听器 + * + * + * @date 2014-12-3-下午7:29:48 + * + */ + public void addRegChangeListener(RegChangeListener listener) { + this.listenerList.add(RegChangeListener.class, listener); + } + + /** + * 移除正则监听器 + * + * @param listener 监听器 + * + * + * @date 2014-12-3-下午7:29:48 + * + */ + public void removeRegChangeListener(RegChangeListener listener) { + this.listenerList.remove(RegChangeListener.class, listener); + } + + public class PhoneRegEvent extends EventObject { + private String phoneRegString; + public PhoneRegEvent(Object source, String phoneRegString) { + super(source); + this.setPhoneRegString(phoneRegString); + } + public void setPhoneRegString(String phoneRegString) { + this.phoneRegString = phoneRegString; + } + public String getPhoneRegString() { + return phoneRegString; + } + } + public class RegChangeEvent extends EventObject { + private String regString; + public RegChangeEvent(Object source, String regString) { + super(source); + this.setRegString(regString); + } + public void setRegString(String regString) { + this.regString = regString; + } + public String getRegString() { + return regString; + } + } + + public interface PhoneRegListener extends EventListener{ + + /** + * 电话规则变化监听 + * + * @param e 变化事件 + * + * + * @date 2014-12-3-下午7:29:01 + * + */ + void phoneRegChangeAction(PhoneRegEvent e); + + } + + public interface RegChangeListener extends EventListener { + + /** + * 正则表达规则变化监听 + * + * + * @date 2014-12-3-下午7:29:01 + * + */ + void regChangeAction(); + } + protected void firePhoneRegAction(String phoneReg) { + Object[] listeners = listenerList.getListenerList(); + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==PhoneRegListener.class) { + ((PhoneRegListener)listeners[i+1]).phoneRegChangeAction(new PhoneRegEvent(this , phoneReg)); + } + } + } + protected void fireRegChangeAction() { + Object[] listeners = listenerList.getListenerList(); + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==RegChangeListener.class) { + ((RegChangeListener)listeners[i+1]).regChangeAction(); + } + } + } + private class RegPhonePane extends DisplayPane { + private static final String EMB_REG1 = "025-85679591"; + private static final String EMB_REG2 = "02585679591"; + private static final String EMB_REG3 = "025 85679591"; + private static final int LIMIT_LENGTH = 20; + private static final String REG_PATTERN = "0123456789-*# "; + + private UIComboBox dataTypeComboBox; + private final String[] dataType = {EMB_REG1, EMB_REG2, EMB_REG3, Inter.getLocText("FR-Designer_Custom")}; + DefaultComboBoxModel DefaultComboBoxModel= new DefaultComboBoxModel(dataType); + public RegPhonePane() { + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + this.add(new UILabel(Inter.getLocText("FR-Designer_Data_Type") + ":")); + dataTypeComboBox = new UIComboBox(DefaultComboBoxModel); + JTextField editFiled = (JTextField)(dataTypeComboBox.getEditor().getEditorComponent()); + editFiled.setDocument(new LimitedDocument(LIMIT_LENGTH, REG_PATTERN)); + dataTypeComboBox.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + if(ComparatorUtils.equals(e.getItem(), dataType[3])) { + dataTypeComboBox.setSelectedItem(null); + dataTypeComboBox.setEditable(true); + firePhoneRegAction(EMB_REG1); + } else { + dataTypeComboBox.setEditable(false); + firePhoneRegAction(dataTypeComboBox.getSelectedItem().toString()); + } + } + } + }); + dataTypeComboBox.setSelectedIndex(0); + firePhoneRegAction(dataTypeComboBox.getSelectedItem().toString()); + this.add(dataTypeComboBox); + } + @Override + protected String title4PopupWindow() { + return "PHONE"; + } + + @Override + public void populate(RegExp regRex) { + if(!(regRex instanceof PhoneReg)) { + return ; + } + String regstr = ((PhoneReg)regRex).getRegString(); + if (checkEmbedded(regstr)){ + DefaultComboBoxModel.addElement(regstr); + } + dataTypeComboBox.setSelectedItem(((PhoneReg)regRex).getRegString()); + } + + private boolean checkEmbedded(String regstr){ + return !ComparatorUtils.equals(EMB_REG1, regstr) && + !ComparatorUtils.equals(EMB_REG2, regstr) && + !ComparatorUtils.equals(EMB_REG3, regstr); + } + + @Override + public RegExp update() { + PhoneReg regRex = new PhoneReg(); + regRex.setRegString((String)(dataTypeComboBox.getSelectedItem())); + return regRex; + } + } + + private static class RegLengthPane extends DisplayPane { + private UISpinner minLenSpinner; + private UISpinner maxLenSpinner; + + public RegLengthPane(){ + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + this.add(new UILabel(Inter.getLocText("FR-Designer_Reg_Min_Length") + ":")); + minLenSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 0); + this.add(minLenSpinner); + this.add(new UILabel(Inter.getLocText("FR-Designer_Reg_Max_Length") + ":")); + maxLenSpinner = new UISpinner(0, Integer.MAX_VALUE, 1, 0); + this.add(maxLenSpinner); + } + + @Override + protected String title4PopupWindow() { + return "LENGTH"; + } + + @Override + public void populate(RegExp regRex) { + if (!(regRex instanceof LengthReg)){ + return; + } + + int minLength = ((LengthReg)regRex).getMinLen(); + int maxLength = ((LengthReg)regRex).getMaxLen(); + minLenSpinner.setValue(minLength); + maxLenSpinner.setValue(maxLength); + } + + @Override + public RegExp update() { + int startLength = ((Number)minLenSpinner.getValue()).intValue(); + int endLength = ((Number)maxLenSpinner.getValue()).intValue(); + LengthReg regRex = new LengthReg(); + regRex.setMinLen(startLength); + regRex.setMaxLen(endLength); + + return regRex; + } + } + + private static class CustomRegRexPane extends DisplayPane{ + private UITextField regTextField; + + public CustomRegRexPane(){ + this.setLayout(FRGUIPaneFactory.createLabelFlowLayout()); + this.add(new UILabel(Inter.getLocText("FR-Designer_Reg_Expressions") + ":")); + regTextField = new UITextField(20); + this.add(regTextField); + } + + @Override + protected String title4PopupWindow() { + return "CUSTOM"; + } + + @Override + public void populate(RegExp regRex) { + if (!(regRex instanceof CustomReg)){ + return; + } + regTextField.setText(regRex.toRegText()); + } + + @Override + public RegExp update() { + return new CustomReg(regTextField.getText()); + } + + public boolean isEmpty() { + return StringUtils.isEmpty(regTextField.getText()); + } + } + + ListCellRenderer listCellRender = new UIComboBoxRenderer(){ + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (value instanceof NoneReg){ + this.setText(Inter.getLocText("FR-Designer_None")); + } else if (value instanceof LengthReg){ + this.setText(Inter.getLocText("FR-Designer_Length")); + } else if (value instanceof MailReg){ + this.setText(Inter.getLocText("FR-Designer_Email")); + } else if (value instanceof PhoneReg){ + this.setText(Inter.getLocText("FR-Designer_Phone")); + } else if (value instanceof MobileReg) { + this.setText(Inter.getLocText("FR-Designer_MobilePhone")); + } else if (value instanceof IDCardReg){ + this.setText(Inter.getLocText("FR-Designer_IDCard")); + } else if (value instanceof PostCardReg){ + this.setText(Inter.getLocText("FR-Designer_PostCode")); + } else if (value instanceof CustomReg){ + this.setText(Inter.getLocText("FR-Designer_Custom")); + } + return this; + } + + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/ReportletParameterViewPane.java b/designer_base/src/com/fr/design/gui/frpane/ReportletParameterViewPane.java new file mode 100644 index 0000000000..23e241d6b0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/ReportletParameterViewPane.java @@ -0,0 +1,128 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.util.List; + +import javax.swing.event.TableModelListener; + +import com.fr.base.Parameter; +import com.fr.base.core.KV; +import com.fr.design.gui.itableeditorpane.ParameterTableModel; +import com.fr.design.gui.itableeditorpane.UITableEditAction; +import com.fr.design.gui.itableeditorpane.UITableEditorPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.ParameterProvider; + +/** + * Defin hyperlink. + * in fact,this is a TablEditorPane + * @editor zhou + * @since 2012-3-23下午3:48:10 + */ +public class ReportletParameterViewPane extends BasicPane { + private UITableEditorPane editorPane; + + + public ReportletParameterViewPane() { + this.initComponent(null, ParameterTableModel.NO_CHART_USE); + } + + // kunsnat: 控制是否用Chart的热点链接actions + public ReportletParameterViewPane(int useParaType) { + this.initComponent(null, useParaType); + } + + public ReportletParameterViewPane(UITableEditAction[] actions, int useParaType) { + this.initComponent(actions, useParaType); + } + + /** + * 初始化组件 + * @param actions Chart的热点链接actions + * @param useParaType 类型 + */ + public void initComponent(final UITableEditAction[] actions, int useParaType) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + if (useParaType != ParameterTableModel.NO_CHART_USE) { + ParameterTableModel model = new ParameterTableModel(useParaType, this) { + @Override + public UITableEditAction[] createAction() { + UITableEditAction[] tableEditActions = new UITableEditAction[] { new AddChartParameterAction(), new DeleteAction(this.component), + new MoveUpAction(), new MoveDownAction() }; + return (UITableEditAction[]) ArrayUtils.addAll(tableEditActions, actions); + } + }; + editorPane = new UITableEditorPane(model); + } else { + editorPane = new UITableEditorPane(new ParameterTableModel() { + @Override + public UITableEditAction[] createAction() { + return (UITableEditAction[]) ArrayUtils.addAll(super.createAction(), actions); + } + }); + } + + this.add(editorPane, BorderLayout.CENTER); + } + + + /** + * 增加事件监听 + * @param l 加的东东 + */ + public void addTableEditorListener(TableModelListener l) { + editorPane.addTableListener(l); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Parameters"); + } + + public void populate(ParameterProvider[] parameters) { + if (parameters == null) { + return; + } + editorPane.populate(parameters); + } + + public void populate(KV[] kv) { + if (kv == null) { + return; + } + Parameter[] parameters = new Parameter[kv.length]; + for (int i = 0; i < kv.length; i++) { + parameters[i] = new Parameter(kv[i].getKey(), kv[i].getValue()); + } + this.populate(parameters); + } + + public List update() { + return editorPane.update(); + } + + /** + * 更新 + * @return 数组 + */ + public KV[] updateKV() { + List list = this.update(); + int length = list.size(); + KV[] kv = new KV[length]; + for (int i = 0; i < length; i++) { + kv[i] = new KV(); + kv[i].setKey(list.get(i).getName()); + kv[i].setValue( list.get(i).getValue()); + } + return kv; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/TemplateParameterPane.java b/designer_base/src/com/fr/design/gui/frpane/TemplateParameterPane.java new file mode 100644 index 0000000000..eae278e38f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/TemplateParameterPane.java @@ -0,0 +1,89 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Component; + +import javax.swing.BorderFactory; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.base.Parameter; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.layout.TableLayout; +import com.fr.design.layout.TableLayoutHelper; +import com.fr.design.dialog.BasicPane; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.general.Inter; + +/** + * 模板的参数添加面板 + * @since 6.5.4 + */ +public class TemplateParameterPane extends BasicPane { + private UITextField nameTextField; + private ValueEditorPane valuePane; + + public TemplateParameterPane() { + this.initComponents(); + } + + public void initComponents() { + this.setBorder(BorderFactory.createTitledBorder(Inter.getLocText("Parameter"))); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(northPane, BorderLayout.NORTH); +// northPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + + JPanel defaultPane = FRGUIPaneFactory.createNormalFlowInnerContainer_M_Pane(); + northPane.add(defaultPane, BorderLayout.CENTER); + UILabel nameLabel = new UILabel(Inter.getLocText("Name") + ":"); + UILabel valueLabel = new UILabel(Inter.getLocText("Value") + ":"); + + nameTextField = new UITextField(12); + valuePane = ValueEditorPaneFactory.createBasicValueEditorPane(); + double i = TableLayout.PREFERRED; + double j = TableLayout.FILL; + double[] column = {i, j}; + double[] row = {i, i}; + Component[][] coms = {{nameLabel, nameTextField}, {valueLabel, valuePane}}; + JPanel centerPane = TableLayoutHelper.createTableLayoutPane(coms, row, column); + defaultPane.add(centerPane, BorderLayout.CENTER); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Parameter"); + } + + public void populate(Parameter parameter) { + if (parameter == null) { + return; + } + + nameTextField.setText(parameter.getName()); + valuePane.populate(parameter.getValue()); + } + + public Parameter update() { + Parameter parameter = new Parameter(); + + parameter.setName(this.nameTextField.getText()); + parameter.setValue(valuePane.update()); + return parameter; + } + + /** + * Check valid. + */ + @Override + public void checkValid() throws Exception { + Parameter parameter = this.update(); + if (parameter.getName() == null || parameter.getName().trim().length() <= 0) { + throw new Exception(Inter.getLocText("ParameterD-Parameter_name_cannot_be_null") + "."); + } + this.valuePane.checkValid(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/TreeSettingPane.java b/designer_base/src/com/fr/design/gui/frpane/TreeSettingPane.java new file mode 100644 index 0000000000..1039cfac6c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/TreeSettingPane.java @@ -0,0 +1,215 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import com.fr.data.impl.TreeNodeWrapper; +import com.fr.design.data.DataCreatorUI; +import com.fr.design.gui.ilable.UILabel; + +import javax.swing.*; + +import com.fr.general.NameObject; +import com.fr.data.impl.TableDataDictionary; +import com.fr.data.impl.TreeAttr; +import com.fr.data.impl.TreeNodeAttr; +import com.fr.design.gui.controlpane.NameObjectCreator; +import com.fr.design.gui.controlpane.NameableCreator; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.itree.refreshabletree.TreeDataCardPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.form.ui.TreeComboBoxEditor; +import com.fr.form.ui.TreeEditor; +import com.fr.general.Inter; + +public class TreeSettingPane extends BasicPane implements DataCreatorUI { + private JTreeControlPane controlPane; + private JTreeAutoBuildPane autoBuildPane; + private UIComboBox buildBox; + /** + * + */ + private static final long serialVersionUID = 1762889323082827111L; + + private String[] buildWay = new String[] { Inter.getLocText("FR-Designer_Layer-Build"), + Inter.getLocText("FR-Designer_Auto-Build") }; + + public TreeSettingPane(boolean isEditor) { + this.initComponents(isEditor); + } + + private void initComponents(boolean isEditor) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel buildWayPanel= FRGUIPaneFactory.createMediumHGapFlowInnerContainer_M_Pane(); + UILabel buildWayLabel = new UILabel(Inter.getLocText("FR-Designer_Build-Way") + " :"); + buildWayPanel.add(buildWayLabel); + buildBox = new UIComboBox(buildWay); + buildBox.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + cardChanged(buildBox.getSelectedIndex()); + } + }); + buildWayPanel.add(buildBox); + + controlPane = new JTreeControlPane(new NameableCreator[] { treeNode }, + new TreeDataCardPane(), isEditor); + autoBuildPane = new JTreeAutoBuildPane(); + this.add(buildWayPanel, BorderLayout.NORTH); + cardChanged(0); + } + + private void cardChanged(int index) { + this.remove(controlPane); + this.remove(autoBuildPane); + this.add(index == 0 ? controlPane : autoBuildPane, BorderLayout.CENTER); + validate(); + repaint(); + revalidate(); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("FR-Designer_Create_Tree"); + } + + @Override + public JComponent toSwingComponent() { + return this; + } + + NameableCreator treeNode = new NameObjectCreator( + Inter.getLocText("FR-Designer_Gradation"), + "/com/fr/design/images/data/source/jdbcTableData.png", + TreeNodeAttr.class); + + /** + * + * @param treeEditor + */ + public void populate(TreeEditor treeEditor) { + boolean isAutoBuild = treeEditor.isAutoBuild(); + TreeAttr treeAttr = treeEditor.getTreeAttr(); + if (treeAttr != null) { + NameObject no = new NameObject("name", treeEditor); + controlPane.populate(no); + } + if (isAutoBuild) { + buildBox.setSelectedIndex(1); + TableDataDictionary dictionary = treeEditor.getDictionary(); + autoBuildPane.populate(dictionary); + } else { + buildBox.setSelectedIndex(0); + } + } + + /** + * 视图树的update + * @return + */ + public TreeEditor updateTreeEditor() { +// NameObject no = this.controlPane.update(); +// if (no != null) { +// return ((TreeEditor) no.getObject()); +// } +// +// return null; + TreeEditor te = new TreeEditor(); + if (buildBox.getSelectedIndex() == 1) { + TableDataDictionary dictionary = this.autoBuildPane.update(); + te.setAutoBuild(true); + te.setDictionary(dictionary); + te.setNodeOrDict(dictionary); + } else { + te.setAutoBuild(false); + NameObject no = this.controlPane.update(); + if (no != null) { + TreeEditor editor = (TreeEditor) no.getObject(); + te.setAllowBlank(editor.isAllowBlank()); + te.setEnabled(editor.isEnabled()); + te.setDirectEdit(editor.isDirectEdit()); + te.setErrorMessage(editor.getErrorMessage()); + te.setWidgetName(editor.getWidgetName()); + te.setVisible(editor.isVisible()); + te.setWaterMark(editor.getWaterMark()); + te.setRemoveRepeat(editor.isRemoveRepeat()); + te.setTreeAttr(editor.getTreeAttr()); + te.setTreeNodeAttr(editor.getTreeNodeAttr()); + te.setNodeOrDict(editor.getTreeNodeAttr()); + te.setPerformanceFirst(editor.isPerformanceFirst()); + } + } + return te; + } + + /** + * 树节点属性的update + * @return + */ + public Object updateTreeNodeAttrs() { + if(buildBox.getSelectedIndex() == 0) { + NameObject no = controlPane.update(); + if (no != null) { + return no.getObject(); + } + } else { + return autoBuildPane.update(); + } + return null; + } + + /** + * 下拉树的update + * @return + */ + public TreeComboBoxEditor updateTreeComboBox() { + TreeComboBoxEditor tcb = new TreeComboBoxEditor(); + if (buildBox.getSelectedIndex() == 1) { + TableDataDictionary dictionary = this.autoBuildPane.update(); + tcb.setAutoBuild(true); + tcb.setDictionary(dictionary); + tcb.setNodeOrDict(dictionary); + } else { + tcb.setAutoBuild(false); + NameObject no = this.controlPane.update(); + if (no != null) { + if (no.getObject() instanceof TreeComboBoxEditor) { + return (TreeComboBoxEditor) no.getObject(); + } + + TreeEditor editor = (TreeEditor) no.getObject(); + tcb.setAllowBlank(editor.isAllowBlank()); + tcb.setEnabled(editor.isEnabled()); + tcb.setDirectEdit(editor.isDirectEdit()); + tcb.setErrorMessage(editor.getErrorMessage()); + tcb.setWidgetName(editor.getWidgetName()); + tcb.setVisible(editor.isVisible()); + tcb.setWaterMark(editor.getWaterMark()); + tcb.setRemoveRepeat(editor.isRemoveRepeat()); + tcb.setTreeAttr(editor.getTreeAttr()); + tcb.setTreeNodeAttr(editor.getTreeNodeAttr()); + tcb.setNodeOrDict(editor.getTreeNodeAttr()); + tcb.setPerformanceFirst(editor.isPerformanceFirst()); + } + } + return tcb; + } + + /** + * + * @param nodeOrDict + */ + public void populate(Object nodeOrDict) { + if(nodeOrDict instanceof TreeNodeAttr[] || nodeOrDict instanceof TreeNodeWrapper) { + buildBox.setSelectedIndex(0); + NameObject no = new NameObject("name", nodeOrDict); + controlPane.populate(no); + } else if(nodeOrDict instanceof TableDataDictionary) { + buildBox.setSelectedIndex(1); + autoBuildPane.populate((TableDataDictionary)nodeOrDict); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UIAdvancedTextPane.java b/designer_base/src/com/fr/design/gui/frpane/UIAdvancedTextPane.java new file mode 100644 index 0000000000..0194551da4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UIAdvancedTextPane.java @@ -0,0 +1,197 @@ +package com.fr.design.gui.frpane; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Action; +import javax.swing.KeyStroke; +import javax.swing.event.DocumentEvent; +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.UndoableEditListener; +import javax.swing.text.AbstractDocument.DefaultDocumentEvent; +import javax.swing.text.Document; +import javax.swing.undo.UndoManager; +import javax.swing.undo.UndoableEdit; + +import com.fr.base.BaseUtils; +import com.fr.design.actions.UpdateAction; +import com.fr.design.menu.KeySetUtils; +import com.fr.general.Inter; + +/** + * p:这是一个增强的JTextPane,支持很多Action + */ +public class UIAdvancedTextPane extends UITextPane { + /** + * + */ + private static final long serialVersionUID = 1L; + private UpdateAction undoAction, redoAction, + cutAction, copyAction, pasteAction; + private UndoManager undoManager = new UndoManager(); + + /** + * Constructor + */ + public UIAdvancedTextPane() { + undoAction = new UndoAction(); + redoAction = new RedoAction(); + cutAction = new CutAction(); + copyAction = new CopyAction(); + pasteAction = new PasteAction(); + + applyDocument(); + + //p:当调用setDocument()方法的时候,调用这个property change的方法. + this.addPropertyChangeListener("document", new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + applyDocument(); + } + }); + } + + //p:将Listener加到Document里面 + private void applyDocument() { + Document textDocument = getDocument(); + textDocument.addUndoableEditListener(new UndoableEditListener() { + public void undoableEditHappened(UndoableEditEvent evt) { + UndoableEdit undoableEdit = evt.getEdit(); + if(undoableEdit instanceof DefaultDocumentEvent) { + DefaultDocumentEvent comEdit = (DefaultDocumentEvent) undoableEdit; + if(comEdit.getType() == DocumentEvent.EventType.CHANGE) { + return; + } + } + + undoManager.addEdit(evt.getEdit()); + } + }); + this.getInputMap().put((KeyStroke)undoAction.getValue(Action.ACCELERATOR_KEY), "undo"); + this.getInputMap().put((KeyStroke)redoAction.getValue(Action.ACCELERATOR_KEY), "redo"); + this.getActionMap().put("undo", undoAction); + this.getActionMap().put("redo", redoAction); + } + + public UpdateAction getUndoAction() { + return undoAction; + } + + public UpdateAction getRedoAction() { + return redoAction; + } + + public UpdateAction getCutAction() { + return cutAction; + } + + public UpdateAction getCopyAction() { + return copyAction; + } + + public UpdateAction getPasteAction() { + return pasteAction; + } + + private class UndoAction extends UpdateAction { + public UndoAction() { + this.setMenuKeySet(KeySetUtils.UNDO); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/undo.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + public void actionPerformed(ActionEvent evt) { + if(undoManager.canUndo()) { + undoManager.undo(); + requestFocus(); + } + } + + @Override + public boolean isEnabled() { + return undoManager.canUndo(); + } + } + + class RedoAction extends UpdateAction { + public RedoAction() { + this.setMenuKeySet(KeySetUtils.REDO); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/redo.png")); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + public void actionPerformed(ActionEvent evt) { + if(undoManager.canRedo()) { + undoManager.redo(); + requestFocus(); + } + } + + @Override + public boolean isEnabled() { + return undoManager.canRedo(); + } + } + + private class CutAction extends UpdateAction { + public CutAction() { + setName(Inter.getLocText("M_Edit-Cut")); + setMnemonic('T'); + setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/cut.png")); + setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK)); + } + + public void actionPerformed(ActionEvent evt) { + cut(); + requestFocus(); + } + + @Override + public boolean isEnabled() { + return UIAdvancedTextPane.this.getSelectedText() == null; + } + } + + private class CopyAction extends UpdateAction { + public CopyAction() { + this.setName(Inter.getLocText("M_Edit-Copy")); + this.setMnemonic('C'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/copy.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); + } + + public void actionPerformed(ActionEvent evt) { + copy(); + requestFocus(); + } + + @Override + public boolean isEnabled() { + return UIAdvancedTextPane.this.getSelectedText() == null; + } + } + + private class PasteAction extends UpdateAction { + public PasteAction() { + this.setName(Inter.getLocText("M_Edit-Paste")); + this.setMnemonic('P'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_edit/paste.png")); + this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK)); + } + + public void actionPerformed(ActionEvent evt) { + paste(); + requestFocus(); + } + + @Override + public boolean isEnabled() { + return true; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UIBasicOptionPaneUI.java b/designer_base/src/com/fr/design/gui/frpane/UIBasicOptionPaneUI.java new file mode 100644 index 0000000000..1d109eae28 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UIBasicOptionPaneUI.java @@ -0,0 +1,266 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.stable.ArrayUtils; +import sun.swing.DefaultLookup; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicOptionPaneUI; +import java.awt.*; +import java.awt.event.ActionListener; +import java.awt.event.HierarchyEvent; +import java.awt.event.HierarchyListener; +import java.util.Locale; + +/** + * Created by zack on 2015/3/3. + */ +public class UIBasicOptionPaneUI extends BasicOptionPaneUI { + private static final int NUM_8 = 8; + private static final int NUM_4 = 4; + + /** + * 创建组件UI + * @param x 组件 + * @return 组件 + */ + public static ComponentUI createUI(JComponent x) { + return new UIBasicOptionPaneUI(); + } + @Override + protected Object[] getButtons() { + if (optionPane != null) { + int minimumWidth = + DefaultLookup.getInt(optionPane, this, + "OptionPane.buttonMinimumWidth", -1); + Object[] suppliedOptions = optionPane.getOptions(); + if (suppliedOptions == null) { + Object[] defaultOptions; + int type = optionPane.getOptionType(); + Locale l = optionPane.getLocale(); + if (type == JOptionPane.YES_NO_OPTION) { + defaultOptions = new ButtonFactory[2]; + defaultOptions[0] = new ButtonFactory( + UIManager.getString("OptionPane.yesButtonText", l), + getMnemonic("OptionPane.yesButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.yesIcon"), minimumWidth); + defaultOptions[1] = new ButtonFactory(UIManager.getString("OptionPane.noButtonText", l), + getMnemonic("OptionPane.noButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.noIcon"), minimumWidth); + } else if (type == JOptionPane.YES_NO_CANCEL_OPTION) { + defaultOptions = getYNCTypeOptions(minimumWidth, l); + } else if (type == JOptionPane.OK_CANCEL_OPTION) { + defaultOptions = new ButtonFactory[2]; + defaultOptions[0] = new ButtonFactory(UIManager.getString("OptionPane.okButtonText",l), + getMnemonic("OptionPane.okButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.okIcon"), minimumWidth); + defaultOptions[1] = new ButtonFactory( + UIManager.getString("OptionPane.cancelButtonText",l), + getMnemonic("OptionPane.cancelButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.cancelIcon"), minimumWidth); + } else { + defaultOptions = new ButtonFactory[1]; + defaultOptions[0] = new ButtonFactory(UIManager.getString("OptionPane.okButtonText",l), + getMnemonic("OptionPane.okButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.okIcon"), minimumWidth); + } + return defaultOptions; + } + Object[] suppliedFlatOptions =new ButtonFactory[suppliedOptions.length]; + for (int i = 0; i < suppliedOptions.length; i++) { + suppliedFlatOptions[i]=new ButtonFactory(suppliedOptions[i].toString(), 0, null, minimumWidth); + } + return suppliedFlatOptions; + } + return ArrayUtils.EMPTY_OBJECT_ARRAY; + } + private int getMnemonic(String key, Locale l) { + String value = (String)UIManager.get(key, l); + + if (value == null) { + return 0; + } + try { + return Integer.parseInt(value); + } + catch (NumberFormatException nfe) { } + return 0; + } + private Object[] getYNCTypeOptions(int minimumWidth, Locale l){ + Object[] defaultOptions = new ButtonFactory[3]; + defaultOptions[0] = new ButtonFactory( + UIManager.getString("OptionPane.yesButtonText", l), + getMnemonic("OptionPane.yesButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.yesIcon"), minimumWidth); + defaultOptions[1] = new ButtonFactory( + UIManager.getString("OptionPane.noButtonText",l), + getMnemonic("OptionPane.noButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.noIcon"), minimumWidth); + defaultOptions[2] = new ButtonFactory( + UIManager.getString("OptionPane.cancelButtonText",l), + getMnemonic("OptionPane.cancelButtonMnemonic", l), + (Icon)DefaultLookup.get(optionPane, this, + "OptionPane.cancelIcon"), minimumWidth); + return defaultOptions; + } + protected void addButtonComponents(Container container, Object[] buttons, + int initialIndex) { + if (ArrayUtils.isNotEmpty(buttons)) { + boolean sizeButtonsToSame = getSizeButtonsToSameWidth(); + boolean createdAll = true; + int numButtons = buttons.length; + JButton[] createdButtons = null; + int maxWidth = 0; + + if (sizeButtonsToSame) { + createdButtons = new JButton[numButtons]; + } + + for(int counter = 0; counter < numButtons; counter++) { + Object button = buttons[counter]; + Component newComponent; + + if (button instanceof Component) { + createdAll = false; + newComponent = (Component)button; + container.add(newComponent); + hasCustomComponents = true; + + } else { + JButton aButton; + + if (button instanceof ButtonFactory) { + aButton = ((ButtonFactory)button).createButton(); + } + else if (button instanceof Icon) + aButton = new JButton((Icon)button); + else + aButton = new JButton(button.toString()); + + aButton.setName("OptionPane.button"); + aButton.setMultiClickThreshhold(DefaultLookup.getInt( + optionPane, this, "OptionPane.buttonClickThreshhold", + 0)); + configureButton(aButton); + + container.add(aButton); + + ActionListener buttonListener = createButtonActionListener(counter); + if (buttonListener != null) { + aButton.addActionListener(buttonListener); + } + newComponent = aButton; + } + if (sizeButtonsToSame && createdAll) { + if ((newComponent instanceof JButton)) { + createdButtons[counter] = (JButton)newComponent; + maxWidth = Math.max(maxWidth, + newComponent.getMinimumSize().width); + } + } + if (counter == initialIndex) { + initialFocusComponent = newComponent; + if (initialFocusComponent instanceof JButton) { + JButton defaultB = (JButton)initialFocusComponent; + defaultB.addHierarchyListener(new HierarchyListener() { + public void hierarchyChanged(HierarchyEvent e) { + if ((e.getChangeFlags() & + HierarchyEvent.PARENT_CHANGED) != 0) { + JButton defaultButton = (JButton) e.getComponent(); + JRootPane root = + SwingUtilities.getRootPane(defaultButton); + if (root != null) { + root.setDefaultButton(defaultButton); + } + } + } + }); + } + } + } + ((ButtonAreaLayout)container.getLayout()). + setSyncAllWidths((sizeButtonsToSame && createdAll)); + /* Set the padding, windows seems to use 8 if <= 2 components, + otherwise 4 is used. It may actually just be the size of the + buttons is always the same, not sure. */ + if (DefaultLookup.getBoolean(optionPane, this, + "OptionPane.setButtonMargin", true)) { + if (sizeButtonsToSame && createdAll) { + JButton aButton; + int padSize; + padSize = (numButtons <= 2 ? NUM_8 : NUM_4); + for(int counter = 0; counter < numButtons; counter++) { + aButton = createdButtons[counter]; + aButton.setMargin(new Insets(2, padSize, 2, padSize)); + } + } + } + } + } + private void configureButton(JButton button) { + Font buttonFont = (Font)DefaultLookup.get(optionPane, this, + "OptionPane.buttonFont"); + if (buttonFont != null) { + button.setFont(buttonFont); + } + } + private static class ButtonFactory { + private String text; + private int mnemonic; + private Icon icon; + private int minimumWidth = -1; + + ButtonFactory(String text, int mnemonic, Icon icon, int minimumWidth) { + this.text = text; + this.mnemonic = mnemonic; + this.icon = icon; + this.minimumWidth = minimumWidth; + } + + JButton createButton() { + JButton button = null; + + if (minimumWidth > 0) { + button = new ConstrainedButton(text, minimumWidth); + } else { + button = new UIButton(text); + } + if (icon != null) { + button.setIcon(icon); + } + if (mnemonic != 0) { + button.setMnemonic(mnemonic); + } + return button; + } + + private static class ConstrainedButton extends JButton { + int minimumWidth; + + ConstrainedButton(String text, int minimumWidth) { + super(text); + this.minimumWidth = minimumWidth; + } + + public Dimension getMinimumSize() { + Dimension min = super.getMinimumSize(); + min.width = Math.max(min.width, minimumWidth); + return min; + } + + public Dimension getPreferredSize() { + Dimension pref = super.getPreferredSize(); + pref.width = Math.max(pref.width, minimumWidth); + return pref; + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UIBubbleFloatPane.java b/designer_base/src/com/fr/design/gui/frpane/UIBubbleFloatPane.java new file mode 100644 index 0000000000..cbf470b3bb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UIBubbleFloatPane.java @@ -0,0 +1,318 @@ +package com.fr.design.gui.frpane; + +import java.awt.*; +import java.awt.event.AWTEventListener; +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import com.fr.base.FRContext; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.dialog.UIDialog; +import com.fr.stable.Constants; +import com.sun.awt.AWTUtilities; + +/** + * @author Jerry + * 非模态悬浮对话框,气泡形状 + */ +public abstract class UIBubbleFloatPane extends BasicBeanPane { + private static final long serialVersionUID = -6386018511442190959L; + private static int OFF_LEFT = 10; + private static final int ARROR_PARALLEL = 30; + private static final int ARROR_VERTICAL = 20; + private static final int TITLE_HEIGHT = 60; + private static final double TIME_DEFAULT = 0.5; + private static final double TIME_GAP = 0.1; + + private BasicBeanPane contentPane; + private Rectangle bounds; + private int arrowPosition; + private double time = 0.5; + + private UIDialog showDialog; + + /** + * @param arrowPosition 箭头的位置,上下左右,暂时只处理了左边,后面用到了再说 TODO + * @param arrowPoint 箭头的坐标点 + * @param contentPane 对话框中的Panel + */ + public UIBubbleFloatPane(int arrowPosition, Point arrowPoint, BasicBeanPane contentPane) { + this(arrowPosition, arrowPoint, contentPane, contentPane.getPreferredSize().width, contentPane.getPreferredSize().height); + } + + /** + * 这个方法主要用于那些宽度和高度有变化的面板,因为显然外面的气泡要固定大小,不然忽大忽小,体验太差了 + * + * @param arrowPosition 箭头的位置,上下左右,暂时只处理了左边,后面用到了再说 TODO + * @param arrowPoint 箭头的坐标点 + * @param contentPane 对话框中的Panel + * @param width 对话框中的Panel的宽度,写死了 + * @param height 对话框中的Panel的高度,写死了 + */ + public UIBubbleFloatPane(int arrowPosition, Point arrowPoint, BasicBeanPane contentPane, int width, int height) { + this.contentPane = contentPane; + this.arrowPosition = arrowPosition; + this.time = initBoundsTime(arrowPosition, arrowPoint, width, height); + if (arrowPosition == Constants.LEFT) { + this.bounds = new Rectangle(arrowPoint.x - width, (int) (arrowPoint.y - height * time), width, height); + } else if (arrowPosition == Constants.TOP) { + this.bounds = new Rectangle((int) (arrowPoint.x - width * time), arrowPoint.y , width, height); + } else if (arrowPosition == Constants.RIGHT) { + this.bounds = new Rectangle(arrowPoint.x - OFF_LEFT * 2 - width, (int) (arrowPoint.y - height * time), width, height); + } + + initComponents(); + } + + /** + * show对话框 + * @param fatherPane 上一层界面 parentPane + * @param ob 传入的内容,在show之前populate + */ + public void show(JComponent fatherPane, T ob) { + populateBean(ob); + UIDialog dialog = showUnsizedWindow(SwingUtilities.getWindowAncestor(fatherPane)); + showDialog = dialog; + Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + dialog.setVisible(true); + } + + /** + * 数据展现 + */ + public void populateBean(T ob) { + contentPane.populateBean(ob); + } + + /** + * 停止编辑, 更新至最新的面板到属性保存 + */ + public T updateBean() { + updateContentPane(); + return contentPane.updateBean(); + } + + /** + * 需要实现更新内容,将updateBean传值给对象即可,在窗口消失的时候会被调用 + */ + protected abstract void updateContentPane(); + + /** + * 以对话框的形式弹出 + * + * @param window 窗口 + * @return 对话框 + */ + public UIDialog showUnsizedWindow(Window window) { + CustomShapedDialog dg = null; + if (window instanceof Frame) { + dg = new CustomShapedDialog((Frame) window); + } else { + dg = new CustomShapedDialog((Dialog) window); + } + if (arrowPosition == Constants.LEFT || arrowPosition == Constants.RIGHT) { + dg.setSize(bounds.width + ARROR_PARALLEL, bounds.height + ARROR_VERTICAL); + } else { + dg.setSize(bounds.width + ARROR_VERTICAL, bounds.height + ARROR_PARALLEL); + } + + dg.setLocation(bounds.x, bounds.y); + dg.setBackground(Color.blue); + dg.setResizable(false); + return dg; + } + + @Override + protected String title4PopupWindow() { + return null; + } + + private double initBoundsTime(int arrowPosition, Point arrowPoint, int width, int height) { + int x = arrowPoint.x; + int y = arrowPoint.y; + int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width; + int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height - TITLE_HEIGHT; + double time = TIME_DEFAULT; + + if (arrowPosition == Constants.LEFT || arrowPosition == Constants.RIGHT) { + while (y + time * height > screenHeight && time > 0) { + time -= TIME_GAP; + } + + while (y - (1 - time) * height < 0 && time < 1) { + time += TIME_GAP; + } + } else if (arrowPosition == Constants.TOP) { + while (x + time * width > screenWidth && time > 0) { + time -= TIME_GAP; + } + + while (x - (1 - time) * width < 0 && time < 1) { + time += TIME_GAP; + } + } + return 1 - time; + } + + private AWTEventListener awt = new AWTEventListener() { + public void eventDispatched(AWTEvent event) { + doSomeInAll(event); + } + }; + + private void doSomeInAll(AWTEvent event) { + if (event instanceof MouseEvent) { + MouseEvent mv = (MouseEvent) event; + if (mv.getClickCount() > 0) { + Point point = new Point((int) (mv.getLocationOnScreen().getX()) - 2 * OFF_LEFT, (int) mv.getLocationOnScreen().getY()); + // 判断鼠标点击是否在边界内 + if (!containsPoint(point) && showDialog != null) { + updateContentPane(); + showDialog.setVisible(false); + Toolkit.getDefaultToolkit().removeAWTEventListener(awt); + } + } + } + } + + private boolean containsPoint(Point point) { + if(arrowPosition == Constants.TOP){ + //箭头和按钮也算在pane内 + Rectangle judgedBounds = new Rectangle(bounds.x, bounds.y - OFF_LEFT * 2, bounds.width, bounds.height + OFF_LEFT * 2 + OFF_LEFT); + return judgedBounds.contains(point); + } + return bounds.contains(point); + } + + private void initComponents() { + if(arrowPosition == Constants.LEFT || arrowPosition == Constants.RIGHT) { + this.setBounds(20, 10, bounds.width, bounds.height); + } else { + this.setBounds(10, 10, bounds.width, bounds.height); + } + + this.setLayout(new BorderLayout()); + this.add(contentPane, BorderLayout.CENTER); + } + + private class CustomShapedDialog extends UIDialog { + + private static final int GAP_SMALL = 10; + private static final int GAP = 20; + private static final int GAP_BIG = 30; + + public CustomShapedDialog(Frame parent) { + super(parent); + this.initComponents(); + } + + public CustomShapedDialog(Dialog parent) { + super(parent); + this.initComponents(); + } + + + private Shape getCustomShap() { + Polygon polygon = new Polygon(); + if (arrowPosition == Constants.LEFT) { + polygon.addPoint(GAP_SMALL, 0); + polygon.addPoint(bounds.width + GAP_BIG, 0); + polygon.addPoint(bounds.width + GAP_BIG, bounds.height + GAP); + polygon.addPoint(GAP_SMALL, bounds.height + GAP); + polygon.addPoint(GAP_SMALL, (int) ((bounds.height + GAP) * time) - GAP_SMALL); + polygon.addPoint(0, (int) ((bounds.height + GAP) * time - GAP)); + polygon.addPoint(GAP_SMALL, (int) ((bounds.height + GAP) * time - GAP_BIG)); + polygon.addPoint(GAP_SMALL, 0); + } else if (arrowPosition == Constants.TOP) { + polygon.addPoint(0, GAP_SMALL); + polygon.addPoint((int) (bounds.width * time + GAP_SMALL), GAP_SMALL); + polygon.addPoint((int) (bounds.width * time + GAP), 0); + polygon.addPoint((int) (bounds.getWidth() * time + GAP_BIG), GAP_SMALL); + polygon.addPoint(bounds.width + GAP, GAP_SMALL); + polygon.addPoint(bounds.width + GAP, bounds.height + GAP_BIG); + polygon.addPoint(0, bounds.height + GAP_BIG); + polygon.addPoint(0, GAP_SMALL); + } else if (arrowPosition == Constants.RIGHT) { + polygon.addPoint(0, 0); + polygon.addPoint(bounds.width + GAP, 0); + polygon.addPoint(bounds.width + GAP, (int) ((bounds.height + GAP) * time) - GAP_BIG); + polygon.addPoint(bounds.width + GAP_BIG, (int) ((bounds.height + GAP) * time) - GAP); + polygon.addPoint(bounds.width + GAP, (int) ((bounds.height + GAP) * time) - GAP_SMALL); + polygon.addPoint(bounds.width + GAP, bounds.height + GAP); + polygon.addPoint(0, bounds.height + GAP); + polygon.addPoint(0, 0); + } + + return polygon; + } + + private Shape getShape4Board() { + Polygon polygon = new Polygon(); + if (arrowPosition == Constants.LEFT) { + polygon.addPoint(GAP_SMALL, 1); + polygon.addPoint(bounds.width + GAP_BIG - 1, 1); + polygon.addPoint(bounds.width + GAP_BIG - 1, bounds.height + GAP - 1); + polygon.addPoint(GAP_SMALL + 1, bounds.height + GAP - 1); + polygon.addPoint(GAP_SMALL + 1, (int) ((bounds.height + GAP) * time) - GAP_SMALL); + polygon.addPoint(1, (int) ((bounds.height + GAP) * time - GAP)); + polygon.addPoint(GAP_SMALL + 1, (int) ((bounds.height + GAP) * time - GAP_BIG)); + polygon.addPoint(GAP_SMALL + 1, 1); + } else if (arrowPosition == Constants.TOP) { + polygon.addPoint(1, GAP_SMALL + 1); + polygon.addPoint((int) (bounds.width * time + GAP_SMALL), GAP_SMALL + 1); + polygon.addPoint((int) (bounds.width * time + GAP), 1); + polygon.addPoint((int) (bounds.getWidth() * time + GAP_BIG), GAP_SMALL + 1); + polygon.addPoint(bounds.width + GAP - 1, GAP_SMALL + 1); + polygon.addPoint(bounds.width + GAP - 1, bounds.height + GAP_BIG - 1); + polygon.addPoint(1, bounds.height + GAP_BIG - 1); + polygon.addPoint(1, GAP_SMALL + 1); + } else if(arrowPosition == Constants.RIGHT) { + polygon.addPoint(1, 1); + polygon.addPoint(bounds.width + GAP - 1, 1); + polygon.addPoint(bounds.width + GAP - 1, (int) ((bounds.height + GAP) * time) - GAP_BIG); + polygon.addPoint(bounds.width + GAP_BIG - 1, (int) ((bounds.height + GAP) * time) - GAP); + polygon.addPoint(bounds.width + GAP - 1, (int) ((bounds.height + GAP) * time) - GAP_SMALL); + polygon.addPoint(bounds.width + GAP - 1, bounds.height + GAP - 1); + polygon.addPoint(1, bounds.height + GAP - 1); + polygon.addPoint(1, 0); + } + return polygon; + } + + /** + * 画出界面的样式, 边框等. + */ + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + Stroke oldStroke = g2d.getStroke(); + g2d.setStroke(new BasicStroke(2, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND)); + g2d.setColor(new Color(51, 51, 51)); + g2d.drawPolygon((Polygon) getShape4Board()); + g2d.setStroke(oldStroke); + } + + protected void initComponents() { + setUndecorated(true); + try { + AWTUtilities.setWindowShape(CustomShapedDialog.this, this.getCustomShap()); + } catch (UnsupportedOperationException e) { + FRContext.getLogger().info("Not support"); + } + final JPanel contentPane = (JPanel) this.getContentPane(); + this.setLayout(null); + contentPane.add(UIBubbleFloatPane.this); + setVisible(true); + } + + /** + * 检查 + */ + public void checkValid() throws Exception { + + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UIComboBoxPane.java b/designer_base/src/com/fr/design/gui/frpane/UIComboBoxPane.java new file mode 100644 index 0000000000..9d31cd4f35 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UIComboBoxPane.java @@ -0,0 +1,145 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.gui.icombobox.UIComboBox; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.List; + +/** + * + * @author zhou + * @since 2012-5-31下午12:25:21 + */ +public abstract class UIComboBoxPane extends BasicBeanPane { + + private static final long serialVersionUID = 1L; + + protected abstract List> initPaneList(); + + protected UIComboBox jcb; + protected JPanel cardPane; + + protected List> cards; + private String[] cardNames; + + public UIComboBoxPane() { + cards = initPaneList(); + initComponents(); + } + + protected void initComponents() { + cardNames = new String[cards.size()]; + + jcb = createComboBox(); + cardPane = new JPanel(new CardLayout()) { + @Override + public Dimension getPreferredSize() { + return cards.get(jcb.getSelectedIndex()).getPreferredSize(); + } + }; + for (int i = 0; i < this.cards.size(); i++) { + String name = this.cards.get(i).title4PopupWindow();// Name从各自的pane里面获取 + cardNames[i] = name; + cardPane.add(this.cards.get(i), cardNames[i]); + addComboBoxItem(cards, i); + } + + jcb.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + comboBoxItemStateChanged(); + CardLayout cl = (CardLayout)cardPane.getLayout(); + cl.show(cardPane, cardNames[jcb.getSelectedIndex()]); + } + }); + + initLayout(); + + jcb.setSelectedIndex(0); + } + + protected UIComboBox createComboBox() { + return new UIComboBox(); + } + + protected void addComboBoxItem(List> cards, int index) { + jcb.addItem(cards.get(index).title4PopupWindow()); + } + + /** + * 设置只支持其中的某个选项, + */ + public void justSupportOneSelect(boolean surpport) { + if(!surpport) { + jcb.setSelectedIndex(0); + } + jcb.setEnabled(surpport); + } + + /** + * august 如果需要的布局有变化,覆盖之 + */ + protected void initLayout() { + this.setLayout(new BorderLayout(0,6)); + JPanel northPane = new JPanel(new BorderLayout()); + northPane.add(jcb, BorderLayout.CENTER); + this.add(northPane, BorderLayout.NORTH); + this.add(cardPane, BorderLayout.CENTER); + + } + + protected void comboBoxItemStateChanged() { + + } + + public void reset() { + jcb.setSelectedIndex(0); + for (FurtherBasicBeanPane pane : cards) { + pane.reset(); + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public void populateBean(T ob) { + for (int i = 0; i < this.cards.size(); i++) { + FurtherBasicBeanPane pane = cards.get(i); + if (pane.accept(ob)) { + pane.populateBean(ob); + jcb.setSelectedIndex(i); + return; + } + } + } + + @Override + public T updateBean() { + return cards.get(jcb.getSelectedIndex()).updateBean(); + } + + public int getSelectedIndex() { + return jcb.getSelectedIndex(); + } + + public void setSelectedIndex(int index) { + jcb.setSelectedIndex(index); + } + + public void addTabChangeListener(ItemListener l){ + jcb.addItemListener(l); + } + + public UIComboBox getUIComboBox(){ + return this.jcb; + } + + public List> getCards(){ + return this.cards; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UICorrelationComboBoxPane.java b/designer_base/src/com/fr/design/gui/frpane/UICorrelationComboBoxPane.java new file mode 100644 index 0000000000..c5837727ed --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UICorrelationComboBoxPane.java @@ -0,0 +1,439 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.imenu.UIMenuItem; +import com.fr.design.gui.imenutable.UIMenuNameableCreator; +import com.fr.design.gui.imenutable.UIMenuTable; +import com.fr.design.hyperlink.ReportletHyperlinkPane; +import com.fr.design.hyperlink.WebHyperlinkPane; +import com.fr.design.javascript.EmailPane; +import com.fr.design.mainframe.BaseJForm; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.DialogActionListener; +import com.fr.design.dialog.UIDialog; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.js.AbstractJavaScript; +import com.fr.js.EmailJavaScript; +import com.fr.js.ReportletHyperlink; +import com.fr.js.WebHyperlink; +import com.fr.stable.ArrayUtils; +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UICorrelationComboBoxPane extends JPanel implements UIObserver { + private JPopupMenu popMenu; + private UIMenuTable tablePane; + private UIButton addButton; + private List values; + private UIObserverListener uiObserverListener; + + public UICorrelationComboBoxPane() { + this(null); + iniListener(); + } + + public UICorrelationComboBoxPane(List values) { + initComponents(); + initLayout(); + refreshMenuAndAddMenuAction(values); + iniListener(); + } + + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + + /** + * 刷新下拉列表和按钮 + * @param values 下拉列表里的值 + */ + public void refreshMenuAndAddMenuAction(List values) { + if (values == null || values.isEmpty()) { + return; + } + this.values = values; + popMenu.removeAll(); + // 如果只有一个弹出项,那么就不弹出,直接让add按钮替代 + if (values.size() > 1) { + for (UIMenuNameableCreator value : values) { + final String itemName = value.getName(); + if(!whetherAdd(itemName)){ + continue; + } + UIMenuItem item = new UIMenuItem(itemName); + final UIMenuNameableCreator creator = value; + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + UIMenuNameableCreator ui = creator.clone(); + ui.setName(createUnrepeatedName(itemName)); + tablePane.addLine(ui); + + final Object obj = ui.getObj(); + final BasicBeanPane pane = ui.getPane(); + UIDialog dialog = pane.showUnsizedWindow(SwingUtilities.getWindowAncestor(new JPanel()), new DialogActionAdapter() { + public void doOk() { + pane.updateBean(obj); + fireTargetChanged(); + } + + public void doCancel() { + int row = tablePane.getRowCount(); + tablePane.removeLine(row - 1); + fireTargetChanged(); + } + }); + dialog.setSize(500, 500); + GUICoreUtils.centerWindow(dialog); + dialog.setVisible(true); + } + }); + popMenu.add(item); + } + } + initAddButtonListener(); + } + + private boolean whetherAdd(String itemName){ + JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + //先屏蔽掉这个,之后还有别的 + String[] names = {Inter.getLocText("FR-Hyperlink_Chart_Float"), Inter.getLocText("FR-Hyperlink_Chart_Cell")}; + for (String name : names){ + if(!jTemplate.isJWorkBook() && ComparatorUtils.equals(itemName,name)){ + if(jTemplate.getEditingReportIndex() == BaseJForm.ELEMENTCASE_TAB && ComparatorUtils.equals(itemName, names[0])){ + //表单报表块中图表悬浮元素超链,只屏蔽联动悬浮元素 + return false; + } else if(jTemplate.getEditingReportIndex() == BaseJForm.FORM_TAB) { + //表单图表超链屏蔽掉联动悬浮元素和联动单元格 + return false; + } + } + } + String formName = Inter.getLocText("Hyperlink-Form_link"); + return !(jTemplate.isJWorkBook() && ComparatorUtils.equals(itemName, formName)); + } + + private String createUnrepeatedName(String prefix) { + List all = tablePane.updateBean(); + // richer:生成的名字从1开始. kunsnat: 添加属性从0开始. + int count = all.size() + 1; + while (true) { + String name_test = prefix + count; + boolean repeated = false; + for (int i = 0, len = all.size(); i < len; i++) { + UIMenuNameableCreator nameable = all.get(i); + if (ComparatorUtils.equals(nameable.getName(), name_test)) { + repeated = true; + break; + } + } + + if (!repeated) { + return name_test; + } + count++; + } + } + + private ActionListener addAction = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (values.size() == 1) { + UIMenuNameableCreator current = values.get(0); + + UIMenuNameableCreator ui = current.clone(); + ui.setName(createUnrepeatedName(current.getName())); + tablePane.addLine(ui); + fireTargetChanged(); + + final Object obj = ui.getObj(); + final BasicBeanPane pane = ui.getPane(); + + pane.populateBean(obj); + + UIDialog dialog = pane.showUnsizedWindow(SwingUtilities.getWindowAncestor(new JPanel()), new DialogActionListener() { + @Override + public void doOk() { + pane.updateBean(obj); + fireTargetChanged(); + } + + @Override + public void doCancel() { + int row = tablePane.getRowCount(); + tablePane.removeLine(row - 1); + fireTargetChanged(); + } + }); + dialog.setSize(500, 500); + dialog.setVisible(true); + } else { + popMenu.show(UICorrelationComboBoxPane.this, addButton.getX() + 1, addButton.getY() + addButton.getHeight()); + } + } + }; + + protected ActionListener addAction(final List values) { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (values.size() == 1) { + UIMenuNameableCreator current = values.get(0); + current.setName(createUnrepeatedName(current.getName())); + tablePane.addLine(current); + fireTargetChanged(); + } else { + popMenu.show(UICorrelationComboBoxPane.this, addButton.getX() + 1, addButton.getY() + addButton.getHeight()); + } + } + }; + } + + protected void initComponents() { + tablePane = new UIMenuTable(); + popMenu = new JPopupMenu() { + @Override + public Dimension getPreferredSize() { + Dimension dimension = new Dimension(); + dimension.height = super.getPreferredSize().height; + dimension.width = addButton.getWidth() - 2; + return dimension; + } + }; + initAddButton(); + } + + protected void initAddButton() { + addButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/buttonicon/add.png")); + addButton.setBorderType(UIButton.OTHER_BORDER); + addButton.setOtherBorder(UIConstants.BS, UIConstants.LINE_COLOR); + } + + private void initAddButtonListener() { + ActionListener[] listeners = addButton.getListeners(ActionListener.class); + if (!ArrayUtils.contains(listeners, addAction)) { + addButton.addActionListener(addAction); + } + } + + protected void initLayout() { + this.setLayout(new Layout()); + this.add(addButton); + this.add(tablePane); + } + + public class Layout implements LayoutManager { + + /** + * 增加布局 + * @param name 名字 + * @param comp 组件 + */ + public void addLayoutComponent(String name, Component comp) { + + } + + /** + * 删除组件 + * @param comp 组件 + */ + public void removeLayoutComponent(Component comp) { + + } + + /** + * 获得组件的大小 + * @param parent 上层容器 + * @return 组件的大小 + */ + public Dimension preferredLayoutSize(Container parent) { + int h = addButton.getPreferredSize().height + tablePane.getPreferredSize().height; + return new Dimension(parent.getWidth(), h + 2); + } + + /** + * 最小的布局大小 + * @param parent 上层容器 + * @return 最小的大小 + */ + public Dimension minimumLayoutSize(Container parent) { + return preferredLayoutSize(parent); + } + + /** + * 布局容器 + * @param parent 上层容器 + */ + public void layoutContainer(Container parent) { + int width = parent.getWidth(); + int y = 0; + tablePane.setBounds(0, y, width, tablePane.getPreferredSize().height); + y += tablePane.getPreferredSize().height + 2; + addButton.setBounds(0, y, width, addButton.getPreferredSize().height); + } + } + + /** + * 增加监听事件 + * @param l 监听的对象 + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + this.tablePane.addChangeListener(l); + } + + /** + * 删除监听事件 + * @param l 需要删除的事件 + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + // august: Process the listeners last to first + protected void fireChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + + this.tablePane.fireTargetChanged(); + } + + /** + * 响应事件 + */ + public void fireTargetChanged() { + this.validate(); + this.repaint(); + this.revalidate(); + fireChanged(); + } + + /** + * 预定义的宽度和高度 + */ + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = super.getPreferredSize().width; + dim.height = addButton.getPreferredSize().height + tablePane.getPreferredSize().height + 2; + return dim; + } + + /** + * 更新并且重载 当前列表的值 + * @param list 更新的列表 + */ + public void populateBean(List list) { + tablePane.populateBean(list); + } + + /** + * 返回 当前列表保存的值, 嵌套的一层, 主要对应creator中的obj + */ + public List updateBean() { + return tablePane.updateBean(); + } + + /** + * 重置每个条目的名字 + */ + public void resetItemName(){ + for(int i = 0; i < tablePane.getRowCount(); i++){ + UIMenuNameableCreator line = tablePane.getLine(i); + Object obj = line.getObj(); + if(obj instanceof AbstractJavaScript){ + AbstractJavaScript script = (AbstractJavaScript)obj; + String itemName = script.getItemName(); + if(!StringUtils.isBlank(itemName)){ + line.setName(itemName); + } + } + } + } + + /** + * 测试例子界面 + * @param args 参数向量 + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + List data = new ArrayList(); + UIMenuNameableCreator reportlet = new UIMenuNameableCreator(Inter.getLocText("FR-Hyperlink_Reportlet"), + new ReportletHyperlink(), true ? ReportletHyperlinkPane.CHART.class : ReportletHyperlinkPane.class); + + UIMenuNameableCreator email = new UIMenuNameableCreator(Inter.getLocText("FR-Designer_Email"), + new EmailJavaScript(), EmailPane.class); + + UIMenuNameableCreator web = new UIMenuNameableCreator(Inter.getLocText("Hyperlink-Web_link"), + new WebHyperlink(), true ? WebHyperlinkPane.CHART.class : WebHyperlinkPane.class); + data.add(reportlet); + data.add(email); + data.add(web); + UICorrelationComboBoxPane pane = new UICorrelationComboBoxPane(data); + content.add(pane, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } + + /** + * 注册观察者监听事件 + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + + } + + /** + * 是否需要响应事件 + * @return 需要相应 + */ + public boolean shouldResponseChangeListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UICorrelationPane.java b/designer_base/src/com/fr/design/gui/frpane/UICorrelationPane.java new file mode 100644 index 0000000000..606ebb4641 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UICorrelationPane.java @@ -0,0 +1,409 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.table.TableCellEditor; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itable.UIDefaultTableCellEditor; +import com.fr.design.gui.itable.UITable; +import com.fr.design.gui.itable.UITableEditor; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.general.Inter; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * @author jerry + */ +public class UICorrelationPane extends JPanel implements UIObserver { + + private static int size = 20; + protected UIButton addButton; + protected UITable tablePane; + protected int columnCount; + private UIObserverListener uiObserverListener; + private HeaderPane header; + + /** + * @param 标题栏的名字,length代表列数 + */ + public UICorrelationPane(String... names) { + columnCount = names.length; + initComponents(); + header = new HeaderPane(names); + initLayout(); + iniListener(); + } + + /** + * @param column 列数 + * 没有标题栏的CorrelationPane + */ + public UICorrelationPane(int column) { + columnCount = column; + initComponents(); + initLayout(); + iniListener(); + } + + /** + * 不需要使用添加按钮, 目前只有图表: 股价图, 甘特图单元格数据界面用到. + */ + public void noAddUse() { + addButton.setEnabled(false); + addButton.setVisible(false); + } + + protected boolean isDeletable(){ + return true; + } + + /** + * 添加按钮 等 是否可用 + * @param use 是否可用 + */ + public void checkBoxUse(boolean use) { + addButton.setEnabled(use); + } + + public void populateBean(List values) { + tablePane.populateBean(values); + this.validate(); + this.repaint(); + this.revalidate(); + } + + public List updateBean() { + List list = tablePane.updateBean(); + + if (tablePane.isEditing()) { + TableCellEditor editor = tablePane.getCellEditor(); + if (editor != null) { + Object value = editor.getCellEditorValue(); + int row = tablePane.getEditingRow(); + int col = tablePane.getEditingColumn(); + if (list.size() > row) { + Object[] objs = list.get(row); + if (objs != null && objs.length > col) { + objs[col] = value; + } + } + } + } + + return list; + } + + + /** + *添加一行 + * @param line 行 + */ + public void addLine(Object[] line) { + tablePane.addLine(line); + } + + /** + * 删除某行内容 + * @param rowIndex 行号 + */ + public void removeLine(int rowIndex) { + tablePane.removeLine(rowIndex); + } + + /** + * @return 添加按钮的事件接口 + */ + protected ActionListener getAddButtonListener() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tablePane.addBlankLine(); + fireTargetChanged(); + } + }; + } + + protected void initLayout() { + this.setLayout(new Layout()); + this.add(addButton); + if (header != null) { + this.add(header); + } + this.add(tablePane); + } + + protected void initComponents() { + tablePane = initUITable(); + initAddButton(); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + /** + * 停止单元格编辑 + */ + public void stopCellEditing() { + if (tablePane.getDefaultEditor(UITable.class) != null) { + tablePane.getDefaultEditor(UITable.class).stopCellEditing(); + } + } + + /** + * 停止面板编辑 + * @param e 事件 + */ + public void stopPaneEditing(ChangeEvent e) { + fireChanged(); + } + + /** + * 创建table编辑器 + * @return 编辑器 + */ + public UITableEditor createUITableEditor() { + return new UIDefaultTableCellEditor(new UITextField()); + } + + protected UITable initUITable() { + return new UITable(columnCount) { + + public UITableEditor createTableEditor() { + return UICorrelationPane.this.createUITableEditor(); + } + + public void tableCellEditingStopped(ChangeEvent e) { + UICorrelationPane.this.stopPaneEditing(e); + } + + }; + } + + protected void initAddButton() { + addButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/buttonicon/add.png")) { + public boolean shouldResponseChangeListener() { + return false; + } + }; + addButton.setBorderType(UIButton.OTHER_BORDER); + addButton.setOtherBorder(UIConstants.BS, UIConstants.LINE_COLOR); + addButton.addActionListener(getAddButtonListener()); + } + + /** + * 通知变化 + */ + public void fireTargetChanged() { + this.validate(); + this.repaint(); + this.revalidate(); + fireChanged(); + } + + /** + * 给组件登记一个观察者监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } + + public class Layout implements LayoutManager { + + /** + * 增加组件 + * @param name 组件名 + * @param comp 组件 + */ + public void addLayoutComponent(String name, Component comp) { + + } + + /** + *移除组件 + * @param comp 组件 + */ + public void removeLayoutComponent(Component comp) { + + } + + /** + *最佳大小 + * @param parent 父容器 + * @return 大小 + */ + public Dimension preferredLayoutSize(Container parent) { + int h = addButton.getPreferredSize().height + tablePane.getPreferredSize().height; + if (header != null) { + h = header.getPreferredSize().height; + } + return new Dimension(parent.getWidth(), h + 2); + } + + /** + * 最小布局大小 + * @param parent 父容器 + * @return 大小 + */ + public Dimension minimumLayoutSize(Container parent) { + return preferredLayoutSize(parent); + } + + /** + * 布局容器 + * @param parent 父容器 + */ + public void layoutContainer(Container parent) { + int width = parent.getWidth(); + int y = 0; + if (header != null) { + header.setBounds(0, y, width - (isDeletable() ?size:0), header.getPreferredSize().height); + y = y + header.getPreferredSize().height; + } + tablePane.setBounds(0, y, width+(isDeletable() ?0:size), tablePane.getPreferredSize().height); + y += tablePane.getPreferredSize().height + 2; + addButton.setBounds(0, y, width, addButton.getPreferredSize().height); + } + } + + private class HeaderPane extends JPanel { + + public HeaderPane(String[] names) { + UILabel[] labels = new UILabel[names.length]; + this.setLayout(new GridLayout(0, names.length)); + for (int i = 0; i < names.length; i++) { + labels[i] = new UILabel(names[i], UILabel.CENTER) { + @Override + public void paint(Graphics g) { + super.paint(g); + int width = getWidth(); + int height = getHeight(); + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(UIConstants.LINE_COLOR); + g2d.drawLine(4, height - 1, width - 4, height - 1); + } + + }; + this.add(labels[i]); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width - (isDeletable() ?size:0), size); + } + + } + + /** + * 增加监听 + * @param l 监听 + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + * 移除监听 + * @param l 监听 + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + // august: Process the listeners last to first + protected void fireChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = super.getPreferredSize().width; + dim.height = addButton.getPreferredSize().height + tablePane.getPreferredSize().height + 2; + if (header != null) { + dim.height += header.getPreferredSize().height; + } + return dim; + } + + public UITable getTable() { + return tablePane; + } + + + /** + * 主函数 + * @param args 参数 + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + final String[] columnNames = {Inter.getLocText("Actual_Value"), Inter.getLocText("Display_Value")}; + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + UICorrelationPane pane = new UICorrelationPane(columnNames); + content.add(pane, BorderLayout.CENTER); + List values = new ArrayList(); + values.add(new String[]{"askdjf1", "skdjfasjdf1"}); + values.add(new String[]{"askdjf2", "skdjfasjdf2"}); + values.add(new String[]{"askdjf3", "skdjfasjdf3"}); + values.add(new String[]{"askdjf4", "skdjfasjdf4"}); + values.add(new String[]{"askdjf5", "skdjfasjdf5"}); + values.add(new String[]{"askdjf6", "skdjfasjdf6"}); + values.add(new String[]{"askdjf7", "skdjfasjdf7"}); + values.add(new String[]{"askdjf8", "skdjfasjdf8"}); + pane.populateBean(values); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UIExtensionPane.java b/designer_base/src/com/fr/design/gui/frpane/UIExtensionPane.java new file mode 100644 index 0000000000..cc3e8886c0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UIExtensionPane.java @@ -0,0 +1 @@ +package com.fr.design.gui.frpane; import com.fr.design.gui.ilable.UILabel; import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 12-12-29 * Time: 上午9:26 */ public class UIExtensionPane extends JPanel implements MouseListener { private boolean expand;// 是否展开 private String title;// 标题 private Component contentPane;// 主面板 private ImageIcon up_icon, down_icon;// 图标 private JPanel currentLabel; private UILabel iconLabel; private UILabel titleLabel; // ----各种构造函数--------------------------------------- public UIExtensionPane() { this("", null, true); } public UIExtensionPane(Component c) { this("", c, true); } public UIExtensionPane(String title, Component c) { this(title, c, true); } public UIExtensionPane(String title, Component c, boolean expand) { this.title = title; this.expand = expand; this.contentPane = GUICoreUtils.createBorderLayoutPane(c, BorderLayout.CENTER, new UILabel(" "), BorderLayout.WEST); init(); } // ----各种方法--------------------------------------- /** * 返回面板伸缩的状态 * @return 返回面板伸缩的状态 */ public boolean isExpand() { return expand; } /** * 设置面板的伸缩 * * @param true 展开 * @param false 收缩 */ public void setExpand(boolean expand) { this.expand = expand; if (this.expand) { this.iconLabel.setIcon(down_icon); if (null != this.contentPane) { contentPane.setVisible(true); } } else { this.iconLabel.setIcon(up_icon); if (null != this.contentPane) { contentPane.setVisible(false); } } this.updateUI(); this.updateUI(); } /** * 返回面板标题 */ public String getTitle() { return title; } /** * 设置面板标题 * * @param panel 面板标题 */ public void setTitle(String title) { this.title = title; this.titleLabel.setText(title); this.updateUI(); } /** * 创建标题指示图标 */ private void createImages() { int w = this.getPreferredSize().width, h = this.getPreferredSize().height; BufferedImage open = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB), close = new BufferedImage( w, h, BufferedImage.TYPE_INT_RGB); // 展开的图标 Graphics2D g2 = open.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setPaint(this.getBackground()); g2.fillRect(0, 0, w, h); int[] x = {w - h, w, w - h / 2}; int[] y = {0, 0, h}; Polygon p = new Polygon(x, y, 3); g2.setPaint(Color.GRAY); g2.draw(p); g2.drawLine(0, h / 2, w - h, h / 2); g2.dispose(); down_icon = new ImageIcon(open); // 收缩的的图标 g2 = close.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setPaint(getBackground()); g2.fillRect(0, 0, w, h); x = new int[]{w - h, w - h, w}; y = new int[]{0, h, h / 2}; p = new Polygon(x, y, 3); g2.setPaint(Color.GRAY); g2.draw(p); g2.drawLine(0, h / 2, w - h, h / 2); g2.dispose(); up_icon = new ImageIcon(close); } /** * 初始化工作 */ private void init() { this.createImages();// 获得图标 this.setLayout(new BorderLayout()); if (this.expand) { this.currentLabel = GUICoreUtils.createBorderLayoutPane( iconLabel = new UILabel(down_icon), BorderLayout.EAST, new LineLabel(), BorderLayout.CENTER, titleLabel = new UILabel(title), BorderLayout.WEST); if (this.contentPane != null) { this.add(this.contentPane, BorderLayout.CENTER); } } else { this.currentLabel = GUICoreUtils.createBorderLayoutPane( iconLabel = new UILabel(up_icon), BorderLayout.EAST, new LineLabel(), BorderLayout.CENTER, titleLabel = new UILabel(title), BorderLayout.WEST); if (this.currentLabel != null) { this.add(currentLabel, BorderLayout.CENTER); } if (this.contentPane != null) { this.add(contentPane, BorderLayout.CENTER); contentPane.setVisible(false); } } this.add(currentLabel, BorderLayout.NORTH); this.currentLabel.addMouseListener(this); } /** * 鼠标点击 * @param e 事件 */ public void mouseClicked(MouseEvent e) { if (e.getSource() == currentLabel && this.isEnabled()) { expand = !expand; if (this.expand) { this.iconLabel.setIcon(down_icon); if (null != this.contentPane) { contentPane.setVisible(true); } } else { this.iconLabel.setIcon(up_icon); if (null != this.contentPane) { contentPane.setVisible(false); } } this.updateUI(); } } /** * 鼠标进入 * @param e 事件 */ public void mouseEntered(MouseEvent e) { } /** * 鼠标移出 * @param e 事件 */ public void mouseExited(MouseEvent e) { } /** * 鼠标按压 * @param e 事件 */ public void mousePressed(MouseEvent e) { } /** * 鼠标释放 * @param e 事件 */ public void mouseReleased(MouseEvent e) { } private class LineLabel extends UILabel { public LineLabel() { super(); } public void paintComponent(Graphics g) { super.paintComponent(g); Rectangle bounds = getBounds(); if (bounds != null) { Graphics2D g2d = (Graphics2D) g; g2d.setPaint(Color.GRAY); g2d.drawLine(0, bounds.height / 2, bounds.width, bounds.height / 2); } } } /** * 测试的入口方法 * @param args 参数 */ public static void main(String[] args) { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container c = f.getContentPane(); c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS)); c.add(new UIExtensionPane("test1", new JButton("test1"), false)); c.add(new UIExtensionPane("test2", new JButton("test2"), false)); f.setSize(360, 500); f.setLocation(200, 100); f.setVisible(true); } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UINumberDragPane.java b/designer_base/src/com/fr/design/gui/frpane/UINumberDragPane.java new file mode 100644 index 0000000000..a4c394ceb7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UINumberDragPane.java @@ -0,0 +1,136 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.gui.style.NumberDragBar; +import com.fr.general.Inter; + +public class UINumberDragPane extends BasicBeanPane implements GlobalNameObserver { + private static final long serialVersionUID = -8681716725163358249L; + private NumberDragBar dragBar; + private UISpinner spinner; + private boolean isEditing = false; + private String numberDargPaneName = ""; + private GlobalNameListener globalNameListener = null; + + /** + * 带说明 + * @param value 带说明 + */ + public void userEvent(double value) { + + } + + public UINumberDragPane(double minValue, double maxValue) { + dragBar = new NumberDragBar((int) minValue, (int) maxValue); + spinner = new UISpinner(minValue, maxValue, 1, minValue); + spinner.setGlobalName(Inter.getLocText("StyleAlignment-Text_Rotation")); + this.setLayout(new BorderLayout(4, 0)); + this.add(spinner, BorderLayout.EAST); + this.add(dragBar, BorderLayout.CENTER); + dragBar.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(numberDargPaneName); + } + spinner.setValue(dragBar.getValue()); + if (isEditing) { + userEvent(updateBean()); + } + } + }); + spinner.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(numberDargPaneName); + } + dragBar.setValue((int) spinner.getValue()); + if (isEditing) { + userEvent(updateBean()); + } + } + }); + } + + /** + * 添加事件 + * @param l 事件 + */ + public void addChangeListener(ChangeListener l) { + spinner.addChangeListener(l); + + } + + /** + * 移除事件 + * @param l 事件 + */ + + public void removeChangeListener(ChangeListener l) { + spinner.removeChangeListener(l); + } + + /** + * @param name + */ + public void setGlobalName(String name) { + numberDargPaneName = name; + } + + @Override + public void populateBean(Double ob) { + isEditing = false; + dragBar.setValue(ob.intValue()); + spinner.setValue(ob); + isEditing = true; + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = super.getPreferredSize().width; + dim.height = super.getPreferredSize().height + 2; + return dim; + } + + public void setEnabled(boolean enabled) { + dragBar.setEnabled(enabled); + spinner.setEnabled(enabled); + } + + @Override + public Double updateBean() { + return spinner.getValue(); + } + + @Override + protected String title4PopupWindow() { + return null; + } + + /** + * 注册 + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 是否应该响应 + * @return 是否应该响应 + */ + public boolean shouldResponseNameListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UINumberSlidePane.java b/designer_base/src/com/fr/design/gui/frpane/UINumberSlidePane.java new file mode 100644 index 0000000000..362d534c77 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UINumberSlidePane.java @@ -0,0 +1,137 @@ +/** + * + */ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.itextfield.UINumberField; +import com.fr.design.gui.style.NumberDragBar; + +/** + * 拖拽的滑条和对应滑条值的数字 + * + * @author jim + * @date 2014-8-20 + */ +public class UINumberSlidePane extends BasicBeanPane { + + /** + * + */ + private static final long serialVersionUID = -3863821662526890552L; + private static final double MIN_DIFF_VALUE = 5.0; + private NumberDragBar dragBar; + private UINumberField manual; + private double minValue; + private double maxValue; + private double value; + + public UINumberSlidePane(double minValue, double maxValue) { + this.minValue = minValue; + this.maxValue = maxValue; + dragBar = new NumberDragBar((int)minValue, (int)maxValue); + manual = new UINumberField(3, 0); + manual.setHorizontalAlignment(manual.CENTER); + this.setLayout(new BorderLayout(4, 0)); + this.add(dragBar, BorderLayout.CENTER); + this.add(manual, BorderLayout.EAST); + dragBar.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + checkValue(dragBar.getValue()); + } + }); + manual.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + checkValue(manual.getValue()); + } + }); + } + + + /** + * 手动输入滑条值后,check下 + * @param value 值 + */ + public void checkValue(double value) { + value = Math.max(value, minValue); + value = Math.min(value, maxValue); + if (this.value == value) { + return; + } + double diff = Math.abs(value - this.value); + manual.setValue(value); + dragBar.setValue((int)value); + // 拖动的比较小,就先不调整界面显示大小,暂时设5px门槛 + if (diff < MIN_DIFF_VALUE) { + return; + } + this.value = value; + fireStateChanged(); + } + + public double getValue() { + return this.value; + } + + @Override + public void populateBean(Double ob) { + dragBar.setValue(ob.intValue()); + manual.setValue(ob); + this.value = ob; + } + + @Override + public Double updateBean() { + return manual.getValue(); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = new Dimension(); + dim.width = super.getPreferredSize().width; + dim.height = super.getPreferredSize().height + 2; + return dim; + } + + @Override + protected String title4PopupWindow() { + return null; + } + + /** + * 添加改变事件 + * @param l 变化事件 + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + * remove ChangeListener事件 + * @param l ChangeListener事件 + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + protected void fireStateChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UIRadioPane.java b/designer_base/src/com/fr/design/gui/frpane/UIRadioPane.java new file mode 100644 index 0000000000..f268a9e4c2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UIRadioPane.java @@ -0,0 +1,107 @@ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.util.List; + +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.beans.FurtherBasicBeanPane; +import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.layout.FRGUIPaneFactory; + +/** + * + * @author zhou + * @since 2012-5-30下午1:12:00 + */ +public abstract class UIRadioPane extends BasicBeanPane { + private static final long serialVersionUID = 1L; + + protected UIButtonGroup cardNamesPane; + protected JPanel cardPane; + + // 放弃下面带泛型的数组,用list,因为Java不支持泛型数组,导致初始化数组时不能用泛型、从而不能严格控制类型,那么用泛型就没有什么意义了 + // private FurtherBasicBeanPane[] cards; august + private List> cards; + + private String[] cardNames; + + protected abstract List> initPaneList(); + + public UIRadioPane() { + cards = initPaneList(); + initComponents(); + } + + protected void initComponents() { + cardNames = new String[cards.size()]; + cardPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + + for (int i = 0; i < this.cards.size(); i++) { + cardNames[i] = getCardName(i); + cardPane.add(this.cards.get(i), cardNames[i]); + } + + cardNamesPane = getCardNamePane(cardNames); + + cardNamesPane.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + showCard(); + } + }); + initLayout(); + cardNamesPane.setSelectedIndex(0);// 默认选中第一个 + } + + protected UIButtonGroup getCardNamePane(String[] cardNames) { + return new UIButtonGroup(cardNames); + } + + private void showCard() { + CardLayout cl = (CardLayout)cardPane.getLayout(); + cl.show(cardPane, cardNames[cardNamesPane.getSelectedIndex()]); + } + + /** + * august 如果需要的布局有变化,覆盖之 + */ + protected void initLayout() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel northPane = new JPanel(new BorderLayout(4, 6)); + northPane.add(cardNamesPane, BorderLayout.CENTER); + + this.add(northPane, BorderLayout.NORTH); + this.add(cardPane, BorderLayout.CENTER); + + } + + protected String getCardName(int i) { + return this.cards.get(i).title4PopupWindow(); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public void populateBean(T ob) { + for (int i = 0; i < this.cards.size(); i++) { + FurtherBasicBeanPane pane = cards.get(i); + if (pane.accept(ob)) { + pane.populateBean(ob); + cardNamesPane.setSelectedIndex(i); + showCard(); + return; + } + } + } + + @Override + public T updateBean() { + return cards.get(cardNamesPane.getSelectedIndex()).updateBean(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UITabbedPane.java b/designer_base/src/com/fr/design/gui/frpane/UITabbedPane.java new file mode 100644 index 0000000000..61773e5f63 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UITabbedPane.java @@ -0,0 +1,122 @@ +package com.fr.design.gui.frpane; + +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +import javax.swing.*; +import javax.swing.plaf.TabbedPaneUI; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-3-28 + * Time: 上午9:14 + */ +public class UITabbedPane extends JTabbedPane{ + + private boolean isClosable = false; //Tab是否可关闭 + private String classPath; //panel对象的类名 + private String tabName; //Tab名称 + private int tabSize = 0; + public UITabbedPane() { + super(); + } + + public UITabbedPane(int tabPlacement) { + super(tabPlacement); + } + + public UITabbedPane(int tabPlacement, int tabLayoutPolicy) { + super(tabPlacement, tabLayoutPolicy); + } + + public UITabbedPane(boolean closable,String tabname,String classpath){ + super(); + setClosable(closable); + setTabName(tabname); + setClassPath(classpath); + } + + /** + * 添加tab + * @param s tab名 + * @param component 组件 + */ + public void addTab(String s, Component component) { + if(isClosable() && ComparatorUtils.equals(s, getTabName())){ + super.addTab(s + tabSize, component); + }else{ + super.addTab(s, component); + } + tabSize++; + } + + /** + * 设置tab可关闭/添加 + * @param isClosable 是否可关闭/添加 + */ + public void setClosable(boolean isClosable){ + this.isClosable = isClosable; + } + + /** + * tab可关闭 + * @return 返回是否tab可关闭 + */ + public boolean isClosable(){ + return this.isClosable; + } + + public void setClassPath(String classpath){ + this.classPath = classpath; + } + + public String getClassPath(){ + return this.classPath; + } + + public void setTabName(String tabname){ + this.tabName = tabname; + } + + public String getTabName(){ + return this.tabName; + } + + public void setTabSize(int tabsize){ + tabSize = tabsize; + } + + public int getTabSize(){ + return tabSize; + } + @Override + /** + * 获取UI对象 + */ + public TabbedPaneUI getUI(){ + return new UITabbedPaneUI(); + } + + @Override + /** + * 更新UI + */ + public void updateUI() { + setUI(getUI()); + } + + /** + * 删除tab,不能直接复写removeTabAt + * @param i tab索引 + */ + public void doRemoveTab(int i){ + int re = JOptionPane.showConfirmDialog(SwingUtilities.getWindowAncestor(UITabbedPane.this), Inter.getLocText("sure_to_delete")+ "?", Inter.getLocText("Remove") + , JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + if (re == JOptionPane.OK_OPTION) { + super.removeTabAt(i); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UITabbedPaneUI.java b/designer_base/src/com/fr/design/gui/frpane/UITabbedPaneUI.java new file mode 100644 index 0000000000..c1b8433555 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UITabbedPaneUI.java @@ -0,0 +1,431 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.general.FRLogger; +import com.fr.general.GeneralUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTabbedPaneUI; +import java.awt.*; +import java.awt.event.*; + +/** + * Coder: Sean + * Date: 13-12-30 + * Time: 上午11:38 + */ +public class UITabbedPaneUI extends BasicTabbedPaneUI { + + private int closeX = -1; + private int closeY = -1; + + private static final Icon ADD_NORMAL = BaseUtils.readIcon("com/fr/design/images/gui/tab_add_normal.png"); + private static final Icon ADD_OVER = BaseUtils.readIcon("com/fr/design/images/gui/tab_add_hover.png"); + private static final Icon ADD_CLICK = BaseUtils.readIcon("com/fr/design/images/gui/tab_add_click.png"); + private Icon addBtn = ADD_NORMAL; + private Icon closeIcon = BaseUtils.readIcon("com/fr/design/images/gui/tab_delete.png"); + private int addX = -1; + private int addY = -1; + private int rollover = -1; + private Color tabBorderColor = new Color(143, 160, 183); + private Color[] tabSelectedColor = {new Color(255, 199, 59), new Color(187, 142, 33), new Color(214, 191, 137)}; + + /** + * 创建UI对象 + * @param c 容器 + * @return 返回UI对象 + */ + public static ComponentUI createUI(JComponent c) { + return new UITabbedPaneUI(); + } + + /** + * 初始化监听事件 + */ + protected void installListeners() { + super.installListeners(); + tabPane.addMouseMotionListener( + (MouseMotionListener)mouseListener); + } + protected MouseListener createMouseListener() { + return new UIMouseHandler(); + } + + public class UIMouseHandler implements MouseListener, MouseMotionListener { + /** + * 鼠标按下 + * @param e 事件 + */ + public void mousePressed(MouseEvent e) { + if (!tabPane.isEnabled()) { + return; + } + int x = e.getX(), y = e.getY(); + if (addX!= -1 && isMouseInAdd(x, y)){ + addBtn = ADD_CLICK; + tabPane.repaint(); + } + int tabIndex = getTabAtLocation(x, y); + if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex)) { + if (canClose() && isMouseInClose(x, y)) { + ((UITabbedPane)tabPane).doRemoveTab(tabIndex); + } else if (tabIndex != tabPane.getSelectedIndex()) { + tabPane.setSelectedIndex(tabIndex); + } else if (tabPane.isRequestFocusEnabled()) { + tabPane.requestFocus(); + } + } + } + + /** + * 鼠标进入 + * @param e 事件 + */ + public void mouseEntered(MouseEvent e) {} + + /** + * 鼠标离开 + * @param e 事件 + */ + public void mouseExited(MouseEvent e) { + if (rollover >= tabPane.getTabCount()) { + rollover = -1; + } + if (rollover != -1) { + tabPane.repaint(getTabBounds(tabPane, rollover)); + rollover = -1; + } + } + + /** + * 鼠标点击 + * @param e 事件 + */ + public void mouseClicked(MouseEvent e) {} + + /** + * 鼠标释放 + * @param e 事件 + */ + public void mouseReleased(MouseEvent e) { + if (addX!= -1 && isMouseInAdd(e.getX(),e.getY())){ + String classpath = ((UITabbedPane)tabPane).getClassPath(); + String tabName = ((UITabbedPane)tabPane).getTabName(); + try { + addBtn = ADD_NORMAL; + tabPane.addTab(tabName, + (Component) GeneralUtils.classForName(classpath).newInstance()); + } catch (Exception ex) { + FRLogger.getLogger().error(ex.getMessage(),ex); + } + } + } + + /** + * 鼠标拖拽 + * @param e 事件 + */ + public void mouseDragged(MouseEvent e) {} + + /** + * 鼠标移动 + * @param e 事件 + */ + public void mouseMoved(MouseEvent e) { + if (tabPane == null) { + return; + } + if (!tabPane.isEnabled()) { + return; + } + int x = e.getX(), y = e.getY(); + if (addX != -1 && isMouseInAdd(x, y)) { + addBtn = ADD_OVER; + tabPane.repaint(); + }else if(addBtn != ADD_NORMAL){ + addBtn = ADD_NORMAL; + tabPane.repaint(); + } + checkRollOver(getTabAtLocation(x, y)); + } + } + + /** + * 判断鼠标是否在添加按钮上 + * @param x 鼠标坐标x + * @param y 鼠标坐标y + * @return 返回鼠标是否在添加按钮上 + */ + private boolean isMouseInAdd(int x, int y){ + int addWidth = addBtn.getIconWidth(),addHeight = addBtn.getIconHeight(); + return x >= addX && x <= addX + addWidth && y > addY && y <= addY + addHeight; + } + + /** + * 判断鼠标是否在关闭按钮上 + * @param x 鼠标坐标x + * @param y 鼠标坐标y + * @return 返回鼠标是否在关闭按钮上 + */ + private boolean isMouseInClose(int x, int y){ + int closeWidth = closeIcon.getIconWidth(),closeHeight = closeIcon.getIconHeight(); + return x >= closeX && x <= closeX + closeWidth && y > closeY && y <= closeY + closeHeight; + } + + /** + * 如果tab只剩下最后一个,则不画删除按钮 + * @return 返回当前tab还可否关闭 + */ + private boolean canClose(){ + return tabPane.getTabCount() > 1 && ((UITabbedPane) tabPane).isClosable(); + } + + /** + * tab轮转切换 + * + * @param tabIndex tab索引 + */ + private void checkRollOver(int tabIndex) { + if (rollover >= tabPane.getTabCount()) { + rollover = -1; + } + if (tabIndex == rollover) { + return; + } + if (rollover != -1) { + tabPane.repaint(getTabBounds(tabPane, rollover)); + if (tabIndex == -1) { + rollover = -1; + } + } + if (tabIndex >= 0 && tabPane.isEnabledAt(tabIndex)) { + rollover = tabIndex; + tabPane.repaint(getTabBounds(tabPane, tabIndex)); + } + } + + /** + * 根据鼠标坐标获取tab + * + * @param x 鼠标坐标x + * @param y 鼠标坐标y + * @return 返回tab索引 + */ + private int getTabAtLocation(int x, int y) { + return tabForCoordinate(tabPane, x, y); + } + + /** + * 绘制tab的边框 + */ + protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) { + boolean isEnabled = (tabPane.isEnabledAt(tabIndex)); + if (!tabPane.isEnabled()) { + isEnabled = false; + } + boolean isRollover = (rollover == tabIndex); + drawUITabBorder(g, tabPlacement, x, y, w, h, isSelected, isEnabled, isRollover); + } + + /** + * 根据tab的状态绘制tab的边框 + */ + private void drawUITabBorder(Graphics g, int tabPlacement, int x, int y, int w, int h, + boolean isSelected, boolean isEnabled, boolean isRollover) { + if (!isEnabled) { + drawUITabBorder(g, tabBorderColor, x, y, w, h, tabPlacement); + } else if (isSelected || isRollover) { + drawSelectedUITabBorder(g, tabBorderColor, x, y, w, h, tabPlacement); + if(isRollover && canClose()){ + closeX = x + w - closeIcon.getIconWidth() - 3; + closeY = 0; + switch (tabPlacement) { + case BOTTOM: + closeY = y; + break; + case TOP: + closeY = y + 3; + break; + } + closeIcon.paintIcon(tabPane, g, closeX, closeY); + } + } else { + drawUITabBorder(g, tabBorderColor, x, y, w, h, tabPlacement); + } + } + + /** + * 更新界面 + * @param g + * @param c + */ + public void update(Graphics g, JComponent c) { + Insets insets = tabPane.getInsets(); + int x = insets.left; + int y = insets.top; + int w = tabPane.getWidth() - insets.right - insets.left; + int h = tabPane.getHeight() - insets.top - insets.bottom; + + if (c.isOpaque()) { + g.setColor(UIConstants.NORMAL_BACKGROUND); + g.fillRect(0, 0, c.getWidth(), c.getHeight()); + } + + int tabPlacement = tabPane.getTabPlacement(); + switch (tabPlacement) { + case BOTTOM: + h -= calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); + break; + case TOP: + default: + y += calculateTabAreaHeight(tabPlacement, runCount, maxTabHeight); + h -= (y - insets.top); + } + drawUIContentBorder(g, x, y, w, h); + if (((UITabbedPane) tabPane).isClosable()) { + drawUITabAddBtn(g, tabPlacement, x, y, w, h); + } + super.paint(g, c); + } + + private void drawUITabAddBtn(Graphics g, int tabPlacement, int x, int y, int w, int h) { + addX = rects[tabPane.getTabCount() - 1].x + rects[tabPane.getTabCount() - 1].width + 4; + switch (tabPlacement) { + case BOTTOM: + addY = y + h + 3; + break; + case TOP: + addY = y - addBtn.getIconHeight() - 3; + break; + } + addBtn.paintIcon(tabPane, g, addX, addY); + } + + private void drawUIContentBorder(Graphics g, int x, int y, int w, int h) { + g.setColor(tabBorderColor); + g.drawRect(x, y, w - 3, h - 3); + // Shadow + g.setColor(new Color(204, 204, 204)); + g.drawLine(x + w - 2, y + 1, x + w - 2, y + h - 2); // right + g.drawLine(x + 1, y + h - 2, x + w - 3, y + h - 2); // bottom + } + + protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) { + } + + /** + * 绘制tab的边框 + */ + private void drawUITabBorder( + Graphics g, Color c, int x, int y, int w, int h, int tabPlacement) { + Color c2 = null; + g.setColor(c); + switch (tabPlacement) { + case SwingConstants.BOTTOM: + w -= 1; + y -= 2; + g.drawLine(x + 2, y + h - 1, x + w - 3, y + h - 1); + g.drawLine(x, y, x, y + h - 3); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 3); + c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), 56); + g.setColor(c2); + g.drawLine(x, y + h - 1, x, y + h - 1); + g.drawLine(x + w - 1, y + h - 1, x + w - 1, y + h - 1); + c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), 183); + g.setColor(c2); + g.drawLine(x, y + h - 2, x, y + h - 2); + g.drawLine(x + 1, y + h - 1, x + 1, y + h - 1); + g.drawLine(x + w - 2, y + h - 1, x + w - 2, y + h - 1); + g.drawLine(x + w - 1, y + h - 2, x + w - 1, y + h - 2); + c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), 76); + g.setColor(c2); + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + g.drawLine(x + w - 2, y + h - 2, x + w - 2, y + h - 2); + break; + case SwingConstants.TOP: + default: + w -= 1; + g.drawLine(x + 2, y, x + w - 3, y); + g.drawLine(x, y + 2, x, y + h - 1); + g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1); + c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), 56); + g.setColor(c2); + g.drawLine(x, y, x, y); + g.drawLine(x + w - 1, y, x + w - 1, y); + c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), 183); + g.setColor(c2); + g.drawLine(x + 1, y, x + 1, y); + g.drawLine(x + w - 2, y, x + w - 2, y); + g.drawLine(x, y + 1, x, y + 1); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + 1); + c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), 76); + g.setColor(c2); + g.drawLine(x + 1, y + 1, x + 1, y + 1); + g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1); + } + } + + /** + * 绘制被选中的tab + */ + private void drawSelectedUITabBorder(Graphics g, Color c, int x, int y, int w, int h, int tabPlacement) { + Color c1 = tabSelectedColor[0]; + Color c2 = tabSelectedColor[1]; + Color c3 = tabSelectedColor[2]; + g.setColor(c2); + switch (tabPlacement) { + case SwingConstants.BOTTOM: + w -= 1; + y -= 2; + g.drawLine(x + 2, y + h - 1, x + w - 3, y + h - 1);//下梯形,4个点2横线 + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + g.drawLine(x + w - 2, y + h - 2, x + w - 2, y + h - 2); + g.drawLine(x, y + h - 3, x, y + h - 3); + g.drawLine(x + w - 1, y + h - 3, x + w - 1, y + h - 3); + g.setColor(c1);//梯形内部,2横线 + g.drawLine(x + 2, y + h - 2, x + w - 3, y + h - 2); + g.drawLine(x + 1, y + h - 3, x + w - 2, y + h - 3); + g.setColor(c);//左右的边框,2竖线 + g.drawLine(x, y, x, y + h - 4); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 4); + g.setColor(c3);//角,4个点 + g.drawLine(x + 1, y + h - 1, x + 1, y + h - 1); + g.drawLine(x, y + h - 2, x, y + h - 2); + g.drawLine(x + w - 2, y + h - 1, x + w - 2, y + h - 1); + g.drawLine(x + w - 1, y + h - 2, x + w - 1, y + h - 2); + break; + case SwingConstants.TOP: + default: + w -= 1; + g.drawLine(x + 2, y, x + w - 3, y); + g.drawLine(x + 1, y + 1, x + 1, y + 1); + g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1); + g.drawLine(x, y + 2, x, y + 2); + g.drawLine(x + w - 1, y + 2, x + w - 1, y + 2); + g.setColor(c1); + g.drawLine(x + 2, y + 1, x + w - 3, y + 1); + g.drawLine(x + 1, y + 2, x + w - 2, y + 2); + g.setColor(c3); + g.drawLine(x + 1, y, x + 1, y); + g.drawLine(x, y + 1, x, y + 1); + g.drawLine(x + w - 2, y, x + w - 2, y); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + 1); + g.setColor(c); + g.drawLine(x, y + 3, x, y + h - 1); + g.drawLine(x + w - 1, y + 3, x + w - 1, y + h - 1); + } + } + + protected LayoutManager createLayoutManager() { + super.createLayoutManager(); + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { + return super.createLayoutManager(); + } else { + return new UITabbedPaneLayout(); + } + } + + protected class UITabbedPaneLayout extends TabbedPaneLayout {} +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UITextPane.java b/designer_base/src/com/fr/design/gui/frpane/UITextPane.java new file mode 100644 index 0000000000..ab7fed53a3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UITextPane.java @@ -0,0 +1,90 @@ +package com.fr.design.gui.frpane; + +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.StyledDocument; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-3-27 + * Time: 上午10:50 + */ +public class UITextPane extends JTextPane implements UIObserver { + + private UIObserverListener uiObserverListener; + + public UITextPane() { + super(); + iniListener(); + } + + public UITextPane(StyledDocument doc) { + super(doc); + iniListener(); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + attributeChanged(); + } + }); + } + + @Override + public void removeUpdate(DocumentEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + attributeChanged(); + } + }); + } + + @Override + public void changedUpdate(DocumentEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + attributeChanged(); + } + }); + } + }); + } + } + + + private void attributeChanged() { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + + } + + @Override + /** + * + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + @Override + /** + * + */ + public boolean shouldResponseChangeListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UITitlePanel.java b/designer_base/src/com/fr/design/gui/frpane/UITitlePanel.java new file mode 100644 index 0000000000..6cdcf50cff --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UITitlePanel.java @@ -0,0 +1,46 @@ +/** + * + */ +package com.fr.design.gui.frpane; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; + +import javax.swing.BorderFactory; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.design.layout.FRGUIPaneFactory; + +/** + * @author zhou + * + */ +public class UITitlePanel extends JPanel { + public UITitlePanel(JPanel contentPanel) { + this.setLayout(new BorderLayout()); + this.setBorder(null); + this.add(contentPanel, BorderLayout.CENTER); + } + + public UITitlePanel(JPanel contentPanel, String title) { + JPanel TitleBar = FRGUIPaneFactory.createBorderLayout_S_Pane(); + TitleBar.setBackground(new Color(148, 148, 148)); + TitleBar.setForeground(Color.white); + TitleBar.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, new Color(85, 85, 85))); + + UILabel titlelabel = new UILabel(" " + title); + titlelabel.setBackground(new Color(148, 148, 148)); + titlelabel.setForeground(new Color(242, 242, 242)); + TitleBar.setPreferredSize(new Dimension(getWidth(), 20)); + TitleBar.setRequestFocusEnabled(true); + TitleBar.add(titlelabel, BorderLayout.WEST); + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createEmptyBorder()); + this.add(TitleBar, BorderLayout.NORTH); + this.add(contentPanel, BorderLayout.CENTER); + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/frpane/UnitInputPane.java b/designer_base/src/com/fr/design/gui/frpane/UnitInputPane.java new file mode 100644 index 0000000000..40390e91d3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/frpane/UnitInputPane.java @@ -0,0 +1,170 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.frpane; + +import com.fr.base.Utils; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ispinner.UIBasicSpinner; +import com.fr.design.gui.itextfield.UINumberField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.math.BigDecimal; + +/** + * For input Number. + */ +public abstract class UnitInputPane extends BasicPane { + private static final double NUM_POINT = 0.000001; + private int scale = -1; + String title; + + public UnitInputPane(int scale, String name) { + this.scale = scale; + title = name; + initComponents(); + } + + protected void initComponents() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel centerPane = FRGUIPaneFactory.createTitledBorderPane(""); + this.add(centerPane, BorderLayout.CENTER); + centerPane.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 30)); + UILabel titleLabel = new UILabel(title + ":"); + centerPane.add(titleLabel); + + // Denny:在对话框中加入JSpinner对象 + numberFieldSpinner = new UIBasicSpinner(new SpinnerNumberModel(0, 0, 999, 1)); + GUICoreUtils.setColumnForSpinner(numberFieldSpinner, 24); + numberFieldSpinner.setPreferredSize(new Dimension(60, 20)); + numberFieldSpinner.setMinimumSize(new Dimension(60, 20)); + centerPane.add(numberFieldSpinner); + numberFieldSpinner.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent arg0) { + if (Math.abs((((Double) numberFieldSpinner.getValue()).floatValue() - popValue)) > NUM_POINT) { + changed = true; + } + } + }); + + unitLabel = new UILabel(""); + centerPane.add(unitLabel); + } + + public void setUnitText(String unit) { + this.unitLabel.setText("(" + unit + ")"); + } + + public void populate(float floatValue) { + popValue = floatValue; + numberFieldSpinner.setModel(new SpinnerNumberModel(0.00, 0.00, 999.00, 0.01)); + + JFormattedTextField temp = GUICoreUtils.getSpinnerTextField(numberFieldSpinner); + addChangeListener(temp); + BigDecimal de = new BigDecimal(floatValue + ""); + if (scale > 0) { + floatValue = de.setScale(scale, BigDecimal.ROUND_DOWN).floatValue(); + } else { + floatValue = de.floatValue(); + } + //选中多列, 并且列宽不完全一致的话, 就不显示值了. + temp.setText(floatValue == 0 ? StringUtils.EMPTY : Utils.convertNumberStringToString(new Float(floatValue))); + + // denny:默认应该为选中,方便用户修改 + temp.selectAll(); + } + + private void addChangeListener(JFormattedTextField temp) { + temp.removeKeyListener(kl); + temp.addKeyListener(kl); + temp.removeMouseListener(ml); + temp.addMouseListener(ml); + } + + // 抛个错只是为了通知外面值没变 + public double update() throws ValueNotChangeException { + // 值没变就不改 + if (!changed) { + throw vncExp; + } + // Denny: get numberFieldSpinner 的 TextField + JFormattedTextField temp = GUICoreUtils.getSpinnerTextField(numberFieldSpinner); + + try { + if (temp.getText().length() == 0) { + return 0; + } + BigDecimal de = new BigDecimal(temp.getText()); + if (scale > 0) { + return de.setScale(scale, BigDecimal.ROUND_DOWN).floatValue(); + } else { + return de.floatValue(); + } + } catch (NumberFormatException numberFormatException) { + + return UINumberField.ERROR_VALUE; + } + } + + public static class ValueNotChangeException extends Exception { + } + + private UILabel unitLabel; + private UIBasicSpinner numberFieldSpinner; + private float popValue; + private boolean changed = false; + private ValueNotChangeException vncExp = new ValueNotChangeException(); + + private KeyListener kl = new KeyListener() { + + @Override + public void keyTyped(KeyEvent arg0) { + } + + @Override + public void keyReleased(KeyEvent arg0) { + } + + @Override + public void keyPressed(KeyEvent arg0) { + changed = true; + } + }; + + private MouseListener ml = new MouseListener() { + + @Override + public void mouseReleased(MouseEvent arg0) { + } + + @Override + public void mousePressed(MouseEvent arg0) { + changed = true; + } + + @Override + public void mouseExited(MouseEvent arg0) { + } + + @Override + public void mouseEntered(MouseEvent arg0) { + } + + @Override + public void mouseClicked(MouseEvent arg0) { + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/FiveButtonLayout.java b/designer_base/src/com/fr/design/gui/ibutton/FiveButtonLayout.java new file mode 100644 index 0000000000..97f68e7fa3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/FiveButtonLayout.java @@ -0,0 +1,55 @@ +package com.fr.design.gui.ibutton; + +import java.awt.*; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-5-27 + * Time: 下午4:51 + * To change this template use File | Settings | File Templates. + */ +public class FiveButtonLayout extends GridLayout { + private static final double SECOND_ROW = 1.25; + + public FiveButtonLayout () { + super(2, 3, 1, 1); + } + + /** + * 容器布局 + * @param parent 容器 + */ + public void layoutContainer(Container parent) { + synchronized(parent.getTreeLock()) { + Insets insets = parent.getInsets(); + int ncomponents = parent.getComponentCount(); + int nrows = 2; + int ncols = 3; + if (ncomponents == 0) { + return; + } + if (nrows > 0) { + ncols = (ncomponents + nrows - 1) / nrows; + } else { + nrows = (ncomponents + ncols - 1) / ncols; + } + int w = parent.getWidth() - (insets.left + insets.right); + int h = parent.getHeight() - (insets.top + insets.bottom); + w = (w - (ncols - 1) ) / ncols; + h = (h - (nrows - 1) ) / nrows; + for (int i = 0, x = insets.left, y = insets.top; i < ncols; i ++, x += w + 1) { + parent.getComponent(i).setBounds(x, y, w, h); + } + int line2w = (int) (SECOND_ROW * w); + int secondRowCount = ncomponents-ncols; + int startx= (parent.getWidth()-line2w*secondRowCount-secondRowCount-1)/2; + for (int i = ncols, x = startx, y = insets.top + h + 1; i < ncomponents; i++, x += line2w + 1) { + parent.getComponent(i).setBounds(x, y, line2w, h); + } + + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/SpecialUIButton.java b/designer_base/src/com/fr/design/gui/ibutton/SpecialUIButton.java new file mode 100644 index 0000000000..9289eba536 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/SpecialUIButton.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ibutton; + +import javax.swing.*; +import javax.swing.plaf.ButtonUI; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-5 + * Time: 下午4:52 + */ +public class SpecialUIButton extends JButton { + public SpecialUIButton(ButtonUI ui) { + this.ui = ui; + ui.installUI(this); + } + + /** + * refuses to change the UI delegate. It keeps the one set in the constructor. + * + * @see javax.swing.AbstractButton#setUI(ButtonUI) + */ + public void setUI(ButtonUI ui) { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIBasicButtonUI.java b/designer_base/src/com/fr/design/gui/ibutton/UIBasicButtonUI.java new file mode 100644 index 0000000000..52b20cd3db --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIBasicButtonUI.java @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ibutton; + +import com.fr.design.gui.itoolbar.UIToolBarUI; +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalButtonUI; +import java.awt.*; +import java.awt.event.KeyEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-19 + * Time: 上午9:29 + */ +public class UIBasicButtonUI extends MetalButtonUI { + + // if a button has not the defined background, it will + // be darkened resp. lightened by BG_CHANGE amount if + // pressed or rollover + public static final int BG_CHANGE_AMOUNT = 10; + + /** + * The Cached UI delegate. + */ + private static final UIBasicButtonUI BUTTON_UI = new UIBasicButtonUI(); + + /* the only instance of the stroke for the focus */ + private static final BasicStroke FOCUS_STROKE = + new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{1.0f, 1.0f}, 0.0f); + + private boolean graphicsTranslated; + private boolean isToolBarButton, isFileChooserButton; + private boolean isDefault; + + public UIBasicButtonUI() { + } + + /** + * 初始化UI + * + * @param c 组件c + */ + public void installUI(JComponent c) { + super.installUI(c); + + if (!ThemeUtils.BUTTON_ENTER) { + return; + } + if (!c.isFocusable()) { + return; + } + + InputMap km = (InputMap) UIManager.get(getPropertyPrefix() + "focusInputMap"); + + if (km != null) { + // replace SPACE with ENTER (but SPACE will still work, don't know why) + km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "pressed"); + km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "released"); + } + } + + /** + * 加载默认的 + * + * @param button 按钮 + */ + public void installDefaults(AbstractButton button) { + super.installDefaults(button); + button.setRolloverEnabled(true); + } + + protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { + boolean isToolButtonFocus = isToolBarButton && !ThemeUtils.TOOL_FOCUS; + boolean isOk = isFileChooserButton || !ThemeUtils.BUTTON_FOCUS; + if (isOk || isToolButtonFocus) { + return; + } + + Graphics2D g2d = (Graphics2D) g; + Rectangle focusRect = b.getBounds(); + + g.setColor(Color.black); + g2d.setStroke(FOCUS_STROKE); + + int x1 = 2; + int y1 = 2; + int x2 = x1 + focusRect.width - 5; + int y2 = y1 + focusRect.height - 5; + + if (!isToolBarButton) { + x1++; + y1++; + x2--; + y2--; + } + } + + /** + * 创建UI + * + * @param c 组件 + * @return 创建的UI + */ + public static ComponentUI createUI(final JComponent c) { + return BUTTON_UI; + } + + protected void paintButtonPressed(Graphics g, AbstractButton button) { + if (isToolBarButton || isFileChooserButton) { + return; + } + + Color col = null; + if (!ComparatorUtils.equals(button.getBackground(), ThemeUtils.BUTTON_NORMAL_COLOR)) { + col = ColorRoutines.darken(button.getBackground(), BG_CHANGE_AMOUNT); + } else { + col = ThemeUtils.BUTTON_PRESS_COLOR; + } + + g.setColor(col); + + drawXpButton(g, button, col, false); + if (!(button instanceof JToggleButton)) { + // Changed in 1.3.04: If button is icon-only + // then don't shift + if (ThemeUtils.SHIFT_BUTTON_TEXT && button.getText() != null && !"".equals(button.getText())) { + g.translate(1, 1); + graphicsTranslated = true; + } + } + } + + public void paintToolBarButton(Graphics g, AbstractButton b) { + Color col = null; + + // New in 1.3.7 + boolean isRollover = b.getModel().isRollover() || b.getModel().isArmed(); + Color toolButtColor = null; + + if (isFileChooserButton) { + toolButtColor = b.getParent().getBackground(); + } else { + toolButtColor = ThemeUtils.TOOLBUTT_COLOR; + } + + if (b.getModel().isPressed()) { + if (isRollover) { + col = ThemeUtils.TOOLBUTT_PRESSED_COLOR; + } else { + if (b.isSelected()) { + col = ThemeUtils.TOOLBUTT_SELECTED_COLOR; + } else { + col = toolButtColor; + } + } + } else if (isRollover) { + if (b.isSelected()) { + col = ThemeUtils.TOOLBUTT_SELECTED_COLOR; + } else { + col = ThemeUtils.TOOLBUTT_ROLLOVER_COLOR; + } + } else if (b.isSelected()) { + col = ThemeUtils.TOOLBUTT_SELECTED_COLOR; + } else { + col = toolButtColor; + } + g.setColor(col); + drawXpToolBarButton(g, b, col, false); + } + + public void paint(Graphics g, JComponent c) { + AbstractButton button = (AbstractButton) c; + if (isToolBarButton || isFileChooserButton) { + paintToolBarButton(g, button); + // the base class may paint text and/or icons + super.paint(g, c); + return; + } + if ((button instanceof JToggleButton) && button.isSelected()) { + paintButtonPressed(g, button); + // the base class may paint text and/or icons + super.paint(g, c); + return; + } + isDefault = (c instanceof JButton) && (((JButton) c).isDefaultButton()); + boolean isRollover = button.getModel().isRollover() && ThemeUtils.BUTTON_ROLLOVER; + boolean isDefinedBackground = ComparatorUtils.equals(c.getBackground(), ThemeUtils.BUTTON_NORMAL_COLOR); + Color col = null; + if (!button.isEnabled()) { + col = ThemeUtils.BUTTON_DISABLE_COLOR; + } else if (button.getModel().isPressed()) { + if (isRollover) { + if (isDefinedBackground) { + col = ThemeUtils.BUTTON_PRESS_COLOR; + } else { + col = ColorRoutines.darken(c.getBackground(), BG_CHANGE_AMOUNT); + } + } else { + // button pressed but mouse exited + col = c.getBackground(); + } + } else if (isRollover) { + if (isDefinedBackground) { + col = ThemeUtils.BUTTON_ROLLOVER_BG_COLOR; + } else { + col = ColorRoutines.lighten(c.getBackground(), BG_CHANGE_AMOUNT); + } + } else { + col = c.getBackground(); + } + g.setColor(col); + drawXpButton(g, button, col, isRollover); + // the base class may paint text and/or icons + super.paint(g, c); + } + + // this overrides BasicButtonUI.paintIcon(...) + protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) { + if (c instanceof JToggleButton) { + paintToggleButtonIcon(g, c, iconRect); + } else { + super.paintIcon(g, c, iconRect); + } + } + + protected void paintToggleButtonIcon(Graphics g, JComponent c, Rectangle iconRect) { + AbstractButton b = (AbstractButton) c; + ButtonModel model = b.getModel(); + Icon icon = null; + + if (!model.isEnabled()) { + if (model.isSelected()) { + icon = (Icon) b.getDisabledSelectedIcon(); + } else { + icon = (Icon) b.getDisabledIcon(); + } + } else if (model.isPressed() && model.isArmed()) { + icon = (Icon) b.getPressedIcon(); + if (icon == null) { + // Use selected icon + icon = (Icon) b.getSelectedIcon(); + } + } else if (model.isSelected()) { + if (b.isRolloverEnabled() && model.isRollover()) { + icon = (Icon) b.getRolloverSelectedIcon(); + if (icon == null) { + icon = (Icon) b.getSelectedIcon(); + } + } else { + icon = (Icon) b.getSelectedIcon(); + } + } else if (model.isRollover()) { + icon = (Icon) b.getRolloverIcon(); + } + + if (icon == null) { + icon = (Icon) b.getIcon(); + } + + icon.paintIcon(b, g, iconRect.x, iconRect.y); + } + + public void update(Graphics g, JComponent c) { + + isToolBarButton = ComparatorUtils.equals(Boolean.TRUE, c.getClientProperty(UIToolBarUI.IS_TOOL_BAR_BUTTON_KEY)); + isFileChooserButton = ComparatorUtils.equals(Boolean.TRUE, c.getClientProperty("JFileChooser.isFileChooserButton")); + paint(g, c); + graphicsTranslated = false; + } + + private void drawXpButton(Graphics g, AbstractButton b, Color c, boolean isRollover) { + if (!b.isContentAreaFilled()) { + return; + } + if (!b.isOpaque()) { + return; + } + int w = b.getWidth(); + int h = b.getHeight(); + + // paint border background + if (b.getParent() != null) { + Color bg = b.getParent().getBackground(); + g.setColor(bg); + } + g.drawRect(0, 0, w - 1, h - 1); + + Color normalLightColor = ThemeUtils.NORMAL_LIGHT_COLOR; + Color normalDarkColor = ThemeUtils.NORMAL_DARK_COLOR; + Graphics2D g2 = (Graphics2D) g; + drawHighLightButton(g2, normalLightColor, normalDarkColor, w, h); + + // 1 pixel away from each corner + if (isRollover) { + g2.setColor(ThemeUtils.BUTTON_ROLLOVER_COLOR); + g2.drawLine(1, h - 2, 1, h - 2); + g2.drawLine(w - 2, h - 2, w - 2, h - 2); + Color rolloverLightColor = ThemeUtils.ROLLOVER_LIGHT_COLOR; + Color rolloverDarkColor = ThemeUtils.ROLLOVER_DARK_COLOR; + drawHighLightButton(g2, rolloverLightColor, rolloverDarkColor, w, h); + + } else if (isDefault) { + g2.setColor(ThemeUtils.BUTTON_DEFAULT_COLOR); + g2.drawLine(1, h - 2, 1, h - 2); + g2.drawLine(w - 2, h - 2, w - 2, h - 2); + Color defaultLightColor = ThemeUtils.DEFAULT_LIGHT_COLOR; + Color defaultDarkColor = ThemeUtils.DEFAULT_DARK_COLOR; + drawHighLightButton(g2, defaultLightColor, defaultDarkColor, w, h); + } + } + + //harry: 画带有高光的按钮。 + private void drawHighLightButton(Graphics2D g2, Color color1, Color color2, int w, int h) { + GradientPaint buttonPaint = new GradientPaint(0, 0, color1, 0, h - 1, color2); + GradientPaint buttonHighLightPaint = new GradientPaint(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.6f), 0, h / 2, new Color(1.0f, 1.0f, 1.0f, 0.2f)); + GradientPaint buttonHighLightLinePaint = new GradientPaint(1, 1, new Color(1.0f, 1.0f, 1.0f, 0.8f), 0, h / 2, new Color(1.0f, 1.0f, 1.0f, 0.4f)); + g2.setPaint(buttonPaint); + g2.fillRoundRect(0, 0, w - 1, h - 1, 3, 3); + g2.setPaint(buttonHighLightLinePaint);//按钮内侧高光线(内发光,0%阻塞) + g2.drawRoundRect(1, 1, w - 3, h - 3, 2, 2); + g2.setPaint(buttonHighLightPaint); + g2.fillRoundRect(0, 0, w - 1, h / 2, 3, 3);//按钮高光,覆盖按钮的上半部分。 + } + + + private void drawXpToolBarButton(Graphics g, AbstractButton b, Color c, boolean isPressed) { + int w = b.getWidth(); + int h = b.getHeight(); + b.setOpaque(false); + + if (b.isContentAreaFilled()) { + g.fillRect(1, 1, w - 2, h - 2); + } + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIButton.java b/designer_base/src/com/fr/design/gui/ibutton/UIButton.java new file mode 100644 index 0000000000..b93ae1a1f6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIButton.java @@ -0,0 +1,361 @@ +package com.fr.design.gui.ibutton; + +import com.fr.base.BaseUtils; +import com.fr.base.CellBorderStyle; +import com.fr.base.GraphHelper; +import com.fr.design.constants.UIConstants; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.plaf.ButtonUI; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.RoundRectangle2D; + +public class UIButton extends JButton implements UIObserver { + + public static final int OTHER_BORDER = 1; + public static final int NORMAL_BORDER = 2; + private static final int HEIGH = 20; + private boolean isExtraPainted = true; + private boolean isRoundBorder = true; + private int rectDirection = Constants.NULL; + private Stroke borderStroke = UIConstants.BS; + private Color borderColor = UIConstants.LINE_COLOR; + + private boolean isPressedPainted = true; + private boolean isNormalPainted = true; + protected boolean isBorderPaintedOnlyWhenPressed = false; + + private int borderType = NORMAL_BORDER; + private CellBorderStyle border = null; + + protected UIObserverListener uiObserverListener; + + public UIButton() { + this(StringUtils.EMPTY); + } + + public UIButton(String string) { + super(string); + init(); + } + + + public UIButton(Icon icon) { + super(icon); + init(); + } + + public UIButton(Action action) { + super(action); + init(); + } + + public UIButton(String text, Icon icon) { + super(text, icon); + init(); + } + + /** + * 是否进行过权限编辑 + * @param role 角色 + * @return 否 + */ + public boolean isDoneAuthorityEdited(String role) { + return false; + } + + public UIButton(Icon normal, Icon rollOver, Icon pressed) { + super(normal); + setBorderPainted(false); + setRolloverIcon(rollOver); + setPressedIcon(pressed); + setExtraPainted(false); + setBackground(null); + setOpaque(false); + initListener(); + } + + protected void initListener() { + if (shouldResponseChangeListener()) { + this.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + + //确定是正常的边框类型,还是其他的Border类型 + //若是其他的border类型,则要setOtherType,即设置线型颜色等。若是其他类型,但是没有设置,则默认的是虚线型边框 + public void setBorderType(int borderType) { + this.borderType = borderType; + } + + + public void setBorderStyle(CellBorderStyle border) { + this.border = border; + } + + public void set4ToolbarButton() { + setNormalPainted(false); + Dimension dim = getPreferredSize(); + dim.height = HEIGH; + setBackground(null); + setOpaque(false); + setSize(dim); + setBorderPaintedOnlyWhenPressed(true); + } + + public void set4LargeToolbarButton() { + setNormalPainted(false); + setBackground(null); + setOpaque(false); + setSize(new Dimension(40, 40)); + setBorderPaintedOnlyWhenPressed(true); + } + + public void set4ChartLargeToolButton(){ + setNormalPainted(false); + setBackground(null); + setOpaque(false); + setSize(new Dimension(34, 44)); + setBorderPaintedOnlyWhenPressed(true); + } + + + private void init() { + setBackground(null); + setRolloverEnabled(true); + initListener(); + } + + @Override + public ButtonUI getUI() { + return new UIButtonUI(); + } + + /** + * 更新界面 + */ + public void updateUI() { + setUI(getUI()); + } + + public CellBorderStyle getBorderStyle() { + return this.border; + } + + @Override + public Insets getInsets() { + if (getIcon() != null) { + return new Insets(0, 3, 0, 3); + } + return new Insets(0, 10, 0, 10); + } + + //@Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, 20); + } + + + public int getBorderType() { + return borderType; + } + + public void setOtherBorder(Stroke s, Color c) { + borderStroke = s; + borderColor = c; + } + + + @Override + protected void paintBorder(Graphics g) { + + if (!isBorderPainted()) { + return; + } + if (borderType == OTHER_BORDER) { + paintOtherBorder(g); + } else { + boolean isPress = (isBorderPaintedOnlyWhenPressed && getModel().isPressed()); + if (isPress || !isBorderPaintedOnlyWhenPressed) { + if (ui instanceof UIButtonUI) { + ((UIButtonUI) ui).paintBorder(g, this); + + } else { + super.paintBorder(g); + + } + } + } + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + Dimension size = this.getSize(); + Graphics2D g2d = (Graphics2D) g; + Stroke oldStroke = g2d.getStroke(); + if (border != null) { + g2d.setColor(border.getTopColor()); + GraphHelper.drawLine(g2d, 3, 4, size.getWidth() - 4, 4, border.getTopStyle()); + g2d.setColor(border.getLeftColor()); + GraphHelper.drawLine(g2d, 3, 4, 3, size.getHeight() - 4, border.getLeftStyle()); + g2d.setColor(border.getBottomColor()); + GraphHelper.drawLine(g2d, 3, size.getHeight() - 4, size.getWidth() - 4, size.getHeight() - 4, border.getBottomStyle()); + g2d.setColor(border.getRightColor()); + GraphHelper.drawLine(g2d, size.getWidth() - 4, 4, size.getWidth() - 4, size.getHeight() - 4, border.getRightStyle()); + } else { + GraphHelper.drawLine(g2d, 2, 4, size.getWidth() - 4, 4, Constants.LINE_NONE); + GraphHelper.drawLine(g2d, 2, 4, 2, size.getHeight() - 4, Constants.LINE_NONE); + GraphHelper.drawLine(g2d, 2, size.getHeight() - 4, size.getWidth() - 4, size.getHeight() - 4, Constants.LINE_NONE); + GraphHelper.drawLine(g2d, size.getWidth() - 4, 4, size.getWidth() - 4, size.getHeight() - 4, Constants.LINE_NONE); + } + g2d.setStroke(oldStroke); + } + + + protected void paintOtherBorder(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setStroke(borderStroke); + Shape shape = new RoundRectangle2D.Float(0.5f, 0.5f, getWidth() - 1, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.setColor(borderColor); + g2d.draw(shape); + } + + public void setExtraPainted(boolean extra) { + this.isExtraPainted = extra; + } + + /** + * 是否额外画 + * @return 是则返回TRUE + */ + public boolean isExtraPainted() { + return this.isExtraPainted; + } + + /** + * @return + */ + public int getRectDirection() { + return rectDirection; + } + + /** + * 是否圆边框 + * @return 是则返回true + */ + public boolean isRoundBorder() { + return isRoundBorder; + } + + /** + * @param isRoundBorder + */ + public void setRoundBorder(boolean isRoundBorder) { + setRoundBorder(isRoundBorder, Constants.NULL); + } + + /** + * @param isRound + * @param rectDirection + */ + public void setRoundBorder(boolean isRound, int rectDirection) { + this.isRoundBorder = isRound; + this.rectDirection = rectDirection; + } + + /** + * 是否按压画 + * @return 是则返回TRUE + */ + public boolean isPressedPainted() { + return isPressedPainted; + } + + /** + * @param isPressedPainted + */ + public void setPressedPainted(boolean isPressedPainted) { + this.isPressedPainted = isPressedPainted; + } + + /** + * 是否正常画 + * @return 是则返回TRUE + */ + public boolean isNormalPainted() { + return isNormalPainted; + } + + /** + * @param isNormalPressed + */ + public void setNormalPainted(boolean isNormalPressed) { + this.isNormalPainted = isNormalPressed; + if (!isNormalPressed) { + setBackground(null); + setOpaque(false); + } + } + + /** + * @param value + */ + public void setBorderPaintedOnlyWhenPressed(boolean value) { + this.isBorderPaintedOnlyWhenPressed = value; + } + + /** + * 主函数 + * @param args 入口参数 + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(null); + + UIButton bb = new UIButton(BaseUtils.readIcon("/com/fr/design/images/buttonicon/add.png")); + bb.setEnabled(false); + bb.setBorderType(OTHER_BORDER); + // bb.setBounds(20, 20,content.getSize().width, bb.getPreferredSize().height); + bb.setPreferredSize(new Dimension(100, 30)); + bb.setBounds(0, 0, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } + + /** + * 给组件登记一个观察者监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + this.uiObserverListener = listener; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIButtonBorder.java b/designer_base/src/com/fr/design/gui/ibutton/UIButtonBorder.java new file mode 100644 index 0000000000..e82c39093c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIButtonBorder.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ibutton; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.utils.ThemeUtils; + + +import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-19 + * Time: 上午10:30 + */ +public class UIButtonBorder extends AbstractBorder implements UIResource { + protected final Insets borderInsets = new Insets(2, 2, 2, 2); + + /** + * Draws the button border for the given component. + * + * @param c The component to draw its border. + * @param g The graphics context. + * @param x The x coordinate of the top left corner. + * @param y The y coordinate of the top left corner. + * @param w The width. + * @param h The height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + drawXpBorder(c, g, x, y, w, h); + } + + + private void drawXpBorder(Component c, Graphics g, int x, int y, int w, int h) { + AbstractButton b = (AbstractButton) c; + boolean isDefault = (c instanceof JButton) && (((JButton) c).isDefaultButton()); + boolean isComboBoxButton = ComparatorUtils.equals(Boolean.TRUE,b.getClientProperty("isComboBoxButton")); + if (isComboBoxButton) { + if (!b.isEnabled()) { + DrawRoutines.drawRoundedBorder( + g, ThemeUtils.COMBO_BORDER_DISABLED_COLOR, x, y, w, h); + } else { + DrawRoutines.drawRoundedBorder( + g, ThemeUtils.COMBO_BORDER_COLOR, x, y, w, h); + + if (b.getModel().isPressed()){ + return; + } + } + } else { // it's a normal JButton or a JSpinner button + boolean isSpinnerButton = ComparatorUtils.equals(Boolean.TRUE,b.getClientProperty("isSpinnerButton")) ; + if (!b.isEnabled()) { + DrawRoutines.drawRoundedBorder( + g, ThemeUtils.BUTTON_BORDER_DISABLE_COLOR, x, y, w, h); + } else { + DrawRoutines.drawRoundedBorder( + g, ThemeUtils.BUTTON_BORDER_COLOR, x, y, w, h); + + if (b.getModel().isPressed()){ + return; + } + + } + } + } + + /** + * Gets the border insets for a given component. + * + * @param c The component to get its border insets. + * @return Always returns the same insets as defined in insets. + */ + public Insets getBorderInsets(Component c) { + return borderInsets; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIButtonGroup.java b/designer_base/src/com/fr/design/gui/ibutton/UIButtonGroup.java new file mode 100644 index 0000000000..f12eec0cb2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIButtonGroup.java @@ -0,0 +1,421 @@ +package com.fr.design.gui.ibutton; + +import java.awt.BorderLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.geom.RoundRectangle2D; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.border.Border; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.stable.ArrayUtils; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UIButtonGroup extends JPanel implements GlobalNameObserver { + private boolean isTwoLine = false; + private static final long serialVersionUID = 1L; + protected List labelButtonList; + protected int selectedIndex = -1; + private List objectList;// 起到一个render的作用 + private GlobalNameListener globalNameListener = null; + private String buttonGroupName = ""; + private boolean isToolBarComponent = false; + private boolean isClick; + + public UIButtonGroup(String[] textArray) { + this(textArray, null); + } + + public UIButtonGroup(Icon[] iconArray) { + this(iconArray, null); + } + + public UIButtonGroup(Icon[] iconArray, T[] objects) { + if (!ArrayUtils.isEmpty(objects) && iconArray.length == objects.length) { + this.objectList = Arrays.asList(objects); + } + labelButtonList = new ArrayList(iconArray.length); + this.setLayout(getGridLayout(iconArray.length)); + this.setBorder(getGroupBorder()); + for (int i = 0; i < iconArray.length; i++) { + final int index = i; + Icon icon = iconArray[i]; + final UIToggleButton labelButton = new UIToggleButton(icon) { + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + isClick = true; + if (!isEnabled()) { + return; + } + if (globalNameListener != null) { + globalNameListener.setGlobalName(buttonGroupName); + } + setSelectedWithFireChanged(index); + } + }; + } + + public boolean shouldResponseNameListener() { + return false; + } + }; + initButton(labelButton); + } + } + + public boolean hasClick(){ + return isClick; + } + + public void setClickState(boolean changeFlag){ + isClick = changeFlag; + } + + public void setForToolBarButtonGroup(boolean isToolBarComponent) { + this.isToolBarComponent = isToolBarComponent; + if (isToolBarComponent) { + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).set4ToolbarButton(); + } + } + repaint(); + + } + + + /** + * setEnabled + * + * @param enabled + */ + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).setEnabled(enabled); + } + } + + public UIButtonGroup(String[] textArray, T[] objects) { + if (!ArrayUtils.isEmpty(objects) && textArray.length == objects.length) { + this.objectList = Arrays.asList(objects); + } + labelButtonList = new ArrayList(textArray.length); + this.setLayout(getGridLayout(textArray.length)); + this.setBorder(getGroupBorder()); + for (int i = 0; i < textArray.length; i++) { + final int index = i; + final UIToggleButton labelButton = new UIToggleButton(textArray[i]) { + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (!isEnabled()) { + return; + } + if(globalNameListener != null) { + globalNameListener.setGlobalName(buttonGroupName); + } + setSelectedWithFireChanged(index); + } + }; + } + + @Override + public Insets getInsets() { + return new Insets(0, 2, 0, 2); + } + + public boolean shouldResponseNameListener() { + return false; + } + + }; + initButton(labelButton); + } + } + + public void setGlobalName(String name) { + buttonGroupName = name; + } + + protected void initButton(UIToggleButton labelButton) { + labelButton.setRoundBorder(false); + labelButton.setBorderPainted(false); + labelButtonList.add(labelButton); + this.add(labelButton); + } + + protected Border getGroupBorder() { + return BorderFactory.createEmptyBorder(1, 1, 1, 1); + } + + protected GridLayout getGridLayout(int number) { + return new GridLayout(0, number, 1, 0); + } + + public void setTwoLine() { + this.isTwoLine = true; + } + + /** + * paintComponent + * + * @param g + */ + public void paintComponents(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Shape oldClip = g2d.getClip(); + g2d.clip(new RoundRectangle2D.Double(1, 1, getWidth(), getHeight(), UIConstants.ARC, UIConstants.ARC)); + super.paintComponents(g); + g2d.setClip(oldClip); + } + + /** + * 重载Border画法 + * + * @param g + */ + @Override + protected void paintBorder(Graphics g) { + if(isToolBarComponent){ + return; + } + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(UIConstants.LINE_COLOR); + if (!isTwoLine) { + int width = 0; + for (int i = 0; i < labelButtonList.size() - 1; i++) { + width += labelButtonList.get(i).getWidth() + 1; + int height = labelButtonList.get(i).getHeight(); + g.drawLine(width, 0, width, height); + } + + width += labelButtonList.get(labelButtonList.size() - 1).getWidth() + 1; + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect(0, 0, width, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } else { + int width = 0; + int upCount = (labelButtonList.size() - 1) / 2 + 1; + for (int i = 0; i < upCount - 1; i++) { + width += labelButtonList.get(i).getWidth() + 1; + int height = labelButtonList.get(i).getHeight() * 2 + 1; + g.drawLine(width, 0, width, height); + } + + width += labelButtonList.get(upCount).getWidth() + 1; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect(0, 0, width, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.drawLine(0, getHeight() / 2, width, getHeight() / 2); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + } + + /** + * setSelectedItem + * + * @param ob + */ + public void setSelectedItem(T ob) { + if (objectList == null) { + setSelectedIndex(-1); + return; + } + setSelectedIndex(objectList.indexOf(ob)); + } + + /** + * getSelectedItem + * + * @return + */ + public T getSelectedItem() { + if (selectedIndex == -1) { + return null; + } + return objectList.get(selectedIndex); + } + + /** + * getSelectedIndex + * + * @return + */ + public int getSelectedIndex() { + return selectedIndex; + } + + protected void setSelectedWithFireChanged(int newSelectedIndex) { + selectedIndex = newSelectedIndex; + for (int i = 0; i < labelButtonList.size(); i++) { + if (i == selectedIndex) { + labelButtonList.get(i).setSelectedWithFireListener(true); + } else { + labelButtonList.get(i).setSelected(false); + } + } + } + + /** + * setSelectedIndex + * + * @param newSelectedIndex + */ + public void setSelectedIndex(int newSelectedIndex) { + selectedIndex = newSelectedIndex; + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).setSelected(i == selectedIndex); + } + } + + private void fireStateChanged() { + Object[] listeners = listenerList.getListenerList(); + ChangeEvent e = null; + + for (int i = 0; i < listeners.length; i++) { + if (listeners[i] == ChangeListener.class) { + if (e == null) { + e = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } + + /** + * getButton + * + * @param index + * @return + */ + public UIToggleButton getButton(int index) { + return labelButtonList.get(index); + } + + /** + * 给所有的Button添加Tips + * + * @param tips + */ + public void setAllToolTips(String[] tips) { + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).setToolTipText(tips[i]); + } + } + + + /** + * 注册全局属性名字监听器 + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 是否响应名字监听事件 + * + * @return + */ + public boolean shouldResponseNameListener() { + return true; + } + + + /** + * @param l + */ + public void addChangeListener(ChangeListener l) { + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).addChangeListener(l); + listenerList.add(ChangeListener.class, l); + } + } + + /** + * @param l + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + + /** + * @param l + */ + public void addActionListener(ActionListener l) { + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).addActionListener(l); + } + } + + + /** + * @param l + */ + public void removeActionListener(ActionListener l) { + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).removeActionListener(l); + } + } + + /** + * populate + */ + public void populateBean() { + fireStateChanged(); + } + + /** + * main + * + * @param args + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + Icon[] a1 = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), + BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png")}; + Integer[] a2 = new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT}; + UIButtonGroup bb = new UIButtonGroup(a1, a2); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + bb.setSelectedIndex(0); + bb.setEnabled(false); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIButtonUI.java b/designer_base/src/com/fr/design/gui/ibutton/UIButtonUI.java new file mode 100644 index 0000000000..6c2ae3c573 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIButtonUI.java @@ -0,0 +1,174 @@ +package com.fr.design.gui.ibutton; + +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.RenderingHints; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicButtonUI; +import javax.swing.plaf.basic.BasicHTML; +import javax.swing.text.View; + +import com.fr.design.constants.UIConstants; +import com.fr.design.roleAuthority.ReportAndFSManagePane; +import sun.swing.SwingUtilities2; + +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class UIButtonUI extends BasicButtonUI { + + private Rectangle viewRec = new Rectangle(); + private Rectangle textRec = new Rectangle(); + private Rectangle iconRec = new Rectangle(); + + @Override + public void paint(Graphics g, JComponent c) { + UIButton b = (UIButton) c; + Graphics2D g2d = (Graphics2D) g; + int w = b.getWidth(); + int h = b.getHeight(); + + String text = initRecAndGetText(b, SwingUtilities2.getFontMetrics(b, g), b.getWidth(), b.getHeight()); + String selectedRoles = ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName(); + clearTextShiftOffset(); + + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + if (b.isExtraPainted()) { + if (isPressed(b) && b.isPressedPainted()) { + GUIPaintUtils.fillPressed(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles)); + } else if (isRollOver(b)) { + GUIPaintUtils.fillRollOver(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted()); + } else if (b.isNormalPainted()) { + GUIPaintUtils.fillNormal(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted()); + } + } + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + paintContent(g, b, text); + } + + protected boolean isRollOver(AbstractButton b) { + ButtonModel model = b.getModel(); + return model.isRollover() && !b.isSelected(); + } + + protected boolean isPressed(AbstractButton b) { + ButtonModel model = b.getModel(); + return (model.isArmed() && model.isPressed()) || b.isSelected(); + } + + private void paintContent(Graphics g, AbstractButton b, String text) { + if (b.getIcon() != null) { + paintIcon(g, b); + } + if (!StringUtils.isEmpty(text)) { + paintText(g, b, text); + } + } + + private void paintText(Graphics g, AbstractButton b, String text) { + View v = (View) b.getClientProperty(BasicHTML.propertyKey); + if (v != null) { + v.paint(g, textRec); + return; + } + FontMetrics fm = SwingUtilities2.getFontMetrics(b, g); + int mnemonicIndex = b.getDisplayedMnemonicIndex(); + if (b.isEnabled()) { + g.setColor(UIConstants.FONT_COLOR); + } else { + g.setColor(UIConstants.LINE_COLOR); + } + + SwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemonicIndex, textRec.x + getTextShiftOffset(), textRec.y + fm.getAscent() + getTextShiftOffset()); + } + + private String initRecAndGetText(AbstractButton b, FontMetrics fm, int width, int height) { + Insets i = b.getInsets(); + viewRec.x = i.left; + viewRec.y = i.top; + viewRec.width = width - (i.right + viewRec.x); + viewRec.height = height - (i.bottom + viewRec.y); + textRec.x = textRec.y = textRec.width = textRec.height = 0; + iconRec.x = iconRec.y = iconRec.width = iconRec.height = 0; + // layout the text and icon + return SwingUtilities.layoutCompoundLabel( + b, fm, b.getText(), b.getIcon(), + b.getVerticalAlignment(), b.getHorizontalAlignment(), + b.getVerticalTextPosition(), b.getHorizontalTextPosition(), + viewRec, iconRec, textRec, + b.getText() == null ? 0 : b.getIconTextGap()); + } + + protected void paintBorder(Graphics g, UIButton b) { + String selectedRoles = ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName(); + GUIPaintUtils.drawBorder((Graphics2D) g, 0, 0, b.getWidth(), b.getHeight(), b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles)); + + } + + protected void paintIcon(Graphics g, JComponent c) { + AbstractButton b = (AbstractButton) c; + ButtonModel model = b.getModel(); + Icon icon = b.getIcon(); + Icon tmpIcon = null; + if (icon == null) { + return; + } + Icon selectedIcon = null; + /* the fallback icon should be based on the selected state */ + if (model.isSelected()) { + selectedIcon = (Icon) b.getSelectedIcon(); + if (selectedIcon != null) { + icon = selectedIcon; + } + } + if (!model.isEnabled()) { + if (model.isSelected()) { + tmpIcon = (Icon) b.getDisabledSelectedIcon(); + if (tmpIcon == null) { + tmpIcon = selectedIcon; + } + } + if (tmpIcon == null) { + tmpIcon = (Icon) b.getDisabledIcon(); + } + } else if (model.isPressed() && model.isArmed()) { + tmpIcon = (Icon) b.getPressedIcon(); + if (tmpIcon != null) { + // revert back to 0 offset + clearTextShiftOffset(); + } + } else if (b.isRolloverEnabled() && model.isRollover()) { + if (model.isSelected()) { + tmpIcon = (Icon) b.getRolloverSelectedIcon(); + if (tmpIcon == null) { + tmpIcon = selectedIcon; + } + } + if (tmpIcon == null) { + tmpIcon = (Icon) b.getRolloverIcon(); + } + } + if (tmpIcon != null) { + icon = tmpIcon; + } + paintModelIcon(model, icon, g, c); + } + + private void paintModelIcon(ButtonModel model, Icon icon, Graphics g, JComponent c) { + if (model.isPressed() && model.isArmed()) { + icon.paintIcon(c, g, iconRec.x + getTextShiftOffset(), + iconRec.y + getTextShiftOffset()); + } else { + icon.paintIcon(c, g, iconRec.x, iconRec.y); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIColorButton.java b/designer_base/src/com/fr/design/gui/ibutton/UIColorButton.java new file mode 100644 index 0000000000..0973fd3636 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIColorButton.java @@ -0,0 +1,250 @@ +package com.fr.design.gui.ibutton; + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +import com.fr.base.Utils; +import com.fr.design.constants.UIConstants; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ipoppane.PopupHider; +import com.fr.general.ComparatorUtils; +import com.fr.design.style.color.ColorControlWindow; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UIColorButton extends UIButton implements PopupHider, UIObserver, GlobalNameObserver { + private static final int SIZE = 16; + private static final int SIZE_2 = 2; + private static final int SIZE_4 = 4; + private static final int SIZE_6 = 6; + private Color color = Color.BLACK; + private ColorControlWindow popupWin; + private EventListenerList colorChangeListenerList = new EventListenerList(); + private boolean isEventBanned = false; + private String colorButtonName = ""; + private UIObserverListener uiObserverListener; + private GlobalNameListener globalNameListener = null; + + public UIColorButton() { + this(UIConstants.FONT_ICON); + } + + public UIColorButton(Icon icon) { + super(icon); + setUI(getButtonUI()); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + showPopupMenu(); + } + }); + iniListener(); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addColorChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(colorButtonName); + } + uiObserverListener.doChange(); + } + }); + } + } + + private UIButtonUI getButtonUI() { + return new UIButtonUI() { + @Override + protected void paintIcon(Graphics g, JComponent c) { + super.paintIcon(g, c); + AbstractButton b = (AbstractButton) c; + ButtonModel model = b.getModel(); + if (model.isEnabled()) { + g.setColor(UIColorButton.this.getColor()); + } else { + g.setColor(new Color(Utils.filterRGB(UIColorButton.this.getColor().getRGB(), 50))); + } + g.fillRect((b.getWidth() - SIZE) / SIZE_2, b.getHeight() - SIZE_6, SIZE, SIZE_4); + } + }; + } + + public void setEventBanned(boolean isEventBanned) { + this.isEventBanned = isEventBanned; + } + + public void setGlobalName(String name) { + colorButtonName = name; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + if (ComparatorUtils.equals(this.color, color)) { + return; + } + + this.color = color; + hidePopupMenu(); + fireColorStateChanged(); + } + + private void showPopupMenu() { + if (isEventBanned) { + return; + } + + if (popupWin != null && popupWin.isVisible()) { + hidePopupMenu(); + return; + } + + if (!this.isEnabled()) { + return; + } + + popupWin = this.getColorControlWindow(); + + GUICoreUtils.showPopupMenu(popupWin, this, 0, this.getSize().height); + } + + /** + * 隐藏popupmenu + */ + public void hidePopupMenu() { + if (popupWin != null) { + popupWin.setVisible(false); + repaint(); + } + + popupWin = null; + } + + private ColorControlWindow getColorControlWindow() { + //find parant. + if (this.popupWin == null) { + this.popupWin = new ColorControlWindow(UIColorButton.this) { + @Override + protected void colorChanged() { + UIColorButton.this.setColor(this.getColor()); + } + + }; + } + + return popupWin; + } + + /** + * 添加监听 + * + * @param changeListener 监听列表 + */ + public void addColorChangeListener(ChangeListener changeListener) { + colorChangeListenerList.add(ChangeListener.class, changeListener); + } + + /** + * 移除监听 + * Removes an old ColorChangeListener. + * @param changeListener 监听列表 + */ + public void removeColorChangeListener(ChangeListener changeListener) { + colorChangeListenerList.remove(ChangeListener.class, changeListener); + } + + /** + * 颜色状态改变 + */ + public void fireColorStateChanged() { + Object[] listeners = colorChangeListenerList.getListenerList(); + ChangeEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + if (e == null) { + e = new ChangeEvent(this); + } + ((ChangeListener) listeners[i + 1]).stateChanged(e); + } + } + } + + + /** + * 注册状态改变监听 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * 是否需要响应监听 + * + * @return 是否响应 + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * 注册监听 + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 是否需要相应 + * + * @return 是否响应 + */ + public boolean shouldResponseNameListener() { + return true; + } + + /** + * 主函数 + * + * @param args 参数 + */ + public static void main(String... args) { + LayoutManager layoutManager = null; + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(layoutManager); + + UIColorButton bb = new UIColorButton(UIConstants.FONT_ICON); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UICombinationButton.java b/designer_base/src/com/fr/design/gui/ibutton/UICombinationButton.java new file mode 100644 index 0000000000..cc7d0be591 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UICombinationButton.java @@ -0,0 +1,143 @@ +package com.fr.design.gui.ibutton; + +import java.awt.BorderLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.Icon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +import com.fr.design.constants.UIConstants; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UICombinationButton extends JPanel{ + protected UIButton leftButton; + protected UIButton rightButton; + + protected void leftButtonClickEvent() { + + } + + protected void rightButtonClickEvent() { + + } + + public UICombinationButton() { + this(new UIButton(), new UIButton()); + } + + public UICombinationButton(UIButton left, UIButton right) { + leftButton = left; + rightButton = right; + + leftButton.setRoundBorder(true, Constants.RIGHT); + rightButton.setRoundBorder(true, Constants.LEFT); + + leftButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + rightButton.getModel().setPressed(true); + rightButton.getModel().setSelected(true); + rightButton.repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + rightButton.getModel().setPressed(false); + rightButton.getModel().setSelected(false); + rightButton.repaint(); + } + @Override + public void mouseClicked(MouseEvent e) { + leftButtonClickEvent(); + } + }); + rightButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + leftButton.getModel().setPressed(true); + leftButton.getModel().setSelected(true); + leftButton.repaint(); + } + + @Override + public void mouseReleased(MouseEvent e) { + leftButton.getModel().setPressed(false); + leftButton.getModel().setSelected(false); + leftButton.repaint(); + } + + @Override + public void mouseClicked(MouseEvent e) { + rightButtonClickEvent(); + } + }); + + this.setLayout(new BorderLayout()); + this.add(leftButton, BorderLayout.CENTER); + this.add(rightButton, BorderLayout.EAST); + } + + public UICombinationButton(String left, Icon right) { + this(); + leftButton.setText(left); + rightButton.setIcon(right); + } + + public UICombinationButton(String left, String right) { + this(); + leftButton.setText(left); + rightButton.setText(right); + } + + public UICombinationButton(Icon left, Icon right) { + this(); + leftButton.setIcon(left); + rightButton.setIcon(right); + } + + public UIButton getLeftButton() { + return leftButton; + } + + public void setExtraPainted(boolean isExtraPainted) { + if(!isExtraPainted) { + leftButton.setBackground(null); + rightButton.setBackground(null); + leftButton.setOpaque(false); + rightButton.setOpaque(false); + } + } + + public UIButton getRightButton() { + return rightButton; + } + + public void set4Toolbar() { + leftButton.setNormalPainted(false); + rightButton.setNormalPainted(false); + leftButton.setBorderPaintedOnlyWhenPressed(true); + rightButton.setBorderPaintedOnlyWhenPressed(true); + } + + protected void showPopWindow(JPopupMenu menu) { + GUICoreUtils.showPopupMenu(menu, this, 0, getY() + getHeight() - 3); + } + + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel)jf.getContentPane(); + content.setLayout(null); + + UICombinationButton bb = new UICombinationButton("123455", UIConstants.ARROW_DOWN_ICON); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIHeadGroup.java b/designer_base/src/com/fr/design/gui/ibutton/UIHeadGroup.java new file mode 100644 index 0000000000..d772054f27 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIHeadGroup.java @@ -0,0 +1,190 @@ +package com.fr.design.gui.ibutton; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UIHeadGroup extends JPanel{ + protected List labelButtonList; + private boolean isNeedLeftRightOutLine = true; + protected int selectedIndex = -1; + + protected void tabChanged(int newSelectedIndex) { + + } + + public UIHeadGroup(String[] textArray) { + labelButtonList = new ArrayList(textArray.length); + this.setBackground(UIConstants.NORMAL_BACKGROUND); + this.setLayout(new GridLayout(0, textArray.length, 1, 0)); + this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); + for(int i = 0; i < textArray.length; i++) { + final int index = i; + String text = textArray[i]; + final UIToggleButton labelButton = new UIToggleButton(text) { + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + setSelectedIndex(index); + UIHeadGroup.this.repaint(); + } + }; + } + }; + initButton(labelButton); + } + setSelectedIndex(0); + } + + public UIHeadGroup(Icon[] iconArray) { + labelButtonList = new ArrayList(iconArray.length); + this.setBackground(UIConstants.NORMAL_BACKGROUND); + this.setLayout(new GridLayout(0, iconArray.length, 1, 0)); + this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); + for(int i = 0; i < iconArray.length; i++) { + final int index = i; + Icon icon = iconArray[i]; + final UIToggleButton labelButton = new UIToggleButton(icon) { + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + setSelectedIndex(index); + UIHeadGroup.this.repaint(); + } + }; + } + }; + initButton(labelButton); + } + setSelectedIndex(0); + } + + public UIHeadGroup(Icon[] iconArray, String[] textArray) { + labelButtonList = new ArrayList(Math.min(textArray.length, iconArray.length)); + this.setBackground(UIConstants.NORMAL_BACKGROUND); + this.setLayout(new GridLayout(0, textArray.length, 1, 0)); + this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); + for(int i = 0; i < textArray.length; i++) { + final int index = i; + String text = textArray[i]; + Icon icon = iconArray[i]; + final UIToggleButton labelButton = new UIToggleButton(text, icon) { + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + setSelectedIndex(index); + UIHeadGroup.this.repaint(); + } + }; + } + }; + initButton(labelButton); + } + setSelectedIndex(0); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = 25; + return dim; + } + + @Override + protected void paintBorder(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(UIConstants.LINE_COLOR); + + int width = 0; + for(int i = 0; i < labelButtonList.size() - 1; i++) { + int height = labelButtonList.get(i).getHeight(); + width += labelButtonList.get(i).getWidth() + 1; + g.drawLine(width, 0, width, height); + } + + width += labelButtonList.get(labelButtonList.size() - 1).getWidth() + 1; + if(isNeedLeftRightOutLine) { + g2d.drawRect(0, 0, width, getHeight() - 1); + } else { + g2d.drawLine(1, 0, width - 1, 0); + g2d.drawLine(1, getHeight() - 1, width - 1, getHeight() - 1); + } + + + g2d.setColor(UIConstants.NORMAL_BACKGROUND); + UIToggleButton headButton = labelButtonList.get(selectedIndex); + g2d.drawLine(headButton.getX(), headButton.getHeight() + 1, headButton.getX() + headButton.getWidth() - 1, headButton.getHeight() + 1); + } + + private void initButton(UIToggleButton labelButton) { + labelButton.setRoundBorder(false); + labelButton.setBorderPainted(false); + labelButton.setPressedPainted(false); + labelButtonList.add(labelButton); + this.add(labelButton); + } + + public void setSelectedIndex(int newSelectedIndex) { + selectedIndex = newSelectedIndex; + for (int i = 0; i < labelButtonList.size(); i++) { + UIToggleButton button = labelButtonList.get(i); + if(i == selectedIndex) { + button.setNormalPainted(false); + button.setOpaque(true); + button.setBackground(null); + button.setSelected(true); + } else { + button.setOpaque(false); + button.setNormalPainted(true); + button.setSelected(false); + } + } + + tabChanged(newSelectedIndex); + } + + public void setNeedLeftRightOutLine(boolean isNeedLeftRightOutLine) { + this.isNeedLeftRightOutLine = isNeedLeftRightOutLine; + } + + public int getSelectedIndex() { + return selectedIndex; + } + + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel)jf.getContentPane(); + content.setLayout(null); + Icon[] a1 = {BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_left_normal.png"), BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_center_normal.png"), + BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/h_right_normal.png")}; + UIHeadGroup bb = new UIHeadGroup(a1); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + bb.setSelectedIndex(0); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIPasswordField.java b/designer_base/src/com/fr/design/gui/ibutton/UIPasswordField.java new file mode 100644 index 0000000000..8d26b5e875 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIPasswordField.java @@ -0,0 +1 @@ +package com.fr.design.gui.ibutton; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import javax.swing.*; /** * Author : Shockway * Date: 13-10-21 * Time: 下午3:23 */ public class UIPasswordField extends JPasswordField implements UIObserver { public void registerChangeListener(UIObserverListener listener) { } public boolean shouldResponseChangeListener() { return false; } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIPreviewButton.java b/designer_base/src/com/fr/design/gui/ibutton/UIPreviewButton.java new file mode 100644 index 0000000000..a5f9de9b70 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIPreviewButton.java @@ -0,0 +1 @@ +package com.fr.design.gui.ibutton; import com.fr.design.constants.UIConstants; import com.fr.stable.Constants; import com.fr.design.utils.gui.GUICoreUtils; import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; /** * Author : daisy * Date: 13-8-1 * Time: 下午3:41 */ public class UIPreviewButton extends JPanel { private static final int START_X = -7; protected UIButton upButton; protected UIButton downButton; protected void upButtonClickEvent() { } protected void downButtonClickEvent() { } public UIPreviewButton() { this(new UIButton(), new UIButton()); } public UIPreviewButton(UIButton up, UIButton down) { upButton = up; downButton = down; upButton.setRoundBorder(true, Constants.CENTER); downButton.setRoundBorder(true, Constants.CENTER); upButton.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { downButton.getModel().setPressed(true); downButton.getModel().setSelected(true); downButton.repaint(); } @Override public void mouseReleased(MouseEvent e) { downButton.getModel().setPressed(false); downButton.getModel().setSelected(false); downButton.repaint(); } @Override public void mouseClicked(MouseEvent e) { upButtonClickEvent(); } }); downButton.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { upButton.getModel().setPressed(true); upButton.getModel().setSelected(true); upButton.repaint(); } @Override public void mouseReleased(MouseEvent e) { upButton.getModel().setPressed(false); upButton.getModel().setSelected(false); upButton.repaint(); } @Override public void mouseClicked(MouseEvent e) { downButtonClickEvent(); } }); this.setLayout(new FlowLayout(FlowLayout.CENTER,5,0)); this.add(upButton); this.add(downButton); } public UIPreviewButton(Icon left, Icon right) { this(); upButton.setIcon(left); downButton.setIcon(right); } public UIButton getUpButton() { return upButton; } public void setExtraPainted(boolean isExtraPainted) { if (!isExtraPainted) { upButton.setBackground(null); downButton.setBackground(null); upButton.setOpaque(false); downButton.setOpaque(false); } } public UIButton getDownButton() { return downButton; } public void set4Toolbar() { upButton.setNormalPainted(false); downButton.setNormalPainted(false); upButton.setBorderPaintedOnlyWhenPressed(true); downButton.setBorderPaintedOnlyWhenPressed(true); } protected void showPopWindow(JPopupMenu menu) { GUICoreUtils.showPopupMenu(menu, this, START_X, getY() + getHeight() - 3); } public static void main(String... args) { JFrame jf = new JFrame("test"); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel content = (JPanel) jf.getContentPane(); content.setLayout(null); UIPreviewButton bb = new UIPreviewButton(UIConstants.PAGE_BIG_ICON, UIConstants.PREVIEW_DOWN); bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); content.add(bb); GUICoreUtils.centerWindow(jf); jf.setSize(100, 100); jf.setVisible(true); } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIRadioButton.java b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButton.java new file mode 100644 index 0000000000..40a0b8e8a2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButton.java @@ -0,0 +1,48 @@ +package com.fr.design.gui.ibutton; + +import javax.swing.*; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-3-27 + * Time: 下午5:04 + */ +public class UIRadioButton extends JRadioButton { + + public UIRadioButton() { + super(); + } + + public UIRadioButton(Icon icon) { + super(icon); + } + + public UIRadioButton(Action a) { + super(a); + } + + public UIRadioButton(Icon icon, boolean selected) { + super(icon, selected); + } + + public UIRadioButton(String text) { + super(text); + } + + public UIRadioButton(String text, boolean selected) { + super(text, selected); + } + + public UIRadioButton(String text, Icon icon) { + super(text, icon); + } + + + public UIRadioButton(String text, Icon icon, boolean selected) { + super(text, icon, selected); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonIcon.java b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonIcon.java new file mode 100644 index 0000000000..14c78c76f8 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonIcon.java @@ -0,0 +1,328 @@ +package com.fr.design.gui.ibutton; + +import com.fr.design.gui.icheckbox.UICheckBoxIcon; +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ThemeUtils; +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.DrawRoutines; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-13 + * Time: 下午2:52 + */ +public class UIRadioButtonIcon extends UICheckBoxIcon { + private static HashMap cache = new HashMap(); + + private static final int[][] A = { + {255, 255, 255, 242, 228, 209, 187, 165, 142, 255, 255}, + {255, 255, 242, 228, 209, 187, 165, 142, 120, 104, 255}, + {255, 242, 228, 209, 187, 165, 142, 120, 104, 86, 72}, + {242, 228, 209, 187, 165, 142, 120, 104, 86, 72, 56}, + {228, 209, 187, 165, 142, 120, 104, 86, 72, 56, 42}, + {209, 187, 165, 142, 120, 104, 86, 72, 56, 42, 28}, + {187, 165, 142, 120, 104, 86, 72, 56, 42, 28, 17}, + {165, 142, 120, 104, 86, 72, 56, 42, 28, 17, 9}, + {142, 120, 104, 86, 72, 56, 42, 28, 17, 9, 0}, + {255, 104, 86, 72, 56, 42, 28, 17, 9, 0, 255}, + {255, 255, 72, 56, 42, 28, 17, 9, 0, 255, 255} + }; + + /** + * Draws the check box icon at the specified location. + * + * @param c The component to draw on. + * @param g The graphics context. + * @param x The x coordinate of the top left corner. + * @param y The y coordinate of the top left corner. + */ + public void paintIcon(Component c, Graphics g, int x, int y) { + AbstractButton button = (AbstractButton) c; + + // inner space + Color col = null; + + if (!button.isEnabled()) { + col = ThemeUtils.BUTTON_DISABLE_COLOR; + } else if (button.getModel().isPressed()) { + if (button.getModel().isRollover() || button.getModel().isArmed()) { + col = ThemeUtils.BUTTON_PRESS_COLOR; + } else { + col = ThemeUtils.BUTTON_NORMAL_COLOR; + } + } else if (button.getModel().isRollover() && ThemeUtils.BUTTON_ROLLOVER) { + col = ThemeUtils.BUTTON_ROLLOVER_BG_COLOR; + } else { + col = ThemeUtils.BUTTON_NORMAL_COLOR; + } + + g.setColor(col); + drawXpRadio(g, button, col, x, y, getIconWidth(), getIconHeight()); + + // checkmark + if (!button.isSelected()) { + return; + } + + if (!button.isEnabled()) { + col = ThemeUtils.BUTTON_CHECK_DISABLE_COLOR; + } else { + col = ThemeUtils.RADIO_CHECK_ROLLOVER_COLOR; + } + g.setColor(col); + drawXpCheckMark(g, col, x, y); + } + + + private void drawXpRadio(Graphics g, AbstractButton b, Color c, + int x, int y, int w, int h) { + boolean pressed = b.getModel().isPressed(); + boolean armed = b.getModel().isArmed(); + boolean enabled = b.isEnabled(); + boolean rollover = b.getModel().isRollover(); + boolean focused = (ThemeUtils.BUTTON_FOCUS_BORDER && !rollover && b.isFocusOwner()); + + Color bg = b.getBackground(); + + if (!b.isOpaque()) { + Container parent = b.getParent(); + bg = parent.getBackground(); + + while (parent != null && !parent.isOpaque()) { + parent = parent.getParent(); + bg = parent.getBackground(); + } + } + + RadioKey key = new RadioKey(c, bg, pressed, enabled, (rollover || armed), focused); + Object value = cache.get(key); + + if (value != null) { + // image already cached - paint image and return + g.drawImage((Image) value, x, y, b); + return; + } + + Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + + drawcalculate(img,bg,w,h,enabled, pressed ,armed,rollover,c,focused); + // draw the image + g.drawImage(img, x, y, b); + + // add the image to the cache + cache.put(key, img); + } + + private void drawcalculate(Image img, Color bg, int w, int h, boolean enabled, + boolean pressed, boolean armed, boolean rollover, Color c,boolean focused ) { + Graphics imgGraphics = img.getGraphics(); + imgGraphics.setColor(bg); + imgGraphics.fillRect(0, 0, w, h); + // spread light is between 0 and 20 + int spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT; + int spread2 = ThemeUtils.BUTTON_SPREAD_DARK; + if (!enabled) { + spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT_DISABLE; + spread2 = ThemeUtils.BUTTON_SPREAD_DARK_DISABLE; + } + int spreadStep1 = spread1 * 5; // 20 -> 100 + int spreadStep2 = spread2 * 4; // 20 -> 80 + boolean isRollverOrArmed = rollover||armed; + if (pressed && isRollverOrArmed) { + spreadStep2 *= 2; + } + c = ColorRoutines.lighten(c, spreadStep1); + imgGraphics.setColor(ColorRoutines.darken(c, spreadStep2)); + imgGraphics.fillRect(2, 2, w - 4, h - 4); + imgGraphics.fillRect(1, 5, 1, 3); + imgGraphics.fillRect(11, 5, 1, 3); + imgGraphics.fillRect(5, 1, 3, 1); + imgGraphics.fillRect(5, 11, 3, 1); + Color color; + for (int row = 0; row < 11; row++) { + for (int col = 0; col < 11; col++) { + color = new Color(c.getRed(), c.getGreen(), c.getBlue(), 255 - A[col][row]); + imgGraphics.setColor(color); + imgGraphics.drawLine(col + 1, row + 1, col + 1, row + 1); + } + } + if (!enabled) { + DrawRoutines.drawXpRadioBorder(imgGraphics, + ThemeUtils.BUTTON_BORDER_DISABLE_COLOR, 0, 0, w, h); + } else { + if (rollover && ThemeUtils.BUTTON_ROLLOVER && !pressed) { + DrawRoutines.drawXpRadioBorder(imgGraphics, + ThemeUtils.RADIO_CHECK_ROLLOVER_COLOR, 0, 0, w, h); + } else if (focused && !pressed) { + DrawRoutines.drawXpRadioBorder(imgGraphics, + ThemeUtils.RADIO_BORDER_NORMAL_COLOR, 0, 0, w, h); + } + + DrawRoutines.drawXpRadioBorder(imgGraphics, + ThemeUtils.RADIO_BORDER_NORMAL_COLOR, 0, 0, w, h); + } + // dispose of image graphics + imgGraphics.dispose(); + } + + + private void drawXpCheckMark(Graphics g, Color c, int x, int y) { + g.translate(x, y); + + g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 224)); + g.fillRect(5, 5, 3, 3); + + g.setColor(c); + g.drawLine(6, 6, 6, 6); + + g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 192)); + g.drawLine(6, 4, 6, 4); + g.drawLine(4, 6, 4, 6); + g.drawLine(8, 6, 8, 6); + g.drawLine(6, 8, 6, 8); + + g.setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), 128)); + g.drawLine(5, 4, 5, 4); + g.drawLine(7, 4, 7, 4); + g.drawLine(4, 5, 4, 5); + g.drawLine(8, 5, 8, 5); + g.drawLine(4, 7, 4, 7); + g.drawLine(8, 7, 8, 7); + g.drawLine(5, 8, 5, 8); + g.drawLine(7, 8, 7, 8); + + g.translate(-x, -y); + } + + /* + * EnabledRadioKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + * Used only if we are run from ControlPanel. + */ + static class EnabledRadioKey { + int spread1; + int spread2; + Color c, back; + + EnabledRadioKey(Color c, Color back) { + spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT; + spread2 = ThemeUtils.BUTTON_SPREAD_DARK; + this.c = c; + this.back = back; + } + + public boolean equals(Object o) { + if (o == null){ + return false; + } + if (!(o instanceof UICheckBoxIcon.EnabledCheckKey)) { + return false; + } + + UICheckBoxIcon.EnabledCheckKey other = (UICheckBoxIcon.EnabledCheckKey) o; + + return ComparatorUtils.equals(c,other.c) && + ComparatorUtils.equals(back,other.back) && + ComparatorUtils.equals(spread1,other.spread1) && + ComparatorUtils.equals(spread2,other.spread2); + } + + public int hashCode() { + return c.hashCode() * back.hashCode() * spread1 * spread2; + } + } + + /* + * DisabledRadioKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + * Used only if we are run from ControlPanel. + */ + static class DisabledRadioKey { + int spread1; + int spread2; + Color c, back; + + DisabledRadioKey(Color c, Color back) { + spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT_DISABLE; + spread2 = ThemeUtils.BUTTON_SPREAD_DARK_DISABLE; + this.c = c; + this.back = back; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof UICheckBoxIcon.DisabledCheckKey)) { + return false; + } + + UICheckBoxIcon.DisabledCheckKey other = (UICheckBoxIcon.DisabledCheckKey) o; + + return ComparatorUtils.equals(c,other.c) && + ComparatorUtils.equals(back,other.back) && + ComparatorUtils.equals(spread1,other.spread1) && + ComparatorUtils.equals(spread2,other.spread2); + } + + public int hashCode() { + return c.hashCode() * back.hashCode() * spread1 * spread2; + } + } + + /* + * RadioKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + */ + static class RadioKey { + + private Color c, background; + private boolean pressed; + private boolean enabled; + private boolean rollover; + private boolean focused; + + RadioKey(Color c, Color background, + boolean pressed, boolean enabled, boolean rollover, boolean focused) { + this.c = c; + this.background = background; + this.pressed = pressed; + this.enabled = enabled; + this.rollover = rollover; + this.focused = focused; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof RadioKey)){ + return false; + } + + RadioKey other = (RadioKey) o; + + return ComparatorUtils.equals(c,other.c) && + ComparatorUtils.equals(pressed,other.pressed) && + ComparatorUtils.equals(enabled,other.enabled) && + ComparatorUtils.equals(rollover,other.rollover)&& + ComparatorUtils.equals(focused,other.focused)&& + ComparatorUtils.equals(background,other.background); + } + + public int hashCode() { + return c.hashCode() * + background.hashCode() * + (pressed ? 1 : 2) * + (enabled ? 4 : 8) * + (rollover ? 16 : 32); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonMenuItemUI.java b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonMenuItemUI.java new file mode 100644 index 0000000000..402779d665 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonMenuItemUI.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ibutton; + +import com.fr.design.gui.imenu.UIBasicMenuItemUI; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import java.awt.*; +import java.awt.event.MouseEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-6 + * Time: 下午4:12 + */ +public class UIRadioButtonMenuItemUI extends UIBasicMenuItemUI { + + /** + * 创建UI + * + * @param b 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent b) { + return new UIRadioButtonMenuItemUI(); + } + + protected String getPropertyPrefix() { + return "RadioButtonMenuItem"; + } + + /** + * 鼠标点击事件 + * + * @param item 菜单项 + * @param e 鼠标事件 + * @param path 菜单元素路径 + * @param manager 鼠标选择manager + */ + public void processMouseEvent(JMenuItem item, MouseEvent e, + MenuElement path[], MenuSelectionManager manager) { + Point p = e.getPoint(); + boolean isContainsX = p.x >= 0 && p.x < item.getWidth(); + boolean isContainsY = p.y >= 0 && p.y < item.getHeight(); + if (isContainsX && isContainsY) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + manager.clearSelectedPath(); + item.doClick(0); + item.setArmed(false); + } else + manager.setSelectedPath(path); + } else if (item.getModel().isArmed()) { + MenuElement[] newPath = new MenuElement[path.length - 1]; + int i, c; + for (i = 0, c = path.length - 1; i < c; i++){ + newPath[i] = path[i]; + } + manager.setSelectedPath(newPath); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonUI.java b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonUI.java new file mode 100644 index 0000000000..8fed217d35 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIRadioButtonUI.java @@ -0,0 +1,112 @@ +package com.fr.design.gui.ibutton; + + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalRadioButtonUI; +import java.awt.*; +import java.awt.event.KeyEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-13 + * Time: 下午2:50 + */ +public class UIRadioButtonUI extends MetalRadioButtonUI { + + Component c; + + /** + * the only instance of the radiobuttonUI + */ + private static final UIRadioButtonUI RADIO_BUTTON_UI = new UIRadioButtonUI(); + + /* the only instance of the stroke for the focus */ + private static BasicStroke focusStroke = + new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, + 1.0f, new float[]{1.0f, 1.0f}, 0.0f); + + /* the only instance of the radiobutton icon*/ + private static UIRadioButtonIcon radioButton; + + /** + * 创建UI + * @param c 组件 + * @return 返回本类对象 + */ + public static ComponentUI createUI(JComponent c) { + if (c instanceof JRadioButton) { + JRadioButton jb = (JRadioButton) c; + jb.setRolloverEnabled(true); + } + + return RADIO_BUTTON_UI; + } + + /** + * 为该组件加载图标 + * @param c 组件对象 + */ + public void installUI(JComponent c) { + super.installUI(c); + + icon = getRadioButton(); + + if (!ThemeUtils.BUTTON_ENTER) { + return; + } + if (!c.isFocusable()){ + return; + } + + InputMap km = (InputMap) UIManager.get(getPropertyPrefix() + "focusInputMap"); + + if (km != null) { + km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "pressed"); + km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "released"); + } + } + + /** + * Returns the skinned Icon + * + * @return TinyRadioButtonIcon + */ + protected UIRadioButtonIcon getRadioButton() { + if (radioButton == null) { + radioButton = new UIRadioButtonIcon(); + } + + return radioButton; + } + + + /** + * Paints the focus for the radiobutton + * + * @see javax.swing.plaf.metal.MetalRadioButtonUI#paintFocus(java.awt.Graphics, java.awt.Rectangle, java.awt.Dimension) + */ + protected void paintFocus(Graphics g, Rectangle t, Dimension arg2) { + if (!ThemeUtils.BUTTON_FOCUS){ + return; + } + + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(Color.black); + g2d.setStroke(focusStroke); + + int x1 = t.x - 1; + int y1 = t.y - 1; + int x2 = x1 + t.width + 1; + int y2 = y1 + t.height + 1; + + g2d.drawLine(x1, y1, x2, y1); + g2d.drawLine(x1, y1, x1, y2); + g2d.drawLine(x1, y2, x2, y2); + g2d.drawLine(x2, y1, x2, y2); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UITabButton.java b/designer_base/src/com/fr/design/gui/ibutton/UITabButton.java new file mode 100644 index 0000000000..fe4bd72756 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UITabButton.java @@ -0,0 +1,181 @@ +package com.fr.design.gui.ibutton; + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.Icon; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.design.gui.core.UISelectedComponent; + +/** + * SelectedAble button label + * + * @author zhou + * @since 2012-5-11下午4:28:24 + */ +public class UITabButton extends UILabel implements UISelectedComponent { + /** + * + */ + private static final long serialVersionUID = 1L; + public static final Color TOP = new Color(200, 200, 200); + public static final Color DOWN = new Color(242, 242, 242); + + protected boolean isSelected = false; + + protected boolean isRollover; + + public UITabButton(Icon image) { + super(image); + this.setHorizontalAlignment(SwingConstants.CENTER); + this.setVerticalAlignment(SwingConstants.CENTER); + this.addMouseListener(getMouseListener()); + this.setFocusable(true); + } + + public UITabButton(String text) { + super(text); + this.setHorizontalAlignment(SwingConstants.CENTER); + this.setVerticalAlignment(SwingConstants.CENTER); + this.addMouseListener(getMouseListener()); + } + + @Override + public boolean isSelected() { + return isSelected; + } + + /** + * 能触发事件 + * + * @param isSelected + */ + + @Override + public void setSelected(boolean isSelected) { + if (this.isSelected != isSelected) { + this.isSelected = isSelected; + fireSelectedChanged(); + this.repaint(); + } + } + + /** + * 不触发事件 + * + * @param isSelected + */ + public void setSelectedDoNotFireListener(boolean isSelected) { + if (this.isSelected != isSelected) { + this.isSelected = isSelected; + this.repaint(); + } + } + + /** + * Adds a ChangeListener to the listener list. + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + * removes a ChangeListener from the listener list. + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + // august: Process the listeners last to first + protected void fireSelectedChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener)listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + /** + * + * @return + */ + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + if (!isSelected()) { + isRollover = true; + repaint(); + } + } + + @Override + public void mouseExited(MouseEvent e) { + isRollover = false; + repaint(); + } + + @Override + public void mousePressed(MouseEvent e) { + UITabButton.this.requestFocus(); + mousePressedTrigger(); + } + }; + } + + protected void mousePressedTrigger() { + setSelected(true); + } + + @Override + public void paint(Graphics g) { + int w = this.getWidth(); + int h = this.getHeight(); + Graphics2D g2d = (Graphics2D)g; + paintRolloverAndSelected(g2d, w, h); + paintOther(g2d, w, h); + super.paint(g); + } + + protected void paintRolloverAndSelected(Graphics2D g2d, int w, int h) { + if (isSelected()) { + Color darkColor = UIConstants.GRDIENT_DARK_GRAY; + Color lightColor = UIConstants.PRESSED_DARK_GRAY; + GradientPaint gp = new GradientPaint(1, 1, darkColor, 1, 5, lightColor); + g2d.setPaint(gp); + g2d.fillRect(0, 0, w - 1, h); + this.setForeground(Color.white); + } else if (!isSelected() && isRollover) { + Color blue = UIConstants.LIGHT_BLUE; + g2d.setColor(blue); + g2d.fillRect(0, 1, w - 1, h / 2); + GradientPaint gp = new GradientPaint(1, 1, UIConstants.OCEAN_BLUE, 1, h - 1, blue); + g2d.setPaint(gp); + g2d.fillRect(0, h / 2, w - 1, h / 2); + this.setForeground(UIConstants.FONT_COLOR); + } else if (!isSelected() && !isRollover) { + GradientPaint gp = new GradientPaint(1, 1, TOP, 1, h - 1, DOWN); + g2d.setPaint(gp); + g2d.fillRect(0, h / 2, w - 1, h / 2); + this.setForeground(UIConstants.FONT_COLOR); + } + } + + protected void paintOther(Graphics2D g2d, int w, int h) { + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UITabGroup.java b/designer_base/src/com/fr/design/gui/ibutton/UITabGroup.java new file mode 100644 index 0000000000..7f6ec850a2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UITabGroup.java @@ -0,0 +1,154 @@ +package com.fr.design.gui.ibutton; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.RenderingHints; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.border.Border; + +import com.fr.design.constants.UIConstants; + +public class UITabGroup extends UIButtonGroup { + private boolean isOneLineTab = false; + private static final int BUTTON_NUMBER = 5; + private static final int SEVEN_NUMBER = 7; + private static final int ORIGINAL_WIDTH = 10; + private static final int GAP = 11; + + /** + * 标签页改变 + * + * @param index 序号 + */ + public void tabChanged(int index) { + + } + + public UITabGroup(Icon[] iconArray) { + super(iconArray, new Integer[iconArray.length]); + setSelectedIndex(0); + tabChanged(0); + } + + public UITabGroup(String[] textArray) { + super(textArray); + } + + @Override + protected GridLayout getGridLayout(int number) { + if (number < BUTTON_NUMBER || isOneLineTab) { + return super.getGridLayout(number); + } else if (number == BUTTON_NUMBER || number == SEVEN_NUMBER) { + return new FiveButtonLayout(); + } else { + return new GridLayout(2, 3, 1, 1); + } + } + + @Override + protected void paintBorder(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(UIConstants.LINE_COLOR); + if (!isTwoLine()) { + int width = isDrawLine() ? ORIGINAL_WIDTH : 0; + for (int i = 0; i < labelButtonList.size() - 1; i++) { + width += labelButtonList.get(i).getWidth() + 1; + int height = labelButtonList.get(i).getHeight(); + g.drawLine(width, 0, width, height); + } + + width += labelButtonList.get(labelButtonList.size() - 1).getWidth() + 1; + if (isDrawLine()) { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect(ORIGINAL_WIDTH, 0, width - ORIGINAL_WIDTH, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } else { + g2d.drawRect(0, 0, width, getHeight() - 1); + } + + } else if (labelButtonList.size() % 2 != 0) { + paintOddNumberButtons(g, g2d); + } else { + int width = ORIGINAL_WIDTH; + int number = labelButtonList.size() / 2; + for (int i = 0; i < number - 1; i++) { + width += labelButtonList.get(i).getWidth() + 1; + int height = labelButtonList.get(i).getHeight() * 2 + 1; + g.drawLine(width, 0, width, height); + } + width += labelButtonList.get(number - 1).getWidth() + 1; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect(ORIGINAL_WIDTH, 0, width - ORIGINAL_WIDTH, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + } + if (isDrawLine()) { + g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2); + } + } + + private void paintOddNumberButtons(Graphics g, Graphics2D g2d) { + int width = ORIGINAL_WIDTH; + int buttonHeight = labelButtonList.get(0).getHeight(); + int upButtonCount = labelButtonList.size() / 2 + 1; + for (int i = 0; i < upButtonCount - 1; i++) { + width += labelButtonList.get(i).getWidth() + 1; + int height = labelButtonList.get(i).getHeight() + 1; + g.drawLine(width, 0, width, height); + } + width += labelButtonList.get(upButtonCount - 1).getWidth() + 1; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect(ORIGINAL_WIDTH, 0, width - ORIGINAL_WIDTH, buttonHeight + 1, UIConstants.ARC, UIConstants.ARC); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + int line2X = labelButtonList.get(upButtonCount).getX(); + int line2Y = labelButtonList.get(upButtonCount).getY(); + width = line2X; + width += labelButtonList.get(upButtonCount).getWidth(); + int height = labelButtonList.get(upButtonCount).getHeight() + 1; + g.drawLine(width, line2Y, width, line2Y + height); + for (int i = upButtonCount + 1; i < labelButtonList.size() - 1; i++) { + width += labelButtonList.get(i).getWidth() + 1; + height = labelButtonList.get(i).getHeight() + 1; + g.drawLine(width, line2Y, width, line2Y + height); + } + width += labelButtonList.get(upButtonCount).getWidth() + 1; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.drawRoundRect(line2X - 1, line2Y, width - line2X + 1, buttonHeight, UIConstants.ARC, UIConstants.ARC); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + } + + protected boolean isTwoLine() { + return labelButtonList.size() >= BUTTON_NUMBER && !isOneLineTab; + } + + public void setOneLineTab(boolean isOneLineTab) { + this.isOneLineTab = isOneLineTab; + } + + protected boolean isDrawLine() { + return true; + } + + @Override + protected Border getGroupBorder() { + if (!isDrawLine()) { + return BorderFactory.createEmptyBorder(1, 1, 1, 1); + } + return BorderFactory.createEmptyBorder(1, GAP, 1, GAP); + } + + @Override + protected void setSelectedWithFireChanged(int newSelectedIndex) { + if (selectedIndex != newSelectedIndex) { + selectedIndex = newSelectedIndex; + for (int i = 0; i < labelButtonList.size(); i++) { + labelButtonList.get(i).setSelected(i == selectedIndex); + } + } + tabChanged(newSelectedIndex); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIToggleButton.java b/designer_base/src/com/fr/design/gui/ibutton/UIToggleButton.java new file mode 100644 index 0000000000..0a766e2e91 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIToggleButton.java @@ -0,0 +1,176 @@ +package com.fr.design.gui.ibutton; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.Icon; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.design.constants.UIConstants; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.stable.StringUtils; + +/** + * SelectedAble button label + * + * @author zhou + * @since 2012-5-11下午4:28:24 + */ +public class UIToggleButton extends UIButton implements GlobalNameObserver{ + private boolean isSelected; + private boolean isEventBannded = false; + private String toggleButtonName = ""; + private GlobalNameListener globalNameListener = null; + + public UIToggleButton() { + this(StringUtils.EMPTY); + } + + public UIToggleButton(Icon image) { + this(StringUtils.EMPTY, image); + } + + public UIToggleButton(String text) { + this(text, null); + } + + public UIToggleButton(String text, Icon image) { + super(text, image); + addMouseListener(getMouseListener()); + } + + public void setGlobalName(String name){ + toggleButtonName = name ; + } + + /** + * + * @return + */ + public boolean isSelected() { + return isSelected; + } + + /** + * 能触发事件 + * + * @param isSelected + */ + + @Override + public void setSelected(boolean isSelected) { + if (this.isSelected != isSelected) { + this.isSelected = isSelected; + repaint(); + } + } + protected void initListener(){ + if(shouldResponseChangeListener()){ + this.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + if(globalNameListener!=null && shouldResponseNameListener()){ + globalNameListener.setGlobalName(toggleButtonName); + } + uiObserverListener.doChange(); + } + }); + } + } + + public void setSelectedWithFireListener(boolean isSelected) { + if (this.isSelected != isSelected) { + this.isSelected = isSelected; + fireSelectedChanged(); + repaint(); + } + } + + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (isEnabled() && !isEventBannded) { + setSelectedWithFireListener(!isSelected()); + } + } + }; + } + + public void setEventBannded(boolean ban) { + this.isEventBannded = ban; + } + + protected void fireStateChanged() { + + } + + + protected void fireSelectedChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + @Override + protected void paintBorder(Graphics g) { + if (!isBorderPainted()) { + return; + } + boolean isBorderPainted = isBorderPaintedOnlyWhenPressed && (getModel().isPressed() || isSelected); + if (isBorderPainted || !isBorderPaintedOnlyWhenPressed) { + if (ui instanceof UIButtonUI) { + ((UIButtonUI) ui).paintBorder(g, this); + } else { + super.paintBorder(g); + } + } + } + + protected void paintOtherBorder(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setStroke(UIConstants.BS); + Shape shape = new RoundRectangle2D.Float(0.5f, 0.5f, getWidth() - 1, getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + g2d.setColor(UIConstants.LINE_COLOR); + g2d.draw(shape); + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * + * @return + */ + public boolean shouldResponseNameListener() { + return true; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ibutton/UIToolButtonBorder.java b/designer_base/src/com/fr/design/gui/ibutton/UIToolButtonBorder.java new file mode 100644 index 0000000000..f854ffac3f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ibutton/UIToolButtonBorder.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ibutton; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-19 + * Time: 下午4:39 + */ +public class UIToolButtonBorder extends AbstractBorder { + protected final Insets insets = new Insets(1, 1, 1, 1); + + /** + * Draws the button border for the given component. + * + * @param c The component to draw its border. + * @param g The graphics context. + * @param x The x coordinate of the top left corner. + * @param y The y coordinate of the top left corner. + * @param w The width. + * @param h The height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + AbstractButton b = (AbstractButton) c; + Color col = null; + + boolean isFileChooserButton =ComparatorUtils.equals(Boolean.TRUE, b.getClientProperty("JFileChooser.isFileChooserButton")); + + // New in 1.3.7 (previously only b.getModel().isRollover() evaluated) + boolean isRollover = b.getModel().isRollover() || b.getModel().isArmed(); + + if (b.getModel().isPressed()) { + if (isRollover) { + col = ThemeUtils.TOOL_BORDER_PRESSED_COLOR; + } else { + if (b.isSelected()) { + col = ThemeUtils.TOOL_BORDER_SELECTED_COLOR; + } else { + if (isFileChooserButton) { + return; // no border painted + } + + col = ThemeUtils.TOOL_BORDER_COLOR; + return; + } + } + } else if (isRollover) { + if (b.isSelected()) { + col = ThemeUtils.TOOL_BORDER_SELECTED_COLOR; + } else { + col = ThemeUtils.TOOL_BORDER_ROLLOVER_COLOR; + } + } else if (b.isSelected()) { + col = ThemeUtils.TOOL_BORDER_SELECTED_COLOR; + } else { + if (isFileChooserButton) { + return; // no border painted + } + + col = ThemeUtils.TOOL_BORDER_COLOR; + return; + } + DrawRoutines.drawRoundedBorder(g, col, x, y, w, h); + } + + /** + * Gets the border insets for a given component. + * + * @return some insets... + */ + public Insets getBorderInsets(Component c) { + if (!(c instanceof AbstractButton)){ + return insets; + } + + AbstractButton b = (AbstractButton) c; + + if (b.getMargin() == null || (b.getMargin() instanceof UIResource)) { + return new Insets(ThemeUtils.TOOL_MARGIN_TOP, ThemeUtils.TOOL_MARGIN_LEFT, + ThemeUtils.TOOL_MARGIN_BOTTOM, ThemeUtils.TOOL_MARGIN_RIGHT); + } else { + Insets margin = b.getMargin(); + + return new Insets( + margin.top + 1, + margin.left + 1, + margin.bottom + 1, + margin.right + 1); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icheckbox/UICheckBox.java b/designer_base/src/com/fr/design/gui/icheckbox/UICheckBox.java new file mode 100644 index 0000000000..08a387f0f2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icheckbox/UICheckBox.java @@ -0,0 +1,201 @@ +package com.fr.design.gui.icheckbox; + +import com.fr.design.constants.UIConstants; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.design.utils.gui.GUIPaintUtils; +import com.fr.stable.Constants; +import sun.swing.SwingUtilities2; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicHTML; +import javax.swing.plaf.metal.MetalCheckBoxUI; +import javax.swing.text.View; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObserver { + private UIObserverListener uiObserverListener; + private GlobalNameListener globalNameListener = null; + private String checkboxName = ""; + + public UICheckBox(String string) { + super(string); + setUI(new UICheckBoxUI()); + initListener(); + } + + public UICheckBox() { + super(); + setUI(new UICheckBoxUI()); + initListener(); + } + + public UICheckBox(String locText, boolean b) { + super(locText, b); + setUI(new UICheckBoxUI()); + initListener(); + } + + public UICheckBox(String text, Icon icon) { + super(text, icon); + setUI(new UICheckBoxUI()); + initListener(); + } + + private void initListener() { + if (shouldResponseChangeListener()) { + this.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + if (uiObserverListener == null) { + return; + } + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(checkboxName); + } + uiObserverListener.doChange(); + } + }); + } + } + + /** + * 给组件登记一个观察者监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + this.uiObserverListener = listener; + } + + + public void setGlobalName(String name) { + checkboxName = name; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * 注册观察者监听事件 + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 组件是否需要响应观察者事件 + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseNameListener() { + return true; + } + + private class UICheckBoxUI extends MetalCheckBoxUI { + public void paint(Graphics g, JComponent c) { + synchronized (this) { + AbstractButton b = (AbstractButton) c; + ButtonModel model = b.getModel(); + Dimension size = c.getSize(); + Font f = c.getFont(); + g.setFont(f); + FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f); + + Rectangle viewRect = new Rectangle(size); + Rectangle iconRect = new Rectangle(); + Rectangle textRect = new Rectangle(); + + Insets i = c.getInsets(); + viewRect.x += i.left; + viewRect.y += i.top; + viewRect.width -= (i.right + viewRect.x); + viewRect.height -= (i.bottom + viewRect.y); + + Icon altIcon = b.getIcon(); + + String text = SwingUtilities.layoutCompoundLabel( + c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(), + b.getVerticalAlignment(), b.getHorizontalAlignment(), + b.getVerticalTextPosition(), b.getHorizontalTextPosition(), + viewRect, iconRect, textRect, b.getIconTextGap()); + + // fill background + if (c.isOpaque()) { + g.setColor(b.getBackground()); + g.fillRect(0, 0, size.width, size.height); + } + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + if ( model.isSelected()) { + GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height,false, Constants.NULL,UIConstants.CHECKBOX_HOVER_SELECTED, 0); + } else if (model.isRollover() && ! model.isSelected()) { + g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED); + g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); + }else{ + g.setColor(UIConstants.LINE_COLOR); + g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); + } + + if (model.isSelected()) { + UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2); + } + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + // Draw the Text + drawLine(text, g, b, c, textRect, fm); + } + } + + private void drawLine(String text, Graphics g, AbstractButton b, JComponent c, Rectangle textRect, FontMetrics fm) { + if (text != null) { + View v = (View) c.getClientProperty(BasicHTML.propertyKey); + if (v != null) { + v.paint(g, textRect); + } else { + int mnemIndex = b.getDisplayedMnemonicIndex(); + if (model.isEnabled()) { + g.setColor(b.getForeground()); + } else { + g.setColor(getDisabledTextColor()); + } + SwingUtilities2.drawStringUnderlineCharAt(c, g, text, + mnemIndex, textRect.x, textRect.y + fm.getAscent()); + } + } + } + + } + + /** + * 测试 + * @param args 参数 + */ + public static void main(String... args) { + LayoutManager layoutManager = null; + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(layoutManager); + + UICheckBox bb = new UICheckBox("sdf"); + bb.setEnabled(false); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxIcon.java b/designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxIcon.java new file mode 100644 index 0000000000..1868e04fee --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxIcon.java @@ -0,0 +1,314 @@ +package com.fr.design.gui.icheckbox; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ThemeUtils; +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.DrawRoutines; + +import javax.swing.*; +import javax.swing.plaf.metal.MetalCheckBoxIcon; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-13 + * Time: 下午2:53 + */ +public class UICheckBoxIcon extends MetalCheckBoxIcon { + + // cache for already drawn icons - speeds up drawing by A factor + // of up to 100 if there are several check boxes or one check box + // is painted several times + + + private static HashMap cache = new HashMap(); + + private static final int[][] A = { + {255, 255, 255, 242, 228, 209, 187, 165, 142, 120, 104}, + {255, 255, 242, 228, 209, 187, 165, 142, 120, 104, 86}, + {255, 242, 228, 209, 187, 165, 142, 120, 104, 86, 72}, + {242, 228, 209, 187, 165, 142, 120, 104, 86, 72, 56}, + {228, 209, 187, 165, 142, 120, 104, 86, 72, 56, 42}, + {209, 187, 165, 142, 120, 104, 86, 72, 56, 42, 28}, + {187, 165, 142, 120, 104, 86, 72, 56, 42, 28, 17}, + {165, 142, 120, 104, 86, 72, 56, 42, 28, 17, 9}, + {142, 120, 104, 86, 72, 56, 42, 28, 17, 9, 0}, + {120, 104, 86, 72, 56, 42, 28, 17, 9, 0, 0}, + {104, 86, 72, 56, 42, 28, 17, 9, 0, 0, 0} + }; + + protected int getControlSize() { + return getIconWidth(); + } + + /** + * Draws the check box icon at the specified location. + * + * @param c The component to draw on. + * @param g The graphics context. + * @param x The x coordinate of the top left corner. + * @param y The y coordinate of the top left corner. + */ + public void paintIcon(Component c, Graphics g, int x, int y) { + AbstractButton button = (AbstractButton) c; + Color col = null; + + if (!button.isEnabled()) { + col = ThemeUtils.BUTTON_DISABLE_COLOR; + } else if (button.getModel().isPressed()) { + if (button.getModel().isRollover()) { + col = ThemeUtils.BUTTON_PRESS_COLOR; + } else { + col = ThemeUtils.BUTTON_NORMAL_COLOR; + } + } else if (button.getModel().isRollover()) { + col = ThemeUtils.BUTTON_ROLLOVER_BG_COLOR; + } else { + col = ThemeUtils.BUTTON_NORMAL_COLOR; + } + + g.setColor(col); + + drawXpCheck(g, button, col, x, y, getIconWidth(), getIconHeight()); + + + // checkmark + if (!button.isSelected()) { + return; + } + if (!button.isEnabled()) { + g.setColor(ThemeUtils.BUTTON_CHECK_DISABLE_COLOR); + } else { + g.setColor(ThemeUtils.BUTTON_CHECK_COLOR); + } + + drawXpCheckMark(g, x, y); + + } + + private void drawXpCheck(Graphics g, AbstractButton b, Color c, + int x, int y, int w, int h) { + boolean pressed = b.getModel().isPressed(); + boolean armed = b.getModel().isArmed(); + boolean enabled = b.isEnabled(); + boolean rollover = b.getModel().isRollover(); + boolean focused = ThemeUtils.BUTTON_FOCUS_BORDER && !rollover && b.isFocusOwner(); + + // In 1.3.5 key was build with argument rollover instead of (rollover || armed) + // Fixed in 1.3.6 + CheckKey key = new CheckKey(c, pressed, enabled, (rollover || armed), focused); + Object value = cache.get(key); + + if (value != null) { + // image already cached - paint image and return + g.drawImage((Image) value, x, y, b); + return; + } + + Image img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + + + // spread light is between 0 and 20 + int spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT; + int spread2 = ThemeUtils.BUTTON_SPREAD_DARK; + + if (!b.isEnabled()) { + spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT_DISABLE; + spread2 = ThemeUtils.BUTTON_SPREAD_DARK_DISABLE; + } + + int spreadStep1 = spread1 * 5; // 20 -> 100 + // this means, we can never fully darken background, + // but we also want it bright enough + int spreadStep2 = spread2 * 4; // 20 -> 80 + boolean isRolloverOrArmed = rollover || armed; + if (pressed && isRolloverOrArmed) { + spreadStep2 *= 2; + } + c = ColorRoutines.lighten(c, spreadStep1); + drawImage(c, spreadStep2, img, b, w, h, rollover, pressed, focused); + + // draw the image + g.drawImage(img, x, y, b); + + // add the image to the cache + cache.put(key, img); + } + + private void drawImage(Color c, int spreadStep2, Image img, AbstractButton b, int w, int h, + boolean rollover, boolean pressed, boolean focused) { + Graphics imgGraphics = img.getGraphics(); + + imgGraphics.setColor(ColorRoutines.darken(c, spreadStep2)); + imgGraphics.fillRect(1, 1, w - 2, h - 2); + Color color; + + for (int row = 0; row < 11; row++) { + for (int col = 0; col < 11; col++) { + color = new Color(c.getRed(), c.getGreen(), c.getBlue(), 255 - A[col][row]); + imgGraphics.setColor(color); + imgGraphics.drawLine(col + 1, row + 1, col + 1, row + 1); + } + } + + // border + if (!b.isEnabled()) { + imgGraphics.setColor(ThemeUtils.BUTTON_BORDER_DISABLE_COLOR); + imgGraphics.drawRect(0, 0, w - 1, h - 1); + } else { + imgGraphics.setColor(ThemeUtils.BUTTON_BORDER_COLOR); + imgGraphics.drawRect(0, 0, w - 1, h - 1); + + if (rollover && ThemeUtils.BUTTON_ROLLOVER && !pressed) { + DrawRoutines.drawRolloverCheckBorder(imgGraphics, + ThemeUtils.BUTTON_ROLLOVER_COLOR, 0, 0, w, h); + } else if (focused && !pressed) { + DrawRoutines.drawRolloverCheckBorder(imgGraphics, + ThemeUtils.BUTTON_DEFAULT_COLOR, 0, 0, w, h); + } + } + + // dispose of image graphics + imgGraphics.dispose(); + } + + private void drawXpCheckMark(Graphics g, int x, int y) { + g.drawLine(x + 3, y + 5, x + 3, y + 7); + g.drawLine(x + 4, y + 6, x + 4, y + 8); + g.drawLine(x + 5, y + 7, x + 5, y + 9); + g.drawLine(x + 6, y + 6, x + 6, y + 8); + g.drawLine(x + 7, y + 5, x + 7, y + 7); + g.drawLine(x + 8, y + 4, x + 8, y + 6); + g.drawLine(x + 9, y + 3, x + 9, y + 5); + } + + public int getIconWidth() { + return ThemeUtils.CHECK_SIZE.width; + } + + public int getIconHeight() { + return ThemeUtils.CHECK_SIZE.height; + } + + /* + * EnabledCheckKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + * Used only if we are run from ControlPanel. + */ + protected static class EnabledCheckKey { + public int spread1; + public int spread2; + public Color c, back; + + EnabledCheckKey(Color c, Color back) { + spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT; + spread2 = ThemeUtils.BUTTON_SPREAD_DARK; + this.c = c; + this.back = back; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof EnabledCheckKey)) { + return false; + } + + EnabledCheckKey other = (EnabledCheckKey) o; + return ComparatorUtils.equals(c, other.c) && + ComparatorUtils.equals(back, other.back) && + ComparatorUtils.equals(spread1, other.spread1) && + ComparatorUtils.equals(spread2, other.spread2); + } + + public int hashCode() { + return c.hashCode() * back.hashCode() * spread1 * spread2; + } + } + + /* + * DisabledCheckKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + * Used only if we are run from ControlPanel. + */ + protected static class DisabledCheckKey { + public int spread1; + public int spread2; + public Color c, back; + + DisabledCheckKey(Color c, Color back) { + spread1 = ThemeUtils.BUTTON_SPREAD_LIGHT_DISABLE; + spread2 = ThemeUtils.BUTTON_SPREAD_DARK_DISABLE; + this.c = c; + this.back = back; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof DisabledCheckKey)) { + return false; + } + + DisabledCheckKey other = (DisabledCheckKey) o; + return ComparatorUtils.equals(c, other.c) && + ComparatorUtils.equals(back, other.back) && + ComparatorUtils.equals(spread1, other.spread1) && + ComparatorUtils.equals(spread2, other.spread2); + } + + public int hashCode() { + return c.hashCode() * back.hashCode() * spread1 * spread2; + } + } + + /* + * CheckKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + */ + protected static class CheckKey { + + private Color c; + private boolean pressed; + private boolean enabled; + private boolean rollover; + private boolean focused; + + CheckKey(Color c, boolean pressed, boolean enabled, boolean rollover, boolean focused) { + this.c = c; + this.pressed = pressed; + this.enabled = enabled; + this.rollover = rollover; + this.focused = focused; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof CheckKey)) { + return false; + } + + CheckKey other = (CheckKey) o; + return ComparatorUtils.equals(c,other.c) && + ComparatorUtils.equals(pressed,other.pressed) && + ComparatorUtils.equals(enabled,other.enabled) && + ComparatorUtils.equals(rollover,other.rollover)&& + ComparatorUtils.equals(focused,other.focused); + } + + public int hashCode() { + return c.hashCode() * + (pressed ? 1 : 2) * + (enabled ? 4 : 8) * + (rollover ? 16 : 32); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxUI.java b/designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxUI.java new file mode 100644 index 0000000000..4699fb5ac3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icheckbox/UICheckBoxUI.java @@ -0,0 +1,88 @@ +package com.fr.design.gui.icheckbox; + + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalCheckBoxUI; +import java.awt.*; +import java.awt.event.KeyEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-13 + * Time: 下午5:12 + */ +public class UICheckBoxUI extends MetalCheckBoxUI { + + /** + * The Cached UI delegate. + */ + private final static UICheckBoxUI CHECK_BOX_UI = new UICheckBoxUI(); + + /** + * 创建UI + * @param c 组件 + * @return 返回组件UI + */ + public static ComponentUI createUI(JComponent c) { + return CHECK_BOX_UI; + } + + /** + * Installs some default values for the given button. + * + * @param button The reference of the button to install its default values. + */ + + static UICheckBoxIcon checkIcon = new UICheckBoxIcon(); + + /** + * 为组件加载图标 + * @param button 按钮 + */ + public void installDefaults(AbstractButton button) { + super.installDefaults(button); + icon = checkIcon; + button.setRolloverEnabled(true); + + if (!ThemeUtils.BUTTON_ENTER){ + return; + } + if (!button.isFocusable()){ + return; + } + + InputMap km = (InputMap) UIManager.get(getPropertyPrefix() + "focusInputMap"); + + if (km != null) { + km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "pressed"); + km.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "released"); + } + } + + static BasicStroke focusStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1.0f, new float[]{1.0f / 1.0f}, 1.0f); + + protected void paintFocus(Graphics g, Rectangle t, Dimension arg2) { + if (!ThemeUtils.BUTTON_FOCUS) { + return; + } + + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(Color.black); + g2d.setStroke(focusStroke); + + int x1 = t.x - 1; + int y1 = t.y - 1; + int x2 = x1 + t.width + 1; + int y2 = y1 + t.height + 1; + + g2d.drawLine(x1, y1, x2, y1); + g2d.drawLine(x1, y1, x1, y2); + g2d.drawLine(x1, y2, x2, y2); + g2d.drawLine(x2, y1, x2, y2); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/AlignmentComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/AlignmentComboBox.java new file mode 100644 index 0000000000..3e1e9aaf23 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/AlignmentComboBox.java @@ -0,0 +1,83 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.general.Inter; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; + +/** + * Alignment ComboBox + */ +public class AlignmentComboBox extends UIComboBox { + + /** + * Constructor. + * + * @param alignmentArray the array of alignment. + */ + public AlignmentComboBox(int[] alignmentArray) { + //copy lineStyle. + Integer[] alignmentIntegerArray = new Integer[alignmentArray.length]; + + for (int i = 0; i < alignmentArray.length; i++) { + alignmentIntegerArray[i] = new Integer(alignmentArray[i]); + } + + this.setModel(new DefaultComboBoxModel(alignmentIntegerArray)); + this.setRenderer(new AligmentCellRenderer()); + } + + /** + * Get selected alignment. + */ + public int getSelectedAlignment() { + return ((Integer) getSelectedItem()).intValue(); + } + + /** + * Set the selected alignment. + */ + public void setSelectedAlignment(int alignment) { + this.setSelectedItem(new Integer(alignment)); + } + + public static String getAlignDescription(int alignment) { + if (alignment == Constants.CENTER) {//0 + return Inter.getLocText("Center"); + } else if (alignment == Constants.TOP) {//1 + return Inter.getLocText("StyleAlignment-Top"); + } else if (alignment == Constants.LEFT) {//2 + return Inter.getLocText("StyleAlignment-Left"); + } else if (alignment == Constants.BOTTOM) {//3 + return Inter.getLocText("StyleAlignment-Bottom"); + } else if (alignment == Constants.RIGHT) { //4 + return Inter.getLocText("StyleAlignment-Right"); + } else if (alignment == Constants.DISTRIBUTED) { //added by Kevin Wang 6 + return Inter.getLocText("StyleAlignment-Distibuted"); + } else { + return StringUtils.EMPTY; + } + } + + /** + * CellRenderer. + */ + class AligmentCellRenderer extends UIComboBoxRenderer { + + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + int alignment = ((Integer) value).intValue(); + this.setText(getAlignDescription(alignment)); + return this; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/ComboCheckBox.java b/designer_base/src/com/fr/design/gui/icombobox/ComboCheckBox.java new file mode 100644 index 0000000000..ec13d2ffda --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/ComboCheckBox.java @@ -0,0 +1,195 @@ +package com.fr.design.gui.icombobox; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.IllegalComponentStateException; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; + +import javax.swing.BorderFactory; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.ListModel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.basic.ComboPopup; + +import com.fr.design.gui.ilist.CheckBoxList; +import com.fr.design.gui.ilist.CheckBoxList.CheckBoxListSelectionChangeListener; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.stable.ArrayUtils; + + +/** + * richer:下拉复选框 + */ +public class ComboCheckBox extends UIComboBox { + + private static final int VALUE120 = 120; + + private CheckBoxList checkBoxList; + + public ComboCheckBox() { + this(new Object[0]); + } + + public ComboCheckBox(Object[] data) { + this.setData(data); + } + + public void setData(Object[] data) { + checkBoxList = new CheckBoxList(data); + this.updateUI(); + } + + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.width = dim.width < VALUE120 ? VALUE120 : dim.width; + return dim; + } + + /** + * 更新UI + */ + public void updateUI() { + ComboBoxUI cui = (ComboBoxUI) UIManager.getUI(this); + cui = new ComboBoxCheckBoxUI(); + setUI(cui); + } + + private class ComboBoxCheckBoxUI extends UIBasicComboBoxUI { + protected ComboPopup createPopup() { + return new CheckListPopup(comboBox); + } + } + + private class CheckListPopup extends JPopupMenu implements ComboPopup { + protected ComboCheckBox comboBox; + protected JScrollPane scrollPane; + + protected MouseListener mouseListener; + protected MouseMotionListener mouseMotionListener; + + public CheckListPopup(JComboBox comboBox) { + this.comboBox = (ComboCheckBox) comboBox; + this.setBorder(BorderFactory.createLineBorder(Color.black)); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled()); + if (checkBoxList != null) { + this.scrollPane = new JScrollPane(checkBoxList); + this.scrollPane.setBorder(null); + this.add(this.scrollPane, BorderLayout.CENTER); + checkBoxList.addCheckBoxListSelectionChangeListener(new CheckBoxListSelectionChangeListener() { + + @Override + public void selectionChanged(CheckBoxList target) { + Object[] values = checkBoxList.getSelectedValues(); + CheckListPopup.this.comboBox.getModel().setSelectedItem(values); + } + }); + } + } + + private int getFittingLocaltion2Show() { + Dimension size = this.getPreferredSize(); + Component com = comboBox.getParent(); + if (com != null) { + if (comboBox.getLocation().y + comboBox.getHeight() + size.height > com.getSize().height && comboBox.getLocation().y - size.height > 0) { + return -size.height; + } + } + + return comboBox.getHeight(); + } + + public void show() { + this.updatePopup(); + try { + this.show(comboBox, 0, getFittingLocaltion2Show()); + } catch (IllegalComponentStateException e) { + // richer:这里有可能会抛出一个异常,可以不用处理 + } + checkBoxList.requestFocus(); + } + + public void hide() { + this.setVisible(false); + } + + protected void togglePopup() { + if (this.isVisible()) { + this.hide(); + } else { + this.show(); + } + } + + protected void updatePopup() { + this.setPreferredSize(new Dimension(this.comboBox.getSize().width, checkBoxList.getPreferredSize().height > VALUE120 ? VALUE120 : checkBoxList.getPreferredSize().height + 2)); + Object obj = this.comboBox.getSelectedItem(); + if (obj instanceof Object[]) { + ListModel model = this.comboBox.checkBoxList.getModel(); + for (int i = 0; i < model.getSize(); i++) { + if (ArrayUtils.indexOf((Object[]) obj, model.getElementAt(i)) != -1) { + this.comboBox.checkBoxList.setSelected(i, true); + } + } + } + } + + public KeyListener getKeyListener() { + return null; + } + + public JList getList() { + return new JList(); + } + + @Override + public MouseListener getMouseListener() { + if (mouseListener == null) { + mouseListener = new InvocationMouseHandler(); + } + return mouseListener; + } + + public MouseMotionListener getMouseMotionListener() { + if (mouseMotionListener == null) { + mouseMotionListener = new MouseMotionAdapter() { + }; + } + return mouseMotionListener; + } + + public void uninstallingUI() { + + } + + protected class InvocationMouseHandler extends MouseAdapter { + public void mousePressed(MouseEvent e) { + if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled()) { + return; + } + if (comboBox.isEditable()) { + Component comp = comboBox.getEditor().getEditorComponent(); + if ((!(comp instanceof JComponent)) || ((JComponent) comp).isRequestFocusEnabled()) { + comp.requestFocus(); + } + } else if (comboBox.isRequestFocusEnabled()) { + comboBox.requestFocus(); + } + togglePopup(); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/DictionaryComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/DictionaryComboBox.java new file mode 100644 index 0000000000..16ad237191 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/DictionaryComboBox.java @@ -0,0 +1,61 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Component; +import java.awt.Dimension; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JList; + +/* + * 显示和选择的项不同的下拉框 + */ +public class DictionaryComboBox extends UIComboBox { + /** + * + */ + private static final long serialVersionUID = -19512646054322609L; + private Object[] keys; + private String[] values; + + + public DictionaryComboBox(T[] keys, String[] displays) { + this(keys, displays, true); + } + + public DictionaryComboBox(Object[] keys, String[] displays, boolean editable) { + this.initComboBox(keys, displays, editable); + } + + private void initComboBox(Object[] keys, String[] displays, boolean editable){ + this.setPreferredSize(new Dimension(60, 20)); + this.keys = keys; + this.values = displays; + this.setModel(new DefaultComboBoxModel(keys)); + this.setRenderer(new UIComboBoxRenderer() { + /** + * + */ + private static final long serialVersionUID = -6497147896537056134L; + + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, + boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, + isSelected, cellHasFocus); + + for (int i = 0, len = DictionaryComboBox.this.keys.length; i < len; i++) { + if (DictionaryComboBox.this.keys[i].equals(value)) { + this.setText(DictionaryComboBox.this.values[i]); + break; + } + } + return this; + } + }); + } + + @SuppressWarnings("unchecked") + public T getSelectedItem() { + return (T)super.getSelectedItem(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/DictionaryConstants.java b/designer_base/src/com/fr/design/gui/icombobox/DictionaryConstants.java new file mode 100644 index 0000000000..c21b857505 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/DictionaryConstants.java @@ -0,0 +1,86 @@ +package com.fr.design.gui.icombobox; + +import com.fr.base.SeparationConstants; +import com.fr.general.Inter; + +public class DictionaryConstants { + // richer:正则表达式 + public final static String[] regexps = new String[] { + "", + "^.+$", + "^\\w{0,13}$", + "^\\d+(\\.\\d+)?$", + "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", + "^\\d{3,4}-\\d{7,8}$", + "^\\d{11}$", + "(^\\d{15}$)|(^\\d{17}([0-9]|[Xx])$)", + "^\\d{6}$" }; + + public final static String[] regexpsDisplays = new String[] { + Inter.getLocText("None"), + Inter.getLocText("Required"), + Inter.getLocText("Length"), + Inter.getLocText("Float"), + Inter.getLocText("Email"), + Inter.getLocText("Phone"), + Inter.getLocText("MobilePhone"), + Inter.getLocText("IDCard"), + Inter.getLocText("PostCode"), + Inter.getLocText("Custom")}; + + public final static int REG_NONE = 0; + public final static int REG_REQUIRED = 1; + public final static int REG_LENGTH = 2; + public final static int REG_FLOAT = 3; + public final static int REG_EMAIL = 4; + public final static int REG_PHONE = 5; + public final static int REG_MOBILEPHONE = 6; + public final static int REG_IDCARD = 7; + public final static int REG_POSTCODE = 8; + public final static int REG_CUSTOM = 9; + + // richer:分隔符 + public static final String[] delimiters = new String[]{ + SeparationConstants.COMMA, SeparationConstants.SEMICOLON, SeparationConstants.COLON + }; + + public static final String[] delimiterDisplays = new String[]{ + Inter.getLocText("Form-Comma"), + Inter.getLocText("Form-Semicolon"), + Inter.getLocText("Form-Colon") + }; + + public static final String[] symbols = new String[]{ + "", SeparationConstants.SINGLE_QUOTE, SeparationConstants.DOUBLE_QUOTES + }; + + public static final String[] symbolDisplays = new String[]{ + Inter.getLocText("None"), + Inter.getLocText("Form-Single_quote"), + Inter.getLocText("Form-Double_quotes") + }; + // richer:文件类型选择器 + public static final String[] fileTypes = new String[]{ + "", + "txt", + "pdf", + "jpg,png,gif", + "doc,xls,ppt" + }; + + public static final String[] acceptTypes = new String[]{ + "", + "txt", + "pdf", + "jpg|png|gif", + "doc|xls|ppt" + }; + + public static final String[] fileTypeDisplays = new String[]{ + Inter.getLocText("Form-All_Files"), + "txt", + "pdf", + "jpg,png,gif", + "doc,xls,ppt" + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBox.java new file mode 100644 index 0000000000..86a5b5cf26 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBox.java @@ -0,0 +1,114 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.util.Vector; + +import javax.swing.ComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.plaf.basic.ComboPopup; + + +public class ExtendedComboBox extends UIComboBox { + private static final int VALUE120 = 120; + + public ExtendedComboBox() { + } + + public ExtendedComboBox(ComboBoxModel aModel) { + super(aModel); + } + + public ExtendedComboBox(Object[] items) { + super(items); + } + + public ExtendedComboBox(Vector items) { + super(items); + } + + /** + * 更新UI + */ + public void updateUI() { + setUI(new ExtendedComboBoxUI()); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.width = VALUE120; + return dim; + } + + static class ExtendedComboBoxUI extends UIBasicComboBoxUI { + public static ComponentUI createUI(JComponent c) { + return new ExtendedComboBoxUI(); + } + + protected ComboPopup createPopup() { + ExtendedComboPopup popup = new ExtendedComboPopup(comboBox); + popup.getAccessibleContext().setAccessibleParent(comboBox); + return popup; + } + + public ComboPopup getPopup() { + return popup; + } + } + + static class ExtendedComboPopup extends BasicComboPopup { + + public ExtendedComboPopup(JComboBox combo) { + super(combo); + } + protected JList createList() { + return new JList(comboBox.getModel()) { + public void processMouseEvent(MouseEvent e) { + if (e.isControlDown()) { + // Fix for 4234053. Filter out the Control + // Key from the list. + // ie., don't allow CTRL key deselection. + e = new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers() + ^ InputEvent.CTRL_MASK, e.getX(), e.getY(), e.getClickCount(), e.isPopupTrigger()); + } + super.processMouseEvent(e); + } + + public String getToolTipText(MouseEvent event) { + int index = locationToIndex(event.getPoint()); + if (index != -1) { + Object value = getModel().getElementAt(index); + ListCellRenderer renderer = getCellRenderer(); + Component rendererComp = renderer.getListCellRendererComponent(this, value, index, true, false); + if (rendererComp.getPreferredSize().width > getVisibleRect().width) { + return value == null ? null : value.toString(); + } else { + return null; + } + } + return null; + } + + public Point getToolTipLocation(MouseEvent event) { + int index = locationToIndex(event.getPoint()); + if (index != -1) { + Rectangle cellBounds = getCellBounds(index, index); + return new Point(cellBounds.x, cellBounds.y); + } + return null; + } + }; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBoxTest.java b/designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBoxTest.java new file mode 100644 index 0000000000..7f64e37fd9 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/ExtendedComboBoxTest.java @@ -0,0 +1,34 @@ +package com.fr.design.gui.icombobox; + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.UIManager; + +import com.fr.base.FRContext; + +public class ExtendedComboBoxTest { + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + final ExtendedComboBox cb = new ExtendedComboBox( + new String[] { + "Hello world, alksdfjlaskdjflaskjdflaksdf", + "Hello world, alksdfjlaskdjflaskjdflaksdfasdfklajsdflkasjdflkasdf", + "Hello world, alksdfjlaskdjflaskjdflaksdfasdfklajsdflkasjdflkasdfaaaaaaaaaaaaaaaaaadfsdf", + "Hello world, alksdfjlaskdjflaskjdflaksdfasdfklajsdflkasjdflkasdfsdfgklsdjfgklsdfjgklsjdfgkljsdflkgjsdlfk" }); + + + JFrame f = new JFrame(); + f.getContentPane().add(cb, BorderLayout.CENTER); + f.pack(); + f.setSize(300, f.getHeight()); + f.setLocationRelativeTo(null); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/FRTreeComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/FRTreeComboBox.java new file mode 100644 index 0000000000..3ddec17d25 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/FRTreeComboBox.java @@ -0,0 +1,596 @@ +package com.fr.design.gui.icombobox; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.IllegalComponentStateException; +import java.awt.RenderingHints; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; +import java.util.Enumeration; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.basic.BasicComboBoxUI; +import javax.swing.plaf.basic.ComboPopup; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.general.ComparatorUtils; +import com.fr.general.NameObject; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +public class FRTreeComboBox extends UIComboBox { + + private static final int PAGE_DIFF = 5; + private static final int DEFAULT_HEIGHT = 120; + + // richer:下拉展示用的tree + protected JTree tree; + private boolean onlyLeafSelectable = true; + + public FRTreeComboBox() { + this(new JTree()); + } + + public FRTreeComboBox(JTree tree) { + this(tree, null); + } + + public FRTreeComboBox(JTree tree, TreeCellRenderer renderer) { + this(tree, renderer, false); + } + + public FRTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) { + this(tree, renderer, false, editable); + } + + public FRTreeComboBox(JTree tree, TreeCellRenderer renderer, + boolean showRoot, boolean editable) { + this.setTree(tree); + this.tree.setCellRenderer(renderer); + this.setEditor(new FrTreeSearchComboBoxEditor(this)); + if (!showRoot) { + tree.expandPath(new TreePath(tree.getModel().getRoot())); + tree.setRootVisible(false); + } + this.setEditable(editable); + setUI(new FRTreeComboBoxUI()); + } + + public JTree getTree() { + return this.tree; + } + + public void setTree(JTree tree) { + this.tree = tree; + if (tree != null) { + this.setSelectedItem(tree.getSelectionPath()); + this.setRenderer(new TreeComboBoxRenderer()); + } + } + + public void setOnlyLeafSelectable(boolean onlyLeafSelectable) { + this.onlyLeafSelectable = onlyLeafSelectable; + } + + /** + * 获得FRTreeComboBox的返回值 + * + * @return Object + */ + public Object getSelectedObject() { + if (!(this.getSelectedItem() instanceof TreePath)) { + return this.getSelectedItem(); + } + TreePath treePath = (TreePath) this.getSelectedItem(); + if (treePath == null) { + return null; + } + DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent(); + return node.getUserObject(); + } + + public String getProcedureSelectName() { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) ((TreePath) this.getSelectedItem()).getLastPathComponent(); + NameObject no = (NameObject) node.getUserObject(); + String ds2 = no.getName(); + node = (DefaultMutableTreeNode) node.getParent(); + no = (NameObject) node.getUserObject(); + String ds1 = no.getName(); + return ds1 + "." + ds2; + } + + protected void dealSamePath(TreePath parent,TreeNode node,UITextField textField){ + boolean isBreak = false; + for (Enumeration e = node.children(); e.hasMoreElements(); ) { + TreeNode n = (TreeNode) e.nextElement(); + TreePath path = parent.pathByAddingChild(n); + TreeNode pathnode = (TreeNode) path.getLastPathComponent(); + for (Enumeration e2 = pathnode.children(); e2.hasMoreElements(); ) { + TreeNode n2 = (TreeNode) e2.nextElement(); + TreePath path2 = path.pathByAddingChild(n2); + if (pathToString(path2).toUpperCase().startsWith(textField.getText().toUpperCase())) { + tree.scrollPathToVisible(path2); + tree.setSelectionPath(path2); + isBreak = true; + break; + } + } + if (isBreak) { + break; + } + } + } + + public void setSelectedItem(Object o) { + if (o instanceof String) { + this.setSelectedItemString((String) o); + return; + } + this.tree.setSelectionPath((TreePath) o); + if (this.isEditable && o != null) { + this.setSelectedItemString(pathToString((TreePath) o)); + } else { + this.getModel().setSelectedItem(o); + } + } + + private boolean validTreePath(String treePath){ + return StringUtils.isNotEmpty(treePath) && treePath.charAt(0) == '[' && treePath.endsWith("]"); + } + + protected String pathToString(TreePath path) { + String temp = path.toString(); + if (validTreePath(temp)) { + temp = temp.substring(2, temp.length() - 1); + String[] selectedtable = temp.split(","); + String table = selectedtable[selectedtable.length - 1].trim(); + if (table.contains(".")) { + String[] temp2 = table.split("\\."); + table = temp2[temp2.length - 1].trim(); + } + return table; + } + return ""; + } + + /* + * richer:根据NameObject的名字来选取 + */ + public void setSelectedItemString(String _name) { + if (StringUtils.isBlank(_name)) { + this.setSelectedIndex(-1); + return; + } + DefaultTreeModel model = (DefaultTreeModel) this.tree.getModel(); + DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); + DefaultMutableTreeNode leaf = root.getFirstLeaf(); + do { + Object userObj = leaf.getUserObject(); + if (userObj instanceof NameObject) { + if (ComparatorUtils.equals(_name, ((NameObject) userObj).getName())) { + TreePath path = new TreePath(model.getPathToRoot(leaf)); + this.tree.setSelectionPath(path); + this.setSelectedItem(path); + break; + } + } + } while ((leaf = leaf.getNextLeaf()) != null); + if (leaf == null) { + this.getModel().setSelectedItem(_name); + } + } + + public void setSelectedFirst() { + DefaultTreeModel model = (DefaultTreeModel) this.tree.getModel(); + DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot(); + if (root == null) { + return; + } + DefaultMutableTreeNode leaf = root.getFirstLeaf(); + if (leaf == null) { + return; + } + if (leaf.getUserObject() instanceof NameObject) { + TreePath path = new TreePath(model.getPathToRoot(leaf)); + this.tree.setSelectionPath(path); + this.setSelectedItem(path); + } + } + + public void setPopSize(int width, int height) { + treePopup.setPopSize(width, height); + } + + + private static TreePopup treePopup; + + private static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{ + private boolean isRollover = false; + + public FRTreeComboBoxUI() { + super(); + } + protected ComboPopup createPopup() { + treePopup = new TreePopup(comboBox); + return treePopup; + } + @Override + protected UIButton createArrowButton() { + arrowButton = new UIButton(UIConstants.ARROW_DOWN_ICON); + ((UIButton) arrowButton).setRoundBorder(true, Constants.LEFT); + arrowButton.addMouseListener(this); + comboBox.addMouseListener(this); + return (UIButton) arrowButton; + } + + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color linecolor = null; + if (comboBox.isPopupVisible()) { + linecolor = UIConstants.LINE_COLOR; + arrowButton.setSelected(true); + } else if (isRollover) { + linecolor = UIConstants.LIGHT_BLUE; + } else { + linecolor = UIConstants.LINE_COLOR; + arrowButton.setSelected(false); + } + g2d.setColor(linecolor); + if (!comboBox.isPopupVisible()) { + g2d.drawRoundRect(0, 0, c.getWidth() - arrowButton.getWidth() + 3, c.getHeight() - 1, UIConstants.LARGEARC, UIConstants.LARGEARC); + } else { + g2d.drawRoundRect(0, 0, c.getWidth() , c.getHeight() + 3, UIConstants.LARGEARC, UIConstants.LARGEARC ); + g2d.drawLine(0, c.getHeight()-1, c.getWidth(), c.getHeight()-1); + } + } + + + + private void setRollover(boolean isRollover) { + if (this.isRollover != isRollover) { + this.isRollover = isRollover; + comboBox.repaint(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + setRollover(true); + } + + @Override + public void mouseExited(MouseEvent e) { + setRollover(false); + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + } + + /** + * 添加弹出菜单监听 + * + * @param l 监听事件 + * + * @date 2015-1-22-下午5:04:00 + * + */ + public void addPopupMenuListener(PopupMenuListener l) { + treePopup.addPopupMenuListener(l); + } + + private class TreeComboBoxRenderer extends DefaultListCellRenderer { + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) { + if (value != null) { + TreePath path = (TreePath) value; + TreeNode node = (TreeNode) path.getLastPathComponent(); + value = node; + TreeCellRenderer treeCellRenderer = tree.getCellRenderer(); + UILabel lb = (UILabel) treeCellRenderer.getTreeCellRendererComponent(tree, value, isSelected, + false, node.isLeaf(), index, cellHasFocus); + return lb; + } + return super.getListCellRendererComponent(list, value, index, + isSelected, cellHasFocus); + } + } + + /* + * richer:弹出部分 + */ + private static class TreePopup extends JPopupMenu implements ComboPopup { + /** + * + */ + private static final long serialVersionUID = 1L; + private int defaultWidth = 0; + private int defaultHeight = 0; + protected FRTreeComboBox comboBox; + protected JScrollPane scrollPane; + protected JTree tree; + + protected MouseMotionListener mouseMotionListener; + protected MouseListener mouseListener; + private MouseListener treeSelectListener = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + JTree tree = (JTree) e.getSource(); + TreePath treePath = tree.getPathForLocation(e.getPoint().x, e + .getPoint().y); + if (treePath == null) { + return; + } + DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath + .getLastPathComponent(); + selectTreeItem(node, treePath); + } + }; + + //samuel:相应首字母导航的键盘确定 + private KeyListener treeKeyListener = new KeyAdapter() { + public void keyReleased(KeyEvent e) { + int key = e.getKeyCode(); + if (key == KeyEvent.VK_ENTER) { + TreePath treePath = tree.getSelectionPath(); + if (treePath == null) { + return; + } + DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath + .getLastPathComponent(); + selectTreeItem(node, treePath); + } + } + }; + + private void selectTreeItem(DefaultMutableTreeNode node, TreePath treePath) { + if (node.isRoot()) { + return; + } + if (comboBox.onlyLeafSelectable && !node.isLeaf()) { + return; + } + comboBox.setSelectedItem(treePath); + togglePopup(); + MenuSelectionManager.defaultManager().clearSelectedPath(); + } + + public TreePopup(JComboBox comboBox) { + this.comboBox = (FRTreeComboBox) comboBox; + this.setBorder(BorderFactory.createLineBorder(Color.black)); + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setLightWeightPopupEnabled(comboBox + .isLightWeightPopupEnabled()); + tree = this.comboBox.getTree(); + if (tree != null) { + this.scrollPane = new JScrollPane(tree); + this.scrollPane.setBorder(null); + this.add(this.scrollPane, BorderLayout.CENTER); + tree.addMouseListener(this.treeSelectListener); + tree.addKeyListener(this.treeKeyListener); + } + } + + public void show() { + this.updatePopup(); + try { + /* + * 这里有个问题,可能是哪里的listenerr有冲突将这个JPopMenu show的X设置为70时 + * 正好可以脱离DBManipulationPane,此时可以正确相应鼠标点击事件,否则由于焦点不在JPopmenu + * 上点击,树时将导致窗口销毁,无法正确相应点击事件 + */ + this.show(comboBox, 0, comboBox.getHeight()); + } catch (IllegalComponentStateException e) { + // richer:这里有可能会抛出一个异常,可以不用处理 + } + } + + public void hide() { + this.setVisible(false); + } + + public JList getList() { + return new JList(); + } + + public MouseMotionListener getMouseMotionListener() { + if (mouseMotionListener == null) { + mouseMotionListener = new MouseMotionAdapter() { + }; + } + return mouseMotionListener; + } + + public KeyListener getKeyListener() { + return null; + } + + public void uninstallingUI() { + } + + public MouseListener getMouseListener() { + if (mouseListener == null) { + mouseListener = new InvocationMouseHandler(); + } + return mouseListener; + } + + protected void togglePopup() { + if (this.isVisible()) { + this.hide(); + } else { + this.show(); + } + } + + protected void updatePopup() { + int width = defaultWidth == 0 ? this.comboBox.getSize().width : defaultWidth; + int height = defaultHeight == 0 ? DEFAULT_HEIGHT : defaultHeight; + this.setPreferredSize(new Dimension(width, height)); + Object selectedObj = this.comboBox.getSelectedItem(); + if (selectedObj instanceof TreePath) { + TreePath tp = (TreePath) selectedObj; + (this.comboBox).getTree().setSelectionPath(tp); + } + } + + public void setPopSize(int width, int height) { + this.defaultWidth = width; + this.defaultHeight = height; + } + + protected class InvocationMouseHandler extends MouseAdapter { + public void mousePressed(MouseEvent e) { + if (!SwingUtilities.isLeftMouseButton(e) + || !comboBox.isEnabled()) { + return; + } + if (comboBox.isEditable()) { + Component comp = comboBox.getEditor().getEditorComponent(); + if ((!(comp instanceof JComponent)) + || ((JComponent) comp).isRequestFocusEnabled()) { + comp.requestFocus(); + } + } else if (comboBox.isRequestFocusEnabled()) { + comboBox.requestFocus(); + } + togglePopup(); + } + } + } + + class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener { + private volatile boolean setting = false; + private FRTreeComboBox comboBox; + private Object item; + + public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) { + super(); + this.comboBox = comboBox; + textField.getDocument().addDocumentListener(this); + textField.addKeyListener(this.treeKeyListener); + } + + private KeyListener treeKeyListener = new KeyAdapter() { + public void keyPressed(KeyEvent e) { + int key = e.getKeyCode(); + if (key == KeyEvent.VK_DOWN) { + int row = tree.getRowForPath(tree.getSelectionPath()) + 1; + tree.setSelectionRow(row); + tree.scrollRowToVisible(row); + } else if (key == KeyEvent.VK_UP) { + int row = tree.getRowForPath(tree.getSelectionPath()) - 1; + tree.setSelectionRow(row); + tree.scrollRowToVisible(row); + } else if (key == KeyEvent.VK_PAGE_DOWN) { + int row = tree.getRowForPath(tree.getSelectionPath()) + PAGE_DIFF; + tree.setSelectionRow(row); + tree.scrollRowToVisible(row); + } else if (key == KeyEvent.VK_PAGE_UP) { + int row = tree.getRowForPath(tree.getSelectionPath()) - PAGE_DIFF; + tree.setSelectionRow(row); + tree.scrollRowToVisible(row); + } + } + + public void keyReleased(KeyEvent e) { + int key = e.getKeyCode(); + if (key == KeyEvent.VK_ENTER) { + TreePath treePath = tree.getSelectionPath(); + if (treePath == null) { + return; + } + DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath + .getLastPathComponent(); + if (node.isLeaf()) { + comboBox.setSelectedItem(treePath); + textField.setText(pathToString(treePath)); + MenuSelectionManager.defaultManager().clearSelectedPath(); + } + } + + } + }; + + + public void setItem(Object item) { + this.item = item; + this.setting = true; + textField.setText((item == null) ? "" : item.toString()); + this.setting = false; + } + + public Object getItem() { + return this.item; + } + + public void insertUpdate(DocumentEvent e) { + changeHandler(); + } + + public void removeUpdate(DocumentEvent e) { + changeHandler(); + } + + public void changedUpdate(DocumentEvent e) { + changeHandler(); + } + + protected void changeHandler() { + if (setting) { + return; + } + setPopupVisible(true); + this.item = textField.getText(); + TreeNode root = (TreeNode) tree.getModel().getRoot(); + TreePath parent = new TreePath(root); + TreeNode node = (TreeNode) parent.getLastPathComponent(); + dealSamePath(parent,node,textField); + this.getEditorComponent().requestFocus(); + } + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/FilterComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/FilterComboBox.java new file mode 100644 index 0000000000..e3cb92a314 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/FilterComboBox.java @@ -0,0 +1,128 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Component; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.ComboBoxEditor; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import com.fr.design.gui.icombobox.filter.Filter; +import com.fr.design.gui.icombobox.filter.StartsWithFilter; +import com.fr.design.gui.itextfield.UITextField; + +/** + * peter:这个类的大部分代码都是抄的,细节我也没有极度关注. + * 使用的时候,只需要做一个Filter类,就可以了. + * 数据以List的形式放到报表里面去 + */ +public class FilterComboBox extends ExtendedComboBox { + private Filter filter; + + public FilterComboBox() { + this(new ArrayList()); + this.setEditable(true); + } + + public FilterComboBox(List itemList) { + this(new StartsWithFilter(), itemList); + } + + public FilterComboBox(Filter filter, List itemList) { + this.filter = filter; + + setModel(new FilterableComboBoxModel(itemList)); + setEditor(new FilterComboBoxEditor()); + setEditable(true); + } + + public void setItemArray(T[] objectArray) { + List itemList = new ArrayList(); + if(objectArray != null) { + for(int i = 0; i < objectArray.length; i++) { + itemList.add(objectArray[i]); + } + } + + this.setItemList(itemList); + } + + public void setItemList(List itemList) { + ((FilterableComboBoxModel)this.getModel()).setPrefix(""); + ((FilterableComboBoxModel)this.getModel()).setItemList(itemList); + } + + class FilterComboBoxEditor implements ComboBoxEditor, DocumentListener { + private Object item; + + public UITextField textField; + private volatile boolean filtering = false; + private volatile boolean setting = false; + + public FilterComboBoxEditor() { + textField = new UITextField(15); + textField.getDocument().addDocumentListener(this); + } + + public Component getEditorComponent() { + return textField; + } + + public void setItem(Object item) { + if (filtering) { + return; + } + this.item = item; + + this.setting = true; + String newText = (item == null) ? "" : item.toString(); + textField.setText(newText); + this.setting = false; + } + + public Object getItem() { + return this.item; + } + + public void selectAll() { + textField.selectAll(); + } + + public void addActionListener(ActionListener l) { + textField.addActionListener(l); + } + + public void removeActionListener(ActionListener l) { + textField.removeActionListener(l); + } + + public void insertUpdate(DocumentEvent e) { + handleChange(); + } + + public void removeUpdate(DocumentEvent e) { + handleChange(); + } + + public void changedUpdate(DocumentEvent e) { + handleChange(); + } + + protected void handleChange() { + if (setting) { + return; + } + + filtering = true; + + ((FilterableComboBoxModel) getModel()).setSelectedItem(textField.getText()); + ((FilterableComboBoxModel) getModel()).setPrefix(textField.getText()); + this.item = textField.getText(); + + setPopupVisible(true); + filtering = false; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/FilterableComboBoxModel.java b/designer_base/src/com/fr/design/gui/icombobox/FilterableComboBoxModel.java new file mode 100644 index 0000000000..e9edbee656 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/FilterableComboBoxModel.java @@ -0,0 +1,103 @@ +package com.fr.design.gui.icombobox; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.swing.AbstractListModel; +import javax.swing.MutableComboBoxModel; + +import com.fr.design.gui.icombobox.filter.Filter; +import com.fr.design.gui.icombobox.filter.StartsWithFilter; + +public class FilterableComboBoxModel extends AbstractListModel implements MutableComboBoxModel { + private List itemList; + private Filter filter = new StartsWithFilter(); + private String prefix = ""; + private List filteredItems; + private Object selectedItem; + + public FilterableComboBoxModel(List items) { + this.itemList = new ArrayList(items); + filteredItems = new ArrayList(items.size()); + updateFilteredItems(); + } + + public void addElement(Object obj) { + itemList.add(obj); + updateFilteredItems(); + } + + public void removeElement(Object obj) { + itemList.remove(obj); + updateFilteredItems(); + } + + public void removeElementAt(int index) { + itemList.remove(index); + updateFilteredItems(); + } + + public void setItemList(List itemList) { + this.itemList = itemList; + updateFilteredItems(); + } + + public void insertElementAt(Object obj, int index) { + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + updateFilteredItems(); + } + + protected void updateFilteredItems() { + fireIntervalRemoved(this, 0, filteredItems.size()); + filteredItems.clear(); + + if (filter == null) { + filteredItems.addAll(itemList); + } else { + // alex:先加一个NPE判断 + if (itemList != null) { + for (Iterator iterator = itemList.iterator(); iterator.hasNext();) { + Object item = iterator.next(); + if (filter.accept(prefix, item)) { + filteredItems.add(item); + } + } + } + } + + fireIntervalAdded(this, 0, filteredItems.size()); + } + + public int getSize() { + return filteredItems.size(); + } + + public Object getElementAt(int index) { + return filteredItems.get(index); + } + + public Object getSelectedItem() { + return selectedItem; + } + + public void setSelectedItem(Object val) { + if ((selectedItem == null) && (val == null)) { + return; + } + + if ((selectedItem != null) && selectedItem.equals(val)) { + return; + } + + if ((val != null) && val.equals(selectedItem)) { + return; + } + + selectedItem = val; + fireContentsChanged(this, -1, -1); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/FixedHeightComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/FixedHeightComboBox.java new file mode 100644 index 0000000000..e776a5242c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/FixedHeightComboBox.java @@ -0,0 +1,103 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; + +import javax.swing.JComboBox; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.basic.ComboPopup; + + +/* + * 下拉框高度固定 + */ +public class FixedHeightComboBox extends FilterComboBox { + private static final long serialVersionUID = 1L; + private static final int VALUE120 = 120; + + public FixedHeightComboBox() { + super(); + } + + public void setUI(ComboBoxUI ui) { + ui = new UI(); + super.setUI(ui); + } + + /** + * 更新UI + */ + public void updateUI() { + setUI(new UI()); + } + + @SuppressWarnings("unchecked") + @Override + public T getSelectedItem() { + return (T) dataModel.getSelectedItem(); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.width = VALUE120; + return dim; + } + + class UI extends UIBasicComboBoxUI { + protected ComboPopup createPopup() { + Popup popup = new Popup(comboBox); + popup.getAccessibleContext().setAccessibleParent(comboBox); + return popup; + } + + public javax.swing.plaf.basic.ComboPopup getPopup() { + return popup; + } + } + + class Popup extends ExtendedComboPopup { + private static final long serialVersionUID = 1L; + + public Popup(JComboBox combo) { + super(combo); + } + + public void show() { + setListSelection(comboBox.getSelectedIndex()); + Point location = getPopupLocation(); + show(comboBox, location.x, location.y); + } + + private void setListSelection(int selectedIndex) { + if (selectedIndex == -1) { + list.clearSelection(); + } else { + list.setSelectedIndex(selectedIndex); + list.ensureIndexIsVisible(selectedIndex); + } + } + + private Point getPopupLocation() { + Dimension popupSize = comboBox.getSize(); + + // reduce the width of the scrollpane by the insets so that + // the popup + // is the same width as the combo box. + popupSize.setSize(popupSize.width, 120); + Rectangle popupBounds = computePopupBounds(0, comboBox.getBounds().height, popupSize.width, popupSize.height); + Dimension scrollSize = popupBounds.getSize(); + Point popupLocation = popupBounds.getLocation(); + + scroller.setMaximumSize(scrollSize); + scroller.setPreferredSize(scrollSize); + scroller.setMinimumSize(scrollSize); + + list.revalidate(); + + return popupLocation; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/FunctionComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/FunctionComboBox.java new file mode 100644 index 0000000000..96371eeab5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/FunctionComboBox.java @@ -0,0 +1,69 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import java.awt.Component; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JList; + +import com.fr.data.core.DataCoreUtils; +import com.fr.data.util.function.DataFunction; + +/** + * DataFunction combobox. + */ +public class FunctionComboBox extends UIComboBox { + + /** + * Constructor. + */ + public FunctionComboBox(DataFunction[] functionArray) { + this.setModel(new DefaultComboBoxModel(functionArray)); + this.setRenderer(functionCellRenderer); + } + + /** + * Return function. + */ + public DataFunction getFunction() { + return (DataFunction) this.getSelectedItem(); + } + + /** + * Set function. + */ + public void setFunction(DataFunction function) { + if (function == null) { + return; + } + + DefaultComboBoxModel model = (DefaultComboBoxModel) this.getModel(); + for (int i = 0; i < model.getSize(); i++) { + DataFunction tmpFunction = (DataFunction) model.getElementAt(i); + if (tmpFunction == null) { + continue; + } + + if (function.getClass().equals(tmpFunction.getClass())) { + this.setSelectedIndex(i); + break; + } + } + } + + UIComboBoxRenderer functionCellRenderer = new UIComboBoxRenderer() { + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof DataFunction) { + DataFunction function = (DataFunction) value; + this.setText(DataCoreUtils.getFunctionDisplayName(function)); + } + + return this; + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/IntComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/IntComboBox.java new file mode 100644 index 0000000000..34da3a4cb7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/IntComboBox.java @@ -0,0 +1,51 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import java.awt.Component; + +import javax.swing.JList; + +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; + +/** + * Int combobox. + * @author zhou + * @since 2012-6-1下午2:00:14 + */ +public class IntComboBox extends UIComboBox { + public IntComboBox() { + this.setRenderer(new UIComboBoxRenderer() { + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof Integer) { + this.setText(" "+value + " "); + } + + return this; + } + }); + } + + public int getSelectedInt() { + if (this.getSelectedItem() == null) { + return -1; + } + return ((Integer)this.getSelectedItem()).intValue(); + } + + public void setSelectedInt(int selectedInt) { + int index = -1; + for (int i = 0; i < this.getItemCount(); i++) { + if (((Integer) this.getItemAt(i)).intValue() == selectedInt) { + index = i; + break; + } + } + this.setSelectedIndex(index); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/LazyComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/LazyComboBox.java new file mode 100644 index 0000000000..5ff9330295 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/LazyComboBox.java @@ -0,0 +1,212 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import java.awt.Dimension; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.basic.BasicComboPopup; + +import com.fr.general.Inter; + +/** + * @author richer + * @since 6.5.5 创建于2011-6-15 延迟加载的下拉框 + */ +public abstract class LazyComboBox extends UIComboBox implements PopupMenuListener { + protected boolean loaded = false; + private List ls = new ArrayList(); + private Object initialSelected = null; + private static final int NUM=80; + + public static final Object PENDING = new Object() { + + @Override + public String toString() { + return Inter.getLocText("Loading") + "..."; + } + }; + + public LazyComboBox() { + super(); + this.setEditor(new FilterComboBoxEditor()); + addPopupMenuListener(this); +// updateUI(); + } + + public void setLoaded(boolean loaded) { + this.loaded = loaded; + } + + public abstract Object[] load(); + + public void setSelectedItem(Object anObject) { + initialSelected = anObject; + if (loaded) { + super.setSelectedItem(anObject); + } else { + + setModel(new DefaultComboBoxModel(new Object[] { anObject })); + super.setSelectedItem(anObject); + } + } + + /** + * 通过调用该方法,在点击下拉框按钮之前就加载好数据 + */ + public void loadInstant() { + if (loaded) { + return; + } + setModel(new DefaultComboBoxModel(load())); + loaded = true; + } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + if (loaded) { + return; + } + DefaultComboBoxModel loadingModel = new DefaultComboBoxModel(new String[]{"", Inter.getLocText("Loading") + "..."}); + LazyComboBox.this.setModel(loadingModel); + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + final Object selectedObj = getSelectedItem(); + loadList(); + return null; + } + + @Override + public void done() { + LazyComboBox.this.updateUI(); + LazyComboBox.this.fireEvent(); + LazyComboBox.this.showPopup(); + } + + }.execute(); + + + } + + /** + * 计算加载下拉列表 + */ + public void loadList() { + DefaultComboBoxModel model = new DefaultComboBoxModel(load()); + model.setSelectedItem(initialSelected); + LazyComboBox.this.setModel(model); + LazyComboBox.this.selectedItemReminder = initialSelected ; + loaded = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + + } + + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + + } + + public void addClickListener(EventListener l) { + if (ls == null) { + ls = new ArrayList(); + } + ls.add(l); + } + + public void fireEvent() { + for (int i = 0, n = ls.size(); i < n; i++) { + ls.get(i).fireEvent(); + } + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.width = NUM; + return dim; + } + + private static class LazyPopMenu extends BasicComboPopup { + + public LazyPopMenu(final JComboBox combo) { + super(combo); + LazyComboBox comboc = (LazyComboBox) combo; + comboc.addClickListener(new EventListener() { + + @Override + public void fireEvent() { + LazyPopMenu.this.show(); + combo.showPopup(); + } + }); + } + } + + private interface EventListener { + void fireEvent(); + } + + class FilterComboBoxEditor extends UIComboBoxEditor implements DocumentListener { + private Object item; + private volatile boolean filtering = false; + private volatile boolean setting = false; + + public FilterComboBoxEditor() { + super(); + textField.getDocument().addDocumentListener(this); + } + + public void setItem(Object item) { + if (filtering) { + return; + } + this.item = item; + + this.setting = true; + String newText = (item == null) ? "" : item.toString(); + textField.setText(newText); + this.setting = false; + } + + public Object getItem() { + return this.item; + } + + public void insertUpdate(DocumentEvent e) { + handleChange(); + } + + public void removeUpdate(DocumentEvent e) { + handleChange(); + } + + public void changedUpdate(DocumentEvent e) { + handleChange(); + } + + protected void handleChange() { + if (setting) { + return; + } + filtering = true; + String xx = textField.getText(); + LazyComboBox.this.setSelectedItem(xx); + this.item = textField.getText(); + + setPopupVisible(true); + filtering = false; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/LazyComboBoxTest.java b/designer_base/src/com/fr/design/gui/icombobox/LazyComboBoxTest.java new file mode 100644 index 0000000000..dc1e449e86 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/LazyComboBoxTest.java @@ -0,0 +1,62 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import java.awt.BorderLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import com.fr.base.FRContext; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.layout.FRGUIPaneFactory; +import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; + +/** + * @author richer + * @since 6.5.5 创建于2011-6-15 + */ +public class LazyComboBoxTest { + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(new WindowsLookAndFeel()); + } catch (UnsupportedLookAndFeelException e1) { + FRContext.getLogger().error(e1.getMessage(), e1); + } + JFrame f = new JFrame(); + JPanel p = (JPanel) f.getContentPane(); + p.setLayout(FRGUIPaneFactory.createBorderLayout()); + + LazyComboBox lc = new LazyComboBox() { + + @Override + public Object[] load() { + Object[] m = new String[] { "aa", "bb", "cc" }; + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + FRContext.getLogger().error(e.getMessage(), e); + } + return m; + } + }; + lc.setEditable(true); + final UITextField jT = new UITextField(); + p.add(jT, BorderLayout.SOUTH); + lc.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + jT.setText(e.getItem().toString()); + } + }); + p.add(lc, BorderLayout.NORTH); + f.setSize(300, 400); + f.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/LineComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/LineComboBox.java new file mode 100644 index 0000000000..8e95b0f230 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/LineComboBox.java @@ -0,0 +1,148 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JLabel; +import javax.swing.JList; + +import com.fr.base.FRContext; +import com.fr.base.GraphHelper; +import com.fr.base.ScreenResolution; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.icombobox.UIComboBoxRenderer; +import com.fr.general.FRFont; +import com.fr.general.Inter; +import com.fr.stable.Constants; + + +/** + * Combobox for selecting line styles. + */ +public class LineComboBox extends UIComboBox { + /** + * Constructor. + * + * @param lineStyleArray the array of lineStyle. + */ + public LineComboBox(int[] lineStyleArray) { + //copy lineStyle. + Integer[] lineStyleIntegerArray = new Integer[lineStyleArray.length]; + + for (int i = 0; i < lineStyleArray.length; i++) { + lineStyleIntegerArray[i] = new Integer(lineStyleArray[i]); + } + + this.setModel(new DefaultComboBoxModel(lineStyleIntegerArray)); + + this.setRenderer(new LineCellRenderer()); + } + + /** + * Get selected line style. + */ + public int getSelectedLineStyle() { + int style = ((Integer) getSelectedItem()).intValue(); + + return (style < 0) ? Constants.LINE_NONE : style; + } + + /** + * Set the selected line style. + */ + public void setSelectedLineStyle(int style) { + this.setSelectedItem(new Integer(style)); + } + + /** + * CellRenderer. + */ + class LineCellRenderer extends UIComboBoxRenderer { + public Component getListCellRendererComponent( + JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel comp= (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + this.style = ((Integer) value).intValue(); + comp.setText(null); + return comp; + } + + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D) g; + + Dimension d = getSize(); + g2d.setColor(getForeground()); + + FRFont font = FRContext.getDefaultValues().getFRFont(); + int resolution = ScreenResolution.getScreenResolution(); + Font rfont = font.applyResolutionNP(resolution); + g2d.setFont(rfont); + FontMetrics fm = GraphHelper.getFontMetrics(rfont); + if (style == Constants.LINE_NONE) { + //draw "none" string + GraphHelper.drawString(g2d, Inter.getLocText("None"), 4, (d.height - fm.getHeight()) / 2 + fm.getAscent()); + } else { + GraphHelper.drawLine(g2d, 4, d.height / 2, d.width - 8, d.height / 2, style); + } + + if(isShowAxisWithLineStyle()) { // 带有坐标轴箭头的样式. + drawArrow(g2d, new Point2D.Double(4, d.height / 2), new Point2D.Double(d.width - 8, d.height/2)); + } + } + + private void drawArrow(Graphics2D g2d, Point2D p0, Point2D p1) { + Point2D s = new Point2D.Double(p1.getX() - p0.getX(), p1.getY() - p0.getY()); + Point2D t = new Point2D.Double(); + double d1 = p0.distance(p1); + //d2-d5设定箭头的大小,p1-p2为坐标轴的延长线,p2-p5-p3-p6为箭头4个点的具体位置 + double d2 = 9; + double d3 = 15; + double d4 = 7; + double d5 = 3; + t.setLocation(d2 * s.getX() / d1, d2 * s.getY() / d1); + Point2D p2 = new Point2D.Double(p1.getX() + t.getX(), p1.getY() + t.getY()); + t.setLocation(d3 * s.getX() / d1, d3 * s.getY() / d1); + Point2D p3 = new Point2D.Double(p1.getX() + t.getX(), p1.getY() + t.getY()); + t.setLocation(d4 * s.getX() / d1, d4 * s.getY() / d1); + Point2D p4 = new Point2D.Double(p1.getX() + t.getX(), p1.getY() + t.getY()); + Point2D p5 = new Point2D.Double(p4.getX() + s.getY() / d1 * d5, p4.getY() - s.getX() / d1 * d5); + Point2D p6 = new Point2D.Double(p4.getX() - s.getY() / d1 * d5, p4.getY() + s.getX() / d1 * d5); + + GeneralPath arrow = new GeneralPath(); + arrow.moveTo((float) p2.getX() - 10, (float) p2.getY()); + arrow.lineTo((float) p5.getX() - 10, (float) p5.getY()); + arrow.lineTo((float) p3.getX() - 10, (float) p3.getY()); + arrow.lineTo((float) p6.getX() - 10, (float) p6.getY()); + arrow.closePath(); + + g2d.draw(arrow); + g2d.fill(arrow); + } + + private boolean isShowAxisWithLineStyle() { + return style == Constants.LINE_CHART_MED_ARROW + || style == Constants.LINE_CHART_THICK_ARROW || style == Constants.LINE_CHART_THIN_ARROW; + } + + public Dimension getPreferredSize() { + return new Dimension(60, 16); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + private int style = Constants.LINE_NONE; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/ParameterComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/ParameterComboBox.java new file mode 100644 index 0000000000..0ca9c91d10 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/ParameterComboBox.java @@ -0,0 +1,87 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; + +import com.fr.base.Parameter; +import com.fr.design.DesignModelAdapter; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.general.ComparatorUtils; + +public class ParameterComboBox extends UIComboBox { + + public ParameterComboBox() { + this.initComponents(); + } + + private void initComponents() { + //render + this.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof com.fr.base.Parameter) { + this.setText(((Parameter) value).toString()); + } + + return this; + } + }); + + //update parameter items + updateParaItems(); + } + + /** + * Update the parameter items of the comboBox + */ + public void updateParaItems() { + //model + DesignModelAdapter designModel = DesignModelAdapter.getCurrentModelAdapter(); + + this.removeAllItems(); + if (designModel != null) { + Parameter[] paras = designModel.getParameters(); + List paraNameList = new ArrayList(); + for (int i = 0; i < paras.length; i++) { + String paraName = paras[i].getName(); + if (!paraNameList.contains(paraName)) { + paraNameList.add(paraName); + this.addItem(paras[i]); + } + + } + } + } + + + @Override + public Parameter getSelectedItem() { + if (super.getSelectedItem() instanceof Parameter) { + return (Parameter) super.getSelectedItem(); + } else if (super.getSelectedItem() instanceof String && ((String) super.getSelectedItem()).startsWith("$")) { + return new Parameter(((String) super.getSelectedItem()).substring(1)); + } + return new Parameter(); + } + + public void setSelectedParameter(Parameter parameter) { + if (parameter == null) { + return; + } + for (int i = 0; i < this.getItemCount(); i++) { + if (ComparatorUtils.equals(((Parameter) this.getItemAt(i)).getName(), parameter.getName())) { + this.setSelectedIndex(i); + return; + } + } + //august:加入itemlist里面没有,应该加进去,不然就不显示了 + this.addItem(parameter); + this.setSelectedItem(parameter); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/SortOrderComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/SortOrderComboBox.java new file mode 100644 index 0000000000..094ab73d58 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/SortOrderComboBox.java @@ -0,0 +1,73 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.icombobox; + +import java.awt.Component; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JList; + +import com.fr.data.util.SortOrder; +import com.fr.general.Inter; + +/** + * Sort order combo box. + */ +public class SortOrderComboBox extends UIComboBox { + /** + * Constructor. + */ + public SortOrderComboBox() { + this(SortOrderComboBox.SortOrderArray); + } + + /** + * Constructor. + */ + public SortOrderComboBox(SortOrder[] sortOrderArray) { + this.setModel(new DefaultComboBoxModel(sortOrderArray)); + this.setRenderer(sortOrderCellRenderer); + } + + /** + * Return selected SortOrder. + */ + public SortOrder getSortOrder() { + return (SortOrder) this.getSelectedItem(); + } + + /** + * Set selected SortOrder. + */ + public void setSortOrder(SortOrder sortOrder) { + this.setSelectedItem(sortOrder); + } + + UIComboBoxRenderer sortOrderCellRenderer = new UIComboBoxRenderer() { + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof SortOrder) { + SortOrder sortOrder = (SortOrder) value; + + if (sortOrder.getOrder() == SortOrder.ASC) { + this.setText(Inter.getLocText("Sort-Ascending")); + } else if (sortOrder.getOrder() == SortOrder.DESC) { + this.setText(Inter.getLocText("Sort-Descending")); + } else if (sortOrder.getOrder() == SortOrder.ORIGINAL) { + this.setText(Inter.getLocText("Sort-Original")); + } + } + + return this; + } + }; + + private static SortOrder[] SortOrderArray = new SortOrder[]{ + new SortOrder(SortOrder.ASC), + new SortOrder(SortOrder.DESC), + new SortOrder(SortOrder.ORIGINAL) + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/TreeComboBoxUI.java b/designer_base/src/com/fr/design/gui/icombobox/TreeComboBoxUI.java new file mode 100644 index 0000000000..c001cadad7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/TreeComboBoxUI.java @@ -0,0 +1,95 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.JComponent; +import javax.swing.plaf.basic.BasicComboBoxUI; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.stable.Constants; + +/** + * + * @author zhou + * @since 2012-5-9下午4:33:07 + */ +public class TreeComboBoxUI extends BasicComboBoxUI implements MouseListener { + + private boolean isRollover = false; + + public TreeComboBoxUI() { + super(); + } + + @Override + protected UIButton createArrowButton() { + arrowButton = new UIButton(UIConstants.ARROW_DOWN_ICON); + ((UIButton) arrowButton).setRoundBorder(true, Constants.LEFT); + arrowButton.addMouseListener(this); + comboBox.addMouseListener(this); + return (UIButton) arrowButton; + } + + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color linecolor = null; + if (comboBox.isPopupVisible()) { + linecolor = UIConstants.LINE_COLOR; + arrowButton.setSelected(true); + } else if (isRollover) { + linecolor = UIConstants.LIGHT_BLUE; + } else { + linecolor = UIConstants.LINE_COLOR; + arrowButton.setSelected(false); + } + g2d.setColor(linecolor); + if (!comboBox.isPopupVisible()) { + g2d.drawRoundRect(0, 0, c.getWidth() - arrowButton.getWidth() + 3, c.getHeight() - 1, UIConstants.LARGEARC, UIConstants.LARGEARC); + } else { + g2d.drawRoundRect(0, 0, c.getWidth() , c.getHeight() + 3, UIConstants.LARGEARC, UIConstants.LARGEARC ); + g2d.drawLine(0, c.getHeight()-1, c.getWidth(), c.getHeight()-1); + } + } + + + + private void setRollover(boolean isRollover) { + if (this.isRollover != isRollover) { + this.isRollover = isRollover; + comboBox.repaint(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + setRollover(true); + } + + @Override + public void mouseExited(MouseEvent e) { + setRollover(false); + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxEditor.java b/designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxEditor.java new file mode 100644 index 0000000000..c1056e135b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxEditor.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.icombobox; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.DrawRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.metal.MetalComboBoxEditor; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-18 + * Time: 上午11:04 + */ +public class UIBasicComboBoxEditor extends MetalComboBoxEditor { + + public UIBasicComboBoxEditor() { + super(); + + editor = new JTextField("", 9) { + // workaround for 4530952 + public void setText(String s) { + if (ComparatorUtils.equals(getText(),s)) { + return; + } + + super.setText(s); + } + }; + + editor.setBorder(new EditorBorder()); + } + + class EditorBorder extends AbstractBorder { + + /** + * @see javax.swing.border.Border#getBorderInsets(java.awt.Component) + */ + public Insets getBorderInsets(Component c) { + // Note: I just adjusted insets until + // editable and non-editable combo boxes look equal + return new Insets( + 1, + ThemeUtils.COMBO_INSETS.left + 1, + 1, + 0); + } + + /** + * @see javax.swing.border.Border#paintBorder(java.awt.Component, java.awt.Graphics, int, int, int, int) + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + JComponent combo = (JComponent) editor.getParent(); + + if (combo.getBorder() == null) { + return; + } + drawXpBorder(c, g, x, y, w, h); + + } + } + + private void drawXpBorder(Component c, Graphics g, int x, int y, int w, int h) { + // paint border background - next parent is combo box + Color bg = c.getParent().getParent().getBackground(); + g.setColor(bg); + g.drawLine(x, y, x + w - 1, y); // top + g.drawLine(x, y, x, y + h - 1); // left + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); // bottom + + if (!c.isEnabled()) { + DrawRoutines.drawEditableComboBorder( + g, ThemeUtils.COMBO_BORDER_DISABLED_COLOR, 0, 0, w, h); + } else { + DrawRoutines.drawEditableComboBorder( + g, ThemeUtils.COMBO_BORDER_COLOR, 0, 0, w, h); + } + } + + + /** + * A subclass of BasicComboBoxEditor that implements UIResource. + * BasicComboBoxEditor doesn't implement UIResource + * directly so that applications can safely override the + * cellRenderer property with BasicListCellRenderer subclasses. + *

+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeansTM + * has been added to the java.beans package. + * Please see {@link java.beans.XMLEncoder}. + */ + public static class UIResource extends UIBasicComboBoxEditor + implements javax.swing.plaf.UIResource { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxUI.java b/designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxUI.java new file mode 100644 index 0000000000..7b4d7eb16c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIBasicComboBoxUI.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.icombobox; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboBoxUI; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.plaf.basic.ComboPopup; +import javax.swing.plaf.metal.MetalComboBoxIcon; +import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-18 + * Time: 上午10:57 + */ +public class UIBasicComboBoxUI extends BasicComboBoxUI { + private static final int VALUE100=100; + + // Flag for calculating the display size + protected boolean isDisplaySizeDirty = true; + + // Cached the size that the display needs to render the largest item + protected Dimension cachedDisplaySize = new Dimension(0, 0); + + /** + * 创建UI + * + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIBasicComboBoxUI(); + } + + public void paint(Graphics g, JComponent c) { + } + + protected ComboBoxEditor createEditor() { + return new UIBasicComboBoxEditor.UIResource(); + } + + protected ComboPopup createPopup() { + return new MetalComboPopup(comboBox); + } + + protected JButton createArrowButton() { + JButton button = new UIComboBoxButton(comboBox, + new MetalComboBoxIcon(), + comboBox.isEditable(), + currentValuePane, + listBox); + + button.setMargin(new Insets(0, 0, 0, 0)); + button.putClientProperty("isComboBoxButton", Boolean.TRUE); + + return button; + } + + protected void installComponents() { + super.installComponents(); + + if (arrowButton != null) { + arrowButton.setFocusable(false); + } + } + + /** + * 创建监听 + * + * @return 返回创建的监听 + */ + public PropertyChangeListener createPropertyChangeListener() { + return new TinyPropertyChangeListener(); + } + + /** + * This inner class is marked "public" due to a compiler bug. + * This class should be treated as a "protected" inner class. + * Instantiate it only within subclasses of . + */ + public class TinyPropertyChangeListener extends BasicComboBoxUI.PropertyChangeHandler { + /** + * 属性改变 + * + * @param e 属性改变事件 + */ + public void propertyChange(PropertyChangeEvent e) { + super.propertyChange(e); + String propertyName = e.getPropertyName(); + if (ComparatorUtils.equals(propertyName, "editable")) { + UIComboBoxButton button = (UIComboBoxButton) arrowButton; + button.setIconOnly(comboBox.isEditable()); + isMinimumSizeDirty = true; + isDisplaySizeDirty = true; + comboBox.revalidate(); + } else if (ComparatorUtils.equals(propertyName, "background")) { + Color color = (Color) e.getNewValue(); + listBox.setBackground(color); + } else if (ComparatorUtils.equals(propertyName, "foreground")) { + Color color = (Color) e.getNewValue(); + listBox.setForeground(color); + } + } + } + + /** + * As of Java 2 platform v1.4 this method is no longer used. Do not call or + * override. All the functionality of this method is in the + * MetalPropertyChangeListener. + * + * @deprecated As of Java 2 platform v1.4. + */ + protected void editablePropertyChanged(PropertyChangeEvent e) { + } + + protected LayoutManager createLayoutManager() { + return new TinyComboBoxLayoutManager(); + } + + /** + * This inner class is marked "public" due to a compiler bug. + * This class should be treated as a "protected" inner class. + * Instantiate it only within subclasses of . + */ + public class TinyComboBoxLayoutManager implements LayoutManager { + /** + * 增加布局组件 + * @param name 名字 + * @param comp 组件 + */ + public void addLayoutComponent(String name, Component comp) { + } + + /** + * 去除布局组件 + * @param comp 组件 + */ + public void removeLayoutComponent(Component comp) { + } + + /** + * 最佳布局大小 + * @param parent 容器 + * @return 大小 + */ + public Dimension preferredLayoutSize(Container parent) { + JComboBox cb = (JComboBox) parent; + return parent.getPreferredSize(); + } + + /** + * 最小布局大小 + * @param parent 容器 + * @return 大小 + */ + public Dimension minimumLayoutSize(Container parent) { + JComboBox cb = (JComboBox) parent; + return parent.getMinimumSize(); + } + + /** + * 布局容器 + * @param parent 容器 + */ + public void layoutContainer(Container parent) { + JComboBox cb = (JComboBox) parent; + int width = cb.getWidth(); + int height = cb.getHeight(); + + Rectangle cvb; + + if (comboBox.isEditable()) { + if (arrowButton != null) { + arrowButton.setBounds(width - + ThemeUtils.COMBOBUTTTON_WIDTH, 0, + ThemeUtils.COMBOBUTTTON_WIDTH, height); + } + if (editor != null) { + cvb = rectangleForCurrentValue2(); + editor.setBounds(cvb); + } + } else { + arrowButton.setBounds(0, 0, width, height); + } + } + } + + protected Rectangle rectangleForCurrentValue2() { + int width = comboBox.getWidth(); + int height = comboBox.getHeight(); + Insets insets = getInsets(); + int buttonSize = height - (insets.top + insets.bottom); + + if (arrowButton != null) { + buttonSize = ThemeUtils.COMBOBUTTTON_WIDTH; + } + if (comboBox.getComponentOrientation().isLeftToRight()) { + return new Rectangle(insets.left, + insets.top, + width - (insets.left + insets.right + buttonSize), + height - (insets.top + insets.bottom)); + } else { + return new Rectangle( + insets.left + buttonSize, + insets.top, + width - (insets.left + insets.right + buttonSize), + height - (insets.top + insets.bottom)); + } + } + + /** + * As of Java 2 platform v1.4 this method is no + * longer used. + * + * @deprecated As of Java 2 platform v1.4. + */ + protected void removeListeners() { + if (propertyChangeListener != null) { + comboBox.removePropertyChangeListener(propertyChangeListener); + } + } + + + /** + * @param c the combo box + */ + public Dimension getMinimumSize(JComponent c) { + if (!isMinimumSizeDirty) { + isDisplaySizeDirty = true; // 1.3 + return new Dimension(cachedMinimumSize); + } + + // changed in 1.3 + Insets insets = ThemeUtils.COMBO_INSETS; + Dimension size = getDisplaySize(); + size.width += ThemeUtils.COMBOBUTTTON_WIDTH; + size.width += insets.left + insets.right; + size.height += insets.top + insets.bottom; + + cachedMinimumSize.setSize(size.width, size.height); + isMinimumSizeDirty = false; + + return new Dimension(cachedMinimumSize); + } + + /** + * Copied from BasicComboBoxUI, because isDisplaySizeDirty was declared private!? + * Returns the calculated size of the display area. The display area is the + * portion of the combo box in which the selected item is displayed. This + * method will use the prototype display value if it has been set. + *

+ * For combo boxes with a non trivial number of items, it is recommended to + * use a prototype display value to significantly speed up the display + * size calculation. + * + * @return the size of the display area calculated from the combo box items + * @see javax.swing.JComboBox#setPrototypeDisplayValue + */ + protected Dimension getDisplaySize() { + if (!isDisplaySizeDirty) { + return new Dimension(cachedDisplaySize); + } + Dimension result = new Dimension(); + ListCellRenderer renderer = comboBox.getRenderer(); + if (renderer == null) { + renderer = new DefaultListCellRenderer(); + } + Object prototypeValue = comboBox.getPrototypeDisplayValue(); + if (prototypeValue != null) { + // Calculates the dimension based on the prototype value + result = getSizeForComponent(renderer.getListCellRendererComponent( + listBox, prototypeValue, -1, false, false)); + } else { + // Calculate the dimension by iterating over all the elements in the combo + // box list. + ComboBoxModel model = comboBox.getModel(); + int modelSize = model.getSize(); + Dimension d; + Component cpn; + if (modelSize > 0) { + for (int i = 0; i < modelSize; i++) { + // Calculates the maximum height and width based on the largest + // element + d = getSizeForComponent(renderer.getListCellRendererComponent( + listBox, model.getElementAt(i), -1, false, false)); + result.width = Math.max(result.width, d.width); + result.height = Math.max(result.height, d.height); + } + } else { + result = getDefaultSize(); + + if (comboBox.isEditable()) { + result.width = VALUE100; + } + } + } + if (comboBox.isEditable()) { + Dimension d = editor.getPreferredSize(); + result.width = Math.max(result.width, d.width); + result.height = Math.max(result.height, d.height); + } + // Set the cached value + cachedDisplaySize.setSize(result.width, result.height); + isDisplaySizeDirty = false; + return result; + } + + /* + * Copied from BasicComboBoxUI. + */ + public Dimension getSizeForComponent(Component comp) { + currentValuePane.add(comp); + comp.setFont(comboBox.getFont()); + Dimension d = comp.getPreferredSize(); + currentValuePane.remove(comp); + return d; + } + + /** + * This inner class is marked "public" due to a compiler bug. + * This class should be treated as a "protected" inner class. + * Instantiate it only within subclasses of . + *

+ * This class is now obsolete and doesn't do anything and + * is only included for backwards API compatibility. Do not call or + * override. + * + * @deprecated As of Java 2 platform v1.4. + */ + public class MetalComboPopup extends BasicComboPopup { + + public MetalComboPopup(JComboBox cBox) { + super(cBox); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/UIComboBox.java new file mode 100644 index 0000000000..90944c4496 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIComboBox.java @@ -0,0 +1,206 @@ +package com.fr.design.gui.icombobox; + +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.basic.ComboPopup; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Vector; + +/** + * august:非常beautiful的ComboBox,不支持编辑状态. 内容过长时,鼠标移动过去会有ToolTips,不会有横向滚动条 + * 假如支持编辑,因为UIComboBox的TextField 的绘制 并不是靠Renderer来控制 , + * 它会通过paintCurrentValueBackground()来绘制背景, + * 然后通过paintCurrentValue(),去绘制UIComboBox里显示的值。所考虑情况比现在复杂多多多多多了,所以暂时不支持 + * 另外,项的内容最好不要有图标 + * + * @author zhou + * @since 2012-5-9下午3:18:58 + */ +public class UIComboBox extends JComboBox implements UIObserver, GlobalNameObserver { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private static final int SIZE = 20; + + private static final int SIZE5 = 5; + + private UIObserverListener uiObserverListener; + + private String comboBoxName = ""; + + private GlobalNameListener globalNameListener = null; + + public UIComboBox() { + super(); + init(); + } + + public UIComboBox(ComboBoxModel model) { + super(model); + init(); + } + + public UIComboBox(Object[] items) { + super(items); + init(); + } + + public UIComboBox(Vector items) { + super(items); + init(); + } + + private void init() { + setOpaque(false); + setUI(getUIComboBoxUI()); + setRenderer(new UIComboBoxRenderer()); + setEditor(new UIComboBoxEditor()); + initListener(); + } + + private void initListener() { + if (shouldResponseChangeListener()) { + this.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + fireSetGlobalName(); + } + }); + this.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (uiObserverListener == null) { + return; + } + fireSetGlobalName(); + if (e.getStateChange() == ItemEvent.SELECTED) { + uiObserverListener.doChange(); + } + } + }); + } + } + + private void fireSetGlobalName() { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(comboBoxName); + } + } + + + protected ComboBoxUI getUIComboBoxUI() { + return new UIComboBoxUI(); + } + + /** + * 只允许设置为UIComboBoxRenderer,所以要继承UIComboBoxRenderer + */ + @Override + public void setRenderer(ListCellRenderer aRenderer) { + if (aRenderer instanceof UIComboBoxRenderer) { + super.setRenderer(aRenderer); + } else { + //throw new IllegalArgumentException("Must be UIComboBoxRenderer"); + } + } + + protected ComboPopup createPopup() { + return null; + } + + public void setGlobalName(String name) { + comboBoxName = name; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width + SIZE5, SIZE);//加5的原因在于:render里,每一个项前面了空了一格,要多几像素 + } + + /** + * 鼠标进入事件 + */ + public void mouseEnterEvent() { + + } + + /** + * 鼠标离开事件 + */ + public void mouseExitEvent() { + + } + + /** + * + */ + public void updateUI() { + setUI(getUIComboBoxUI()); + } + + + /** + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * @return + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * + * @return + */ + public boolean shouldResponseNameListener() { + return true; + } + + + /** + * @param args + */ + public static void main(String... args) { + LayoutManager layoutManager = null; + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(layoutManager); + UIComboBox bb = new UIComboBox(new String[]{"", "jerry", "kunsnat", "richer"}); + bb.setEditable(true); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxButton.java b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxButton.java new file mode 100644 index 0000000000..3c19f1e81e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxButton.java @@ -0,0 +1,278 @@ +package com.fr.design.gui.icombobox; + +import com.fr.design.gui.UILookAndFeel; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-13 + * Time: 上午11:23 + */ +public class UIComboBoxButton extends JButton { + + protected JComboBox comboBox; + protected JList listBox; + protected CellRendererPane rendererPane; + protected Icon comboIcon; + protected boolean iconOnly = false; + private static BufferedImage focusImg; + + public final JComboBox getComboBox() { + return comboBox; + } + + public final void setComboBox(JComboBox cb) { + comboBox = cb; + } + + public final Icon getComboIcon() { + return comboIcon; + } + + public final void setComboIcon(Icon i) { + comboIcon = i; + } + + + public final void setIconOnly(boolean isIconOnly) { + iconOnly = isIconOnly; + } + + UIComboBoxButton() { + super(""); + + DefaultButtonModel model = new DefaultButtonModel() { + public void setArmed(boolean armed) { + armed = isPressed() ? true : armed; + super.setArmed(armed); + } + }; + + setModel(model); + + // Set the background and foreground to the combobox colors. + setBackground(UIManager.getColor("ComboBox.background")); + setForeground(UIManager.getColor("ComboBox.foreground")); + + if (focusImg == null) { + ImageIcon icon = UILookAndFeel.loadIcon("ComboBoxFocus.png", this); + + if (icon != null) { + focusImg = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB); + Graphics g = focusImg.getGraphics(); + icon.paintIcon(this, g, 0, 0); + } + } + } + + public UIComboBoxButton(JComboBox cb, Icon i, + boolean onlyIcon, CellRendererPane pane, JList list) { + this(); + comboBox = cb; + comboIcon = i; + rendererPane = pane; + listBox = list; + setEnabled(comboBox.isEnabled()); + } + + /** + * Mostly taken from the swing sources + * + * @see javax.swing.JComponent#paintComponent(Graphics) + */ + public void paintComponent(Graphics g) { + // Note: border was already painted in TinyButtonBorder + boolean leftToRight = getComponentOrientation().isLeftToRight(); + if (comboBox.isEnabled()) { + if (comboBox.isEditable()) { + g.setColor(ThemeUtils.TEXT_BG_COLOR); + } else { + g.setColor(comboBox.getBackground()); + } + } else { + g.setColor(ThemeUtils.TEXT_DISABLED_BG_COLOR); + } + + g.fillRect(1, 1, getWidth() - 2, getHeight() - 2); + if (getParent() != null && getParent().getParent() != null) { + // paint border background - next parent is combo box + Color bg = getParent().getParent().getBackground(); + g.setColor(bg); + } + g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); + drawArrow(g); + Insets insets = new Insets(ThemeUtils.COMBO_INSETS.top, ThemeUtils.COMBO_INSETS.left, + ThemeUtils.COMBO_INSETS.bottom, 0); + int width = getWidth() - (insets.left + insets.right); + int widthFocus = width; + int height = getHeight() - (insets.top + insets.bottom); + if (height <= 0 || width <= 0) { + return; + } + int left = insets.left; + int top = insets.top; + int right = left + (width - 1); + int bottom = top + (height - 1); + int iconWidth = ThemeUtils.COMBOBUTTTON_WIDTH; + int iconLeft = (leftToRight) ? right : left; + // Let the renderer paint + Component c = null; + boolean mustResetOpaque = false; + boolean savedOpaque = false; + + paintRender(g, c, mustResetOpaque, savedOpaque, leftToRight, width, insets, iconWidth, left, top, height); + if (mustResetOpaque) { + JComponent jc = (JComponent) c; + jc.setOpaque(savedOpaque); + } + } + + private void paintRender(Graphics g, Component c, boolean mustResetOpaque, boolean savedOpaque, boolean leftToRight, + int width, Insets insets, int iconWidth, int left, int top, int height) { + boolean paintFocus = false; + if (!iconOnly && comboBox != null) { + ListCellRenderer renderer = comboBox.getRenderer(); + boolean renderPressed = getModel().isPressed(); + c = renderer.getListCellRendererComponent(listBox, comboBox.getSelectedItem(), -1, renderPressed, false); + c.setFont(rendererPane.getFont()); + calculateColor(c, mustResetOpaque, savedOpaque, paintFocus); + int cWidth = width - (insets.right + iconWidth); + boolean shouldValidate = false; + if (c instanceof JPanel) { + shouldValidate = true; + } + if (leftToRight) { + rendererPane.paintComponent(g, c, this, left, top, cWidth, height, shouldValidate); + } else { + rendererPane.paintComponent(g, c, this, left + iconWidth, top, cWidth, height, shouldValidate); + } + if (paintFocus && ThemeUtils.COMBO_FOCUS) { + g.setColor(Color.black); + Graphics2D g2d = (Graphics2D) g; + Rectangle r = new Rectangle(left, top, 2, 2); + TexturePaint tp = new TexturePaint(focusImg, r); + g2d.setPaint(tp); + g2d.draw(new Rectangle(left, top, cWidth, height)); + } + } + } + + private void calculateColor(Component c, boolean mustResetOpaque, boolean savedOpaque, boolean paintFocus) { + if (model.isArmed() && model.isPressed()) { + if (isOpaque()) { + c.setBackground(UIManager.getColor("Button.select")); + } + c.setForeground(comboBox.getForeground()); + } else if (!comboBox.isEnabled()) { + if (isOpaque()) { + c.setBackground(ThemeUtils.TEXT_DISABLED_BG_COLOR); + } else { + comboBox.setBackground(ThemeUtils.TEXT_DISABLED_BG_COLOR); + } + c.setForeground(UIManager.getColor("ComboBox.disabledForeground")); + } else if (comboBox.hasFocus() && !comboBox.isPopupVisible()) { + if (comboBox.isEditable()) { + c.setForeground(ThemeUtils.MAIN_COLOR); + } else { + c.setForeground(UIManager.getColor("ComboBox.selectionForeground")); + } + c.setBackground(UIManager.getColor("ComboBox.focusBackground")); + if (c instanceof JComponent) { + mustResetOpaque = true; + JComponent jc = (JComponent) c; + savedOpaque = jc.isOpaque(); + jc.setOpaque(true); + paintFocus = true; + } + } else { + c.setForeground(comboBox.getForeground()); + c.setBackground(comboBox.getBackground()); + } + } + + private void drawArrow(Graphics g) { + + Color col = null; + + if (!isEnabled()) { + col = ThemeUtils.COMBOBUTT_DISABLED_COLOR; + } else if (model.isPressed()) { + col = ThemeUtils.COMBOBUTT_PRESSED_COLOR; + } else if (model.isRollover()) { + col = ThemeUtils.COMBOBUTT_ROLLOVER_COLOR; + } else { + col = ThemeUtils.COMBOBUTT_COLOR; + } + + g.setColor(col); + + Rectangle buttonRect = new Rectangle( + getWidth() - ThemeUtils.COMBOBUTTTON_WIDTH, + 1, ThemeUtils.COMBOBUTTTON_WIDTH, getHeight() - 2); + drawXpButton(g, buttonRect, col); + + // draw arrow + if (isEnabled()) { + g.setColor(ThemeUtils.COMBO_ARROW_COLOR); + } else { + g.setColor(ThemeUtils.COMBO_ARROW_DISABLED_COLOR); + } + + drawXpArrow(g, buttonRect); + } + + + private void drawXpButton(Graphics g, Rectangle r, Color c) { + int xs = r.x; + int ys = r.y; + int y2 = r.y + r.height; + + Color a = ThemeUtils.COMBO_BORDER_COLOR; + + Color pressedLightColor = ThemeUtils.PRESSED_LIGHT_COLOR; + Color pressedDarkColor = ThemeUtils.PRESSED_DARK_COLOR; + Color rolloverLightColor = ThemeUtils.ROLLOVER_LIGHT_COLOR; + Color rolloverDarkColor = ThemeUtils.ROLLOVER_DARK_COLOR; + Color normalLightColor = ThemeUtils.NORMAL_LIGHT_COLOR; + Color normalDarkColor = ThemeUtils.NORMAL_DARK_COLOR; + Color lightBorderColor = ThemeUtils.WHITE_BORDER_COLOR; + + Graphics2D g2 = (Graphics2D) g; + GradientPaint scrollBarBg = null; + if (!isEnabled()) { + scrollBarBg = new GradientPaint(xs, ys, normalLightColor, xs, y2, normalDarkColor); + } else if (model.isPressed()) { + scrollBarBg = new GradientPaint(xs, ys, pressedLightColor, xs, y2, pressedDarkColor); + } else if (model.isRollover()) { + scrollBarBg = new GradientPaint(xs, ys, rolloverLightColor, xs, y2, rolloverDarkColor); + } else { + scrollBarBg = new GradientPaint(xs, ys, normalLightColor, xs, y2, normalDarkColor); + } + + GradientPaint scrollBarHight = new GradientPaint(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.5f), 0, 7, new Color(1.0f, 1.0f, 1.0f, 0.2f)); + g2.setPaint(scrollBarBg); + g2.fillRoundRect(xs, ys, r.width, r.height, 3, 3);//画渐变的背景 + g2.setPaint(scrollBarHight); + g2.fillRoundRect(xs, ys, r.width, r.height / 2, 3, 3);//画高光 + g2.setColor(a); + g2.drawLine(xs, ys, xs, y2); + g2.setColor(lightBorderColor); + g2.drawRoundRect(xs + 1, ys, r.width - 3, r.height - 1, 1, 1);//画高光线(内发光,0%阻塞) + + } + + private void drawXpArrow(Graphics g, Rectangle r) { + int x = r.x + (r.width - 8) / 2 - 1; + int y = r.y + (r.height - 6) / 2 + 1; + g.drawLine(x + 1, y + 1, x + 7, y + 1); + g.drawLine(x + 2, y + 2, x + 6, y + 2); + g.drawLine(x + 3, y + 3, x + 5, y + 3); + g.drawLine(x + 4, y + 4, x + 4, y + 4); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxEditor.java b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxEditor.java new file mode 100644 index 0000000000..79877fe3db --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxEditor.java @@ -0,0 +1,88 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Component; +import java.awt.event.ActionListener; +import java.lang.reflect.Method; + +import javax.swing.plaf.basic.BasicComboBoxEditor; + +import com.fr.design.gui.itextfield.UITextField; +import com.fr.general.ComparatorUtils; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +public class UIComboBoxEditor extends BasicComboBoxEditor { + protected UITextField textField; + private Object oldValue; + + public UIComboBoxEditor() { + textField = new UITextField(); + textField.setRectDirection(Constants.RIGHT); + } + + @Override + public Component getEditorComponent() { + return textField; + } + + @Override + public void setItem(Object anObject) { + if (anObject != null) { + + textField.setText(anObject.toString()); + oldValue = anObject; + } else { + textField.setText(StringUtils.EMPTY); + } + + } + + @Override + public Object getItem() { + Object newValue = textField.getText(); + if (oldValue != null && !(oldValue instanceof String)) { + // The original value is not a string. Should return the value in it's + // original type. + if(ComparatorUtils.equals(newValue,oldValue.toString())) { + return oldValue; + } else { + // Must take the value from the textField and get the value and cast it to the new type. + Class cls = oldValue.getClass(); + try { + Method method = cls.getMethod("valueOf", new Class[]{String.class}); + newValue = method.invoke(oldValue, new Object[]{textField.getText()}); + } catch (Exception ex) { + // Fail silently and return the newValue (a String object) + } + } + } + return newValue; + + } + + @Override + /** + * + */ + public void selectAll() { + textField.selectAll(); + textField.requestFocus(); + } + + @Override + /** + * + */ + public void addActionListener(ActionListener l) { + textField.addActionListener(l); + } + + @Override + /** + * + */ + public void removeActionListener(ActionListener l) { + textField.removeActionListener(l); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxRenderer.java b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxRenderer.java new file mode 100644 index 0000000000..7674b574f6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxRenderer.java @@ -0,0 +1,35 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.DefaultListCellRenderer; + +import com.fr.design.constants.UIConstants; + +import javax.swing.JList; +import javax.swing.JLabel; + +/** + * + * @author zhou + * @since 2012-5-18上午11:18:30 + */ +public class UIComboBoxRenderer extends DefaultListCellRenderer { + + private static final long serialVersionUID = 1L; + + public UIComboBoxRenderer() { + super(); + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + cellHasFocus = cellHasFocus && !this.isEnabled(); + JLabel renderer =(JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + renderer.setForeground(Color.black); + list.setSelectionBackground(UIConstants.FLESH_BLUE); + list.setSelectionForeground(Color.black); + renderer.setText(" " + renderer.getText()); + return renderer; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxUI.java b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxUI.java new file mode 100644 index 0000000000..28ae0aebf7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIComboBoxUI.java @@ -0,0 +1,250 @@ +package com.fr.design.gui.icombobox; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicComboBoxUI; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.plaf.basic.ComboPopup; + +import com.fr.design.constants.UIConstants; +import sun.swing.DefaultLookup; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; + +/** + * @author zhou F + * @since 2012-5-9下午4:33:07 + */ +public class UIComboBoxUI extends BasicComboBoxUI implements MouseListener { + + protected boolean isRollover = false; + + public UIComboBoxUI() { + super(); + } + + + @Override + protected UIButton createArrowButton() { + arrowButton = new UIButton(UIConstants.ARROW_DOWN_ICON) { + public boolean shouldResponseChangeListener() { + return false; + } + }; + ((UIButton) arrowButton).setRoundBorder(true, Constants.LEFT); + arrowButton.addMouseListener(this); + comboBox.addMouseListener(this); + return (UIButton) arrowButton; + } + + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + Color linecolor = UIConstants.LINE_COLOR; + if (comboBox.isPopupVisible()) { + arrowButton.setSelected(true); + } else { + linecolor = UIConstants.LINE_COLOR; + arrowButton.setSelected(false); + } + g2d.setColor(linecolor); + if (!comboBox.isPopupVisible()) { + g2d.drawRoundRect(0, 0, c.getWidth() - arrowButton.getWidth() + 3, c.getHeight() - 1, UIConstants.LARGEARC, UIConstants.LARGEARC); + } else { + g2d.drawRoundRect(0, 0, c.getWidth(), c.getHeight() + 3, UIConstants.LARGEARC, UIConstants.LARGEARC); + g2d.drawLine(0, c.getHeight() - 1, c.getWidth(), c.getHeight() - 1); + } + } + + /** + * 覆盖之 + */ + @Override + public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) { + ListCellRenderer renderer = comboBox.getRenderer(); + Component c; + + if (hasFocus && !isPopupVisible(comboBox)) { + c = renderer.getListCellRendererComponent(listBox, + comboBox.getSelectedItem(), + -1, + true, + false); + } else { + c = renderer.getListCellRendererComponent(listBox, + comboBox.getSelectedItem(), + -1, + false, + false); + c.setBackground(UIManager.getColor("ComboBox.background")); + } + c.setFont(comboBox.getFont()); + if (hasFocus && !isPopupVisible(comboBox)) { + if (comboBox.isEnabled()) { + c.setForeground(Color.black); + c.setBackground(Color.white); + } else { + c.setForeground(DefaultLookup.getColor( + comboBox, this, "ComboBox.disabledForeground", comboBox.getForeground())); + c.setBackground(DefaultLookup.getColor( + comboBox, this, "ComboBox.disabledBackground", comboBox.getBackground())); + } + } else { + if (comboBox.isEnabled()) { + c.setForeground(comboBox.getForeground()); + c.setBackground(comboBox.getBackground()); + } else { + c.setForeground(DefaultLookup.getColor( + comboBox, this, "ComboBox.disabledForeground", comboBox.getForeground())); + c.setBackground(DefaultLookup.getColor( + comboBox, this, "ComboBox.disabledBackground", comboBox.getBackground())); + + } + } + + boolean shouldValidate = false; + if (c instanceof JPanel) { + shouldValidate = true; + } + + int x = bounds.x, y = bounds.y, w = bounds.width, h = bounds.height; + + currentValuePane.paintComponent(g, c, comboBox, x, y, w, h, shouldValidate); + } + + @Override + protected ComboPopup createPopup() { + if (comboBox instanceof UIComboBox) { + if (((UIComboBox) comboBox).createPopup() != null) { + return ((UIComboBox) comboBox).createPopup(); + } + } + return new UIComboPopup(comboBox); + } + + private void setRollover(boolean isRollover) { + if (this.isRollover != isRollover) { + this.isRollover = isRollover; + comboBox.repaint(); + } + } + + @Override + public void mouseEntered(MouseEvent e) { + if (comboBox != null) { + ((UIComboBox) comboBox).mouseEnterEvent(); + arrowButton.getModel().setRollover(true); + setRollover(true); + } + } + + @Override + public void mouseExited(MouseEvent e) { + if (comboBox != null) { + ((UIComboBox) comboBox).mouseExitEvent(); + arrowButton.getModel().setRollover(false); + setRollover(false); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + private class UIComboPopup extends BasicComboPopup { + public UIComboPopup(JComboBox comboBox) { + super(comboBox); + } + + @Override + protected JScrollPane createScroller() { + return new UIScrollPane(list); + } + + // august:重载paintBorder方法 来画出我们想要的边框.. + @Override + public void paintBorder(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + g2.setColor(UIConstants.LINE_COLOR); + g2.drawRoundRect(0, -arrowButton.getHeight(), getWidth() - 1, getHeight() + arrowButton.getHeight() - 1, UIConstants.ARC, UIConstants.ARC); + } + + @Override + public void setVisible(boolean b) { + super.setVisible(b); + if (!b) { + comboBox.repaint(); + } + } + + @Override + protected JList createList() { + return new JList(comboBox.getModel()) { + + @Override + public void processMouseEvent(MouseEvent e) { + if (e.isControlDown()) { + e = new MouseEvent((Component) e.getSource(), e.getID(), e.getWhen(), e.getModifiers() ^ InputEvent.CTRL_MASK, e.getX(), e.getY(), e.getClickCount(), + e.isPopupTrigger()); + } + super.processMouseEvent(e); + } + + @Override + public String getToolTipText(MouseEvent event) { + int index = locationToIndex(event.getPoint()); + if (index != -1) { + Object value = getModel().getElementAt(index); + ListCellRenderer renderer = getCellRenderer(); + Component rendererComp = renderer.getListCellRendererComponent(this, value, index, true, false); + if (rendererComp.getPreferredSize().width > getVisibleRect().width) { + String tips = (rendererComp instanceof JComponent) ? ((JComponent) rendererComp).getToolTipText() : null; + if (tips == null && value instanceof String) { + tips = (String) value; + } + return tips; + } else { + return null; + } + } + return null; + } + + @Override + public Point getToolTipLocation(MouseEvent event) { + int index = locationToIndex(event.getPoint()); + if (index != -1 && StringUtils.isNotEmpty(getToolTipText(event))) { + Rectangle cellBounds = getCellBounds(index, index); + return new Point(event.getX(), cellBounds.y + cellBounds.height); + } + return null; + } + }; + } + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/UIDictionaryComboBox.java b/designer_base/src/com/fr/design/gui/icombobox/UIDictionaryComboBox.java new file mode 100644 index 0000000000..ad876f87a4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/UIDictionaryComboBox.java @@ -0,0 +1,44 @@ +package com.fr.design.gui.icombobox; + +import javax.swing.*; +import java.awt.*; + +public class UIDictionaryComboBox extends UIComboBox { + private static final long serialVersionUID = -19512646054322609L; + private T[] keys; + private String[] values; + + public UIDictionaryComboBox(T[] keys, String[] displays) { + super(); + this.initComboBox(keys, displays); + } + + private void initComboBox(T[] keys, String[] displays) { + this.keys = keys; + this.values = displays; + this.setModel(new DefaultComboBoxModel(keys)); + this.setRenderer(new UIComboBoxRenderer() { + /** + * + */ + private static final long serialVersionUID = -6497147896537056134L; + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + for (int i = 0, len = UIDictionaryComboBox.this.keys.length; i < len; i++) { + if (UIDictionaryComboBox.this.keys[i].equals(value)) { + this.setText(" " + UIDictionaryComboBox.this.values[i]); + break; + } + } + return this; + } + }); + } + + @SuppressWarnings("unchecked") + public T getSelectedItem() { + return (T)super.getSelectedItem(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/filter/Filter.java b/designer_base/src/com/fr/design/gui/icombobox/filter/Filter.java new file mode 100644 index 0000000000..bdded169d9 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/filter/Filter.java @@ -0,0 +1,8 @@ +package com.fr.design.gui.icombobox.filter; + +/** + * Filter used in ComboBox. + */ +public interface Filter { + public boolean accept(String prefix, Object object); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/filter/LastStartWithFilter.java b/designer_base/src/com/fr/design/gui/icombobox/filter/LastStartWithFilter.java new file mode 100644 index 0000000000..73e25a9b7d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/filter/LastStartWithFilter.java @@ -0,0 +1,18 @@ +package com.fr.design.gui.icombobox.filter; + + +public class LastStartWithFilter implements Filter { + public boolean accept(String prefix, Object object) { + boolean result = false; + if(prefix == null ){ + result = true; + }else if(object != null ){ + String tempString = object.toString().toLowerCase(); + tempString =tempString.substring(tempString.lastIndexOf("/")+1); + result=tempString.startsWith(prefix.toLowerCase()); + }else { + result = false ; + } + return result; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/filter/StartsWithFilter.java b/designer_base/src/com/fr/design/gui/icombobox/filter/StartsWithFilter.java new file mode 100644 index 0000000000..1319f2a861 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/filter/StartsWithFilter.java @@ -0,0 +1,11 @@ +package com.fr.design.gui.icombobox.filter; + +/** + * Filter used in ComboBox. + */ +public class StartsWithFilter implements Filter { + public boolean accept(String prefix, Object object) { + return prefix == null || (object != null && object.toString() != null && + object.toString().toLowerCase().startsWith(prefix.toLowerCase())); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeCellRenderer.java b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeCellRenderer.java new file mode 100644 index 0000000000..3d1924537c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeCellRenderer.java @@ -0,0 +1,86 @@ +package com.fr.design.gui.icombobox.icombotree; + +import javax.swing.*; +import javax.swing.plaf.ColorUIResource; +import javax.swing.tree.TreeCellRenderer; +import java.awt.*; + +public class CheckBoxTreeCellRenderer extends JPanel implements TreeCellRenderer +{ + protected JCheckBox check; + protected CheckBoxTreeLabel label; + + public CheckBoxTreeCellRenderer() + { + this.setLayout(null); + this.add(check = new JCheckBox()); + this.add(label = new CheckBoxTreeLabel()); + check.setBackground(UIManager.getColor("Tree.textBackground")); + label.setForeground(UIManager.getColor("Tree.textForeground")); + this.setBackground(UIManager.getColor("Tree.textBackground")); + } + + /** + * 返回的是一个JPanel对象,该对象中包含一个JCheckBox对象 + * 和一个JLabel对象。并且根据每个结点是否被选中来决定JCheckBox + * 是否被选中。 + */ + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean selected, boolean expanded, boolean leaf, int row, + boolean hasFocus) + { + String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, hasFocus); + setEnabled(tree.isEnabled()); + check.setSelected(((CheckBoxTreeNode)value).isSelected()); + label.setFont(tree.getFont()); + label.setText(stringValue); + label.setSelected(selected); + label.setFocus(hasFocus); +// if(leaf) +// label.setIcon(UIManager.getIcon("Tree.leafIcon")); +// else if(expanded) +// label.setIcon(UIManager.getIcon("Tree.openIcon")); +// else +// label.setIcon(UIManager.getIcon("Tree.closedIcon")); + + return this; + } + + @Override + public Dimension getPreferredSize() + { + Dimension dCheck = check.getPreferredSize(); + Dimension dLabel = label.getPreferredSize(); + return new Dimension(dCheck.width + dLabel.width, dCheck.height < dLabel.height ? dLabel.height: dCheck.height); + } + + /** + * 重新计算check和label位置 + */ + @Override + public void doLayout() + { + Dimension dCheck = check.getPreferredSize(); + Dimension dLabel = label.getPreferredSize(); + int yCheck = 0; + int yLabel = 0; + int height = dCheck.height < dLabel.height ? dCheck.height:dLabel.height; +// if(dCheck.height < dLabel.height) +// yCheck = (dLabel.height - dCheck.height) / 2; +// else +// yLabel = (dCheck.height - dLabel.height) / 2; + check.setLocation(0, yCheck); + check.setBounds(0, yCheck, dCheck.width, height); + label.setLocation(dCheck.width, yLabel); + label.setBounds(dCheck.width, yLabel, dLabel.width, height); + } + + @Override + public void setBackground(Color color) + { + if(color instanceof ColorUIResource){ + color = null; + } + super.setBackground(color); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeLabel.java b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeLabel.java new file mode 100644 index 0000000000..9b1c6d1b03 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeLabel.java @@ -0,0 +1,73 @@ +package com.fr.design.gui.icombobox.icombotree; + +import javax.swing.*; +import javax.swing.plaf.ColorUIResource; +import java.awt.*; + +public class CheckBoxTreeLabel extends JLabel +{ + private boolean isSelected; + private boolean hasFocus; + + public CheckBoxTreeLabel() + { + } + + @Override + public void setBackground(Color color) + { + if(color instanceof ColorUIResource){ + color = null; + } + super.setBackground(color); + } + + @Override + public void paint(Graphics g) + { + String str; + if((str = getText()) != null) + { + if(0 < str.length()) + { +// if(isSelected) +// g.setColor(UIManager.getColor("Tree.selectionBackground")); +// else + g.setColor(UIManager.getColor("Tree.textBackground")); + Dimension d = getPreferredSize(); + int imageOffset = 0; + Icon currentIcon = getIcon(); + if(currentIcon != null){ + imageOffset = currentIcon.getIconWidth() + Math.max(0, getIconTextGap() - 1); + } + g.fillRect(imageOffset, 0, d.width - 1 - imageOffset, d.height); + if(hasFocus) + { + g.setColor(UIManager.getColor("Tree.selectionBorderColor")); + g.drawRect(imageOffset, 0, d.width - 1 - imageOffset, d.height - 1); + } + } + } + super.paint(g); + } + + @Override + public Dimension getPreferredSize() + { + Dimension retDimension = super.getPreferredSize(); + if(retDimension != null){ + retDimension = new Dimension(retDimension.width + 3, retDimension.height); + } + return retDimension; + } + + public void setSelected(boolean isSelected) + { + this.isSelected = isSelected; + } + + public void setFocus(boolean hasFocus) + { + this.hasFocus = hasFocus; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNode.java b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNode.java new file mode 100644 index 0000000000..6d603520c0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNode.java @@ -0,0 +1,88 @@ +package com.fr.design.gui.icombobox.icombotree; + +import javax.swing.tree.DefaultMutableTreeNode; + +public class CheckBoxTreeNode extends DefaultMutableTreeNode +{ + protected boolean isSelected; + + public CheckBoxTreeNode() + { + this(null); + } + + public CheckBoxTreeNode(Object userObject) + { + this(userObject, true, false); + } + + public CheckBoxTreeNode(Object userObject, boolean allowsChildren, boolean isSelected) + { + super(userObject, allowsChildren); + this.isSelected = isSelected; + } + + /** + * 节点是否被选中 + * @return 节点是否被选中 + */ + public boolean isSelected() + { + return isSelected; + } + + /** + * 选择节点 + * @param _isSelected 节点是否被选中 + */ + public void setSelected(boolean _isSelected){ + this.isSelected = _isSelected; + if(_isSelected){ // 如果选中,则将其所有的子结点都选中 + if(children != null){ + for(Object obj : children){ + CheckBoxTreeNode node = (CheckBoxTreeNode)obj; + if(_isSelected != node.isSelected()){ + node.setSelected(_isSelected); + } + } + } + CheckBoxTreeNode pNode = (CheckBoxTreeNode)parent; // 向上检查,如果父结点的所有子结点都被选中,那么将父结点也选中 + if(pNode != null){ // 开始检查pNode的所有子节点是否都被选中 + int index = 0; + for(; index < pNode.children.size(); ++ index){ + CheckBoxTreeNode pChildNode = (CheckBoxTreeNode)pNode.children.get(index); + if(!pChildNode.isSelected()){ + break; + } + } + if(index == pNode.children.size()){ // 表明pNode所有子结点都已经选中,则选中父结点,该方法是一个递归方法,因此在此不需要进行迭代,因为当选中父结点后,父结点本身会向上检查的。 + if(pNode.isSelected() != _isSelected){ + pNode.setSelected(_isSelected); + } + } + } + }else{ //如果是取消父结点导致子结点取消,那么此时所有的子结点都应该是选择上的; 否则就是子结点取消导致父结点取消,然后父结点取消导致需要取消子结点,但是这时候是不需要取消子结点的。 + if(children != null){ + int index = 0; + for(; index < children.size(); ++ index){ + CheckBoxTreeNode childNode = (CheckBoxTreeNode)children.get(index); + if(!childNode.isSelected()){ + break; + } + } + if(index == children.size()){ // 从上向下取消的时候 + for(int i = 0; i < children.size(); ++ i){ + CheckBoxTreeNode node = (CheckBoxTreeNode)children.get(i); + if(node.isSelected() != _isSelected){ + node.setSelected(_isSelected); + } + } + } + } + CheckBoxTreeNode pNode = (CheckBoxTreeNode)parent; // 向上取消,只要存在一个子节点不是选上的,那么父节点就不应该被选上。 + if(pNode != null && pNode.isSelected() != _isSelected){ + pNode.setSelected(_isSelected); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNodeSelectionListener.java b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNodeSelectionListener.java new file mode 100644 index 0000000000..c0385ad7c0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icombobox/icombotree/CheckBoxTreeNodeSelectionListener.java @@ -0,0 +1,65 @@ +package com.fr.design.gui.icombobox.icombotree; + +import javax.swing.*; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +public class CheckBoxTreeNodeSelectionListener extends MouseAdapter +{ + private ArrayList treePathList = new ArrayList(); + + /** + * 鼠标点击事件 + * @param event 事件 + */ + @Override + public void mouseClicked(MouseEvent event) + { + JTree tree = (JTree)event.getSource(); + int x = event.getX(); + int y = event.getY(); + int row = tree.getRowForLocation(x, y); + TreePath treePath = tree.getPathForRow(row); + if(treePath != null) + { + tree.setExpandsSelectedPaths(true); + CheckBoxTreeNode node = (CheckBoxTreeNode)treePath.getLastPathComponent(); + if(node != null) + { + boolean isSelected = !node.isSelected(); + node.setSelected(isSelected); + ((DefaultTreeModel)tree.getModel()).nodeStructureChanged(node); + } + }else{ + tree.setExpandsSelectedPaths(false); + } + CheckBoxTreeNode root = (CheckBoxTreeNode) tree.getModel().getRoot(); + treePathList.clear(); + addPathList(tree,root); + selectTreeItem(tree,treePathList); + } + + private void addPathList(JTree tree,CheckBoxTreeNode root){ + for(int i = 0;i< root.getChildCount();i++){ + CheckBoxTreeNode treeNode = (CheckBoxTreeNode) root.getChildAt(i); + if(treeNode.isLeaf() && treeNode.isSelected()){ + DefaultTreeModel model = (DefaultTreeModel) tree.getModel(); + treePathList.add(new TreePath(model.getPathToRoot(treeNode))); + }else{ + addPathList(tree,treeNode); + } + } + } + + private void selectTreeItem(JTree tree,ArrayList treePath) { + TreePath[] treePaths = new TreePath[treePath.size()]; + for(int i = 0;i < treePath.size();i++){ + treePaths[i] = treePath.get(i); + } + tree.setSelectionPaths(treePaths); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UIModeControlContainer.java b/designer_base/src/com/fr/design/gui/icontainer/UIModeControlContainer.java new file mode 100644 index 0000000000..fad42d9754 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UIModeControlContainer.java @@ -0,0 +1,458 @@ +package com.fr.design.gui.icontainer; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.Inter; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; + +public class UIModeControlContainer extends JLayeredPane { + private static int DIM_HEIGHT = 30; + private static final int NUM32 = 32; + private static final int NUM5 = 5; + private JComponent upPane; + private JComponent downPane; + private JPanel horizontToolPane; + + private CoverPane coverPane; + private HidePane hidePane; + private AuthoritySheetInvisibleCoverPane sheetInvisibleCoverPane; + + private int toolPaneY = 300; + private int sheetCorverGap = 33; + private int toolPaneHeight = 10; + private boolean upEditMode = false; + private boolean isHideMode = false; + private boolean isSheeetCovered = false; + + private AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 30 / 100.0F); + + public UIModeControlContainer() { + this(new JPanel(), new JPanel()); + } + + public UIModeControlContainer(JComponent up, JComponent down) { + upPane = up; + downPane = down; + setLayout(containerLayout); + initToolbar(); + sheetInvisibleCoverPane = new AuthoritySheetInvisibleCoverPane(); + + if (upPane == null) { + toolPaneY = 0; + } else { + toolPaneY = upPane.getPreferredSize().height; + add(upPane); + add(horizontToolPane); + } + add(downPane); + add(coverPane = new CoverPane()); + add(hidePane = new HidePane()); + if (upPane != null) { + setLayer(upPane, 1); + setLayer(horizontToolPane, 2); + } + setLayer(downPane, 1); + setLayer(coverPane, 3); + setLayer(hidePane, 2); + } + + + public void setSheeetCovered(boolean isSheetCovered) { + this.isSheeetCovered = isSheetCovered; + } + + + public void needToShowCoverAndHidPane() { + if (BaseUtils.isAuthorityEditing()) { + this.remove(coverPane); + this.remove(hidePane); + } else { + this.remove(sheetInvisibleCoverPane); + this.add(coverPane); + this.add(hidePane); + setLayer(coverPane, 3); + setLayer(hidePane, 2); + } + } + + + public void setDownPane(JComponent downPane) { + this.downPane = downPane; + } + + protected void onResize(int distance) { + + } + + private void initToolbar() { + horizontToolPane = new JPanel() { + @Override + public void paint(Graphics g) { + g.drawImage(UIConstants.DRAG_BAR, 0, 0, getWidth(), getHeight(), null); + if (upEditMode) { + g.drawImage(UIConstants.DRAG_DOT, (getWidth() - toolPaneHeight) / 2, 3, toolPaneHeight, 5, null); + } + } + }; + + horizontToolPane.addMouseListener(mouseAdapter); + + horizontToolPane.addMouseMotionListener(mouseMotionListener); + } + + MouseAdapter mouseAdapter = new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + if (isHideMode || !upEditMode) { + return; + } + if (BaseUtils.isAuthorityEditing()) { + return; + } + setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + if (isHideMode || !upEditMode) { + return; + } + setCursor(Cursor.getDefaultCursor()); + } + + @Override + public void mouseReleased(MouseEvent e) { + refreshContainer(); + } + }; + + MouseMotionListener mouseMotionListener = new MouseMotionListener() { + @Override + public void mouseMoved(MouseEvent e) { + } + + @Override + public void mouseDragged(MouseEvent e) { + if (BaseUtils.isAuthorityEditing()) { + return; + } + boolean notUpEditMode = isHideMode || !upEditMode; + if (notUpEditMode) { + return; + } + // 拖动的距离,为正值表示往下拖动,为负值表示往上拖动 + int deltaY = e.getY(); + toolPaneY += deltaY; + onResize(toolPaneY); + refreshContainer(); + } + }; + + private LayoutManager containerLayout = new LayoutManager() { + + @Override + public void removeLayoutComponent(Component comp) { + + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + synchronized (parent.getTreeLock()) { + return parent.getSize(); + } + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + if (toolPaneY < 0) { + toolPaneY = 0; + setUpPaneHeight(0); + } + + if (BaseUtils.isAuthorityEditing() && isSheeetCovered) { + sheetInvisibleCoverPane.setBounds(0, toolPaneY + toolPaneHeight + UIConstants.SIZE, getWidth(), getHeight() - toolPaneY - toolPaneHeight - sheetCorverGap); + UIModeControlContainer.this.add(sheetInvisibleCoverPane); + UIModeControlContainer.this.setLayer(sheetInvisibleCoverPane, 2); + sheetInvisibleCoverPane.setVisible(true); + } else { + sheetInvisibleCoverPane.setVisible(false); + UIModeControlContainer.this.remove(sheetInvisibleCoverPane); + } + + if (isHideMode) { + hidePane.setVisible(true); + coverPane.setVisible(false); + hidePane.setBounds(0, 0, parent.getWidth(), hidePane.getPreferredSize().height); + if (upPane != null) { + upPane.setVisible(false); + horizontToolPane.setBounds(0, hidePane.getPreferredSize().height, parent.getWidth(), toolPaneHeight); + } + downPane.setBounds(0, hidePane.getPreferredSize().height + toolPaneHeight, parent.getWidth(), parent.getHeight() - hidePane.getPreferredSize().height - toolPaneHeight); + } else { + hidePane.setVisible(false); + coverPane.setVisible(true); + if (upPane != null) { + upPane.setVisible(true); + upPane.setBounds(0, 0, parent.getWidth(), toolPaneY + UIConstants.SIZE); + horizontToolPane.setBounds(0, toolPaneY + UIConstants.SIZE, parent.getWidth(), toolPaneHeight); + } + downPane.setBounds(0, toolPaneY + toolPaneHeight + UIConstants.SIZE, parent.getWidth(), parent.getHeight() - toolPaneY - toolPaneHeight - UIConstants.SIZE); + if (upEditMode) { + coverPane.setBounds(0, toolPaneY + toolPaneHeight + UIConstants.SIZE, getWidth(), getHeight() - toolPaneY - toolPaneHeight); + } else { + coverPane.setBounds(0, 0, getWidth(), toolPaneY + UIConstants.SIZE); + } + } + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + }; + + protected void onModeChanged() { + + } + + /** + * @return + */ + public boolean isUpEditMode() { + return upEditMode; + } + + private void setEditMode() { + this.upEditMode = !upEditMode; + onModeChanged(); + } + + public void setAuthorityMode(boolean isUpMode) { + this.upEditMode = isUpMode; + } + + public void setUpPaneHeight(int height) { + this.toolPaneY = height; + refreshContainer(); + } + + /** + * + */ + public void refreshContainer() { + validate(); + repaint(); + revalidate(); + } + + private class HidePane extends JPanel { + public HidePane() { + setLayout(new FlowLayout(FlowLayout.CENTER, 10, -3)); + setBackground(UIConstants.NORMAL_BACKGROUND); + add(new UILabel("" + Inter.getLocText(new String[]{"Parameter", "Panel"}) + "")); + UIButton viewButton = new UIButton(UIConstants.VIEW_NORMAL_ICON, UIConstants.VIEW_PRESSED_ICON, UIConstants.VIEW_PRESSED_ICON) { + @Override + public Dimension getPreferredSize() { + return new Dimension(32, 32); + } + }; + viewButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + isHideMode = false; + refreshContainer(); + } + }); + add(viewButton); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = DIM_HEIGHT; + return dim; + } + } + + + private class AuthoritySheetInvisibleCoverPane extends JPanel { + public AuthoritySheetInvisibleCoverPane() { + setLayout(invisibleCoverLayout); + setBackground(null); + setOpaque(false); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + + } + }); + } + + + private LayoutManager invisibleCoverLayout = new LayoutManager() { + + @Override + public void removeLayoutComponent(Component comp) { + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return parent.getPreferredSize(); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + }; + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(composite); + g2d.setColor(Color.BLACK); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.setComposite(oldComposite); + super.paint(g); + } + + + } + + private class CoverPane extends JPanel { + UIButton editButton; + UIButton hideButton; + + public CoverPane() { + setLayout(coverLayout); + setBackground(null); + setOpaque(false); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + + } + }); + + editButton = new UIButton(UIConstants.EDIT_NORMAL_ICON, UIConstants.EDIT_PRESSED_ICON, UIConstants.EDIT_PRESSED_ICON) { + @Override + public Dimension getPreferredSize() { + return new Dimension(40, 40); + } + }; + hideButton = new UIButton(UIConstants.HIDE_NORMAL_ICON, UIConstants.HIDE_PRESSED_ICON, UIConstants.HIDE_PRESSED_ICON) { + @Override + public Dimension getPreferredSize() { + return new Dimension(40, 40); + } + }; + editButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + setEditMode(); + refreshContainer(); + DesignerContext.getDesignerFrame().getContentFrame().repaint(); + } + }); + + hideButton.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + isHideMode = true; + refreshContainer(); + } + }); + + add(editButton); + add(hideButton); + } + + private LayoutManager coverLayout = new LayoutManager() { + + @Override + public void removeLayoutComponent(Component comp) { + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return parent.getPreferredSize(); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + int width = parent.getWidth(); + int height = parent.getHeight() + NUM32; + int preferWidth = editButton.getPreferredSize().width; + int preferHeight = editButton.getPreferredSize().height; + if (upEditMode) { + hideButton.setVisible(false); + editButton.setBounds((width - preferWidth) / 2, 84, preferWidth, preferHeight); + } else { + hideButton.setVisible(true); + hideButton.setBounds(width / 2 - preferWidth - NUM5, height / 2 - preferHeight + 3, preferWidth, preferWidth); + editButton.setBounds(width / 2 + NUM5, height / 2 - preferHeight + 3, preferWidth, preferWidth); + } + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + }; + + @Override + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Composite oldComposite = g2d.getComposite(); + g2d.setComposite(composite); + g2d.setColor(Color.BLACK); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.setComposite(oldComposite); + super.paint(g); + } + } + + /** + * @param args + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + UIModeControlContainer bb = new UIModeControlContainer(); + content.add(bb, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(500, 500); + jf.setVisible(true); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UIResizableContainer.java b/designer_base/src/com/fr/design/gui/icontainer/UIResizableContainer.java new file mode 100644 index 0000000000..4315a8c26e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UIResizableContainer.java @@ -0,0 +1,469 @@ +package com.fr.design.gui.icontainer; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.mainframe.DesignerContext; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; + +public class UIResizableContainer extends JPanel { + private static final long serialVersionUID = 1854340560790476907L; + private int containerWidth = 240; + private int preferredWidth = 240; + private int toolPaneY = 300; + private int toolPaneHeight = 10; + + private JComponent upPane; + private JComponent downPane; + + private HorizotalToolPane horizontToolPane; + private VerticalToolPane verticalToolPane; + + private int direction; + + private static final int MAX_WIDTH = 300; + private static final int MIN_WIDTH = 165; + + private static final int ARROW_MARGIN = 15; + private static final int ARROW_MARGIN_VERTICAL = 20; + private static final int ARROW_RANGE = 35; + private static final int ARROW_RANGE_VERTICAL = 40; + + private boolean isLeftRightDragEnabled = true; + private boolean isDownPaneVisible = true ; + + public UIResizableContainer(int direction) { + this(new JPanel(), new JPanel(), direction); + } + + /** + * 设置是否允许拖拽 + * + * @param isEnabled + */ + public void setVerticalDragEnabled(boolean isEnabled) { + isLeftRightDragEnabled = isEnabled; + } + + /** + * 设置面板宽度 + * + * @param width + */ + public void setContainerWidth(int width) { + this.containerWidth = width; + this.preferredWidth = width; + } + + + public void setDownPaneVisible(boolean isVisible){ + this.isDownPaneVisible = isVisible; + } + + private void setPreferredWidth(int width) { + this.preferredWidth = width; + } + + public UIResizableContainer(JComponent upPane, JComponent downPane, int direction) { + setBackground(UIConstants.NORMAL_BACKGROUND); + + this.upPane = upPane; + this.direction = direction; + this.downPane = downPane; + + this.horizontToolPane = new HorizotalToolPane(); + this.verticalToolPane = new VerticalToolPane(); + + setLayout(containerLayout); + add(upPane); + add(horizontToolPane); + add(downPane); + add(verticalToolPane); + } + + /** + * 将面板设置成最佳的宽度 + */ + public void setWindow2PreferWidth() { + if (containerWidth == toolPaneHeight) { + containerWidth = preferredWidth; + refreshContainer(); + } + } + + /** + * 得到上下子面板的高度 + * + * @return + */ + public int getToolPaneY() { + return this.toolPaneY; + } + + /** + * 设置关闭设计器前最后一次上下子面板的高度 + * + * @param toolPaneY + */ + public void setLastToolPaneY(int toolPaneY) { + this.toolPaneY = toolPaneY; + } + + /** + * 得到容器的宽度 + * + * @return + */ + public int getContainerWidth() { + return this.containerWidth; + } + + /** + * 设置关闭设计器前最后一次面板的宽度 + * + * @param containerWidth + */ + public void setLastContainerWidth(int containerWidth) { + this.containerWidth = containerWidth; + } + + private LayoutManager containerLayout = new LayoutManager() { + + @Override + public void removeLayoutComponent(Component comp) { + // TODO Auto-generated method stub + + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return parent.getPreferredSize(); + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + if (direction == Constants.RIGHT) { + if(isDownPaneVisible){ + upPane.setBounds(0, 0, containerWidth - toolPaneHeight, toolPaneY); + horizontToolPane.setBounds(0, toolPaneY, containerWidth - toolPaneHeight, toolPaneHeight); + downPane.setBounds(0, toolPaneY + toolPaneHeight, containerWidth - toolPaneHeight, parent.getHeight() - toolPaneY - toolPaneHeight); + verticalToolPane.setBounds(containerWidth - toolPaneHeight, 0, toolPaneHeight, getHeight()); + }else{ + upPane.setBounds(0, 0, containerWidth - toolPaneHeight, getHeight()); + verticalToolPane.setBounds(containerWidth - toolPaneHeight, 0, toolPaneHeight, getHeight()); + } + } else if (direction == Constants.LEFT) { + if(isDownPaneVisible){ + if (toolPaneY > getHeight() - toolPaneHeight) { + toolPaneY = getHeight() - toolPaneHeight; + } + upPane.setBounds(toolPaneHeight, 0, containerWidth - toolPaneHeight, toolPaneY); + horizontToolPane.setBounds(toolPaneHeight, toolPaneY, containerWidth - toolPaneHeight, toolPaneHeight); + downPane.setBounds(toolPaneHeight, toolPaneY + toolPaneHeight, containerWidth - toolPaneHeight, parent.getHeight() - toolPaneY - toolPaneHeight); + verticalToolPane.setBounds(0, 0, toolPaneHeight, getHeight()); + }else{ + upPane.setBounds(toolPaneHeight, 0, containerWidth - toolPaneHeight, getHeight()); + verticalToolPane.setBounds(0, 0, toolPaneHeight, getHeight()); + } + } + + } + + @Override + public void addLayoutComponent(String name, Component comp) { + } + }; + + @Override + /** + * 得到最佳大小 + */ + public Dimension getPreferredSize() { + return new Dimension(containerWidth, 400); + } + + /** + * 替换上子面板 + * + * @param pane 面板 + */ + public void replaceUpPane(JComponent pane) { + remove(pane); + remove(this.upPane); + add(this.upPane = pane); + refreshContainer(); + } + + + /** + * 替换下子面板 + * + * @param pane 面板 + */ + public void replaceDownPane(JComponent pane) { + remove(pane); + remove(this.downPane); + add(this.downPane = pane); + refreshContainer(); + } + + /** + * 得到上子面板 + * + * @return + */ + public JComponent getUpPane() { + return this.upPane; + } + + /** + * 得到下子面板 + * + * @return + */ + public JComponent getDownPane() { + return this.downPane; + } + + /** + * 刷新下面板 + */ + public void refreshDownPane() { + + } + + private void refreshContainer() { + validate(); + repaint(); + revalidate(); + } + + + private class HorizotalToolPane extends JPanel { + private int upModel = UIConstants.MODEL_NORMAL; + private int downModel = UIConstants.MODEL_NORMAL; + + public HorizotalToolPane() { + super(); + addMouseMotionListener(new MouseMotionListener() { + + @Override + public void mouseMoved(MouseEvent e) { + if (e.getX() <= ARROW_RANGE) { + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + upModel = UIConstants.MODEL_PRESS; + } else if (e.getX() >= getWidth() - ARROW_RANGE) { + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + downModel = UIConstants.MODEL_PRESS; + } else { + resetModel(); + setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); + } + repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + toolPaneY = e.getYOnScreen() - UIResizableContainer.this.getLocationOnScreen().y; + toolPaneY = toolPaneY < 0 ? 0 : toolPaneY; + toolPaneY = toolPaneY > UIResizableContainer.this.getHeight() - toolPaneHeight ? UIResizableContainer.this.getHeight() - toolPaneHeight : toolPaneY; + refreshContainer(); + } + }); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + setCursor(Cursor.getDefaultCursor()); + resetModel(); + repaint(); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getX() <= ARROW_RANGE) { + toolPaneY = 0; + } else if (e.getX() >= getWidth() - ARROW_RANGE) { + toolPaneY = UIResizableContainer.this.getHeight() - toolPaneHeight; + } else { + return; + } + refreshContainer(); + } + }); + } + + private void resetModel() { + upModel = UIConstants.MODEL_NORMAL; + downModel = UIConstants.MODEL_NORMAL; + } + + @Override + public void paint(Graphics g) { + Image upButton = (upModel == UIConstants.MODEL_NORMAL ? UIConstants.DRAG_UP_NORMAL : UIConstants.DRAG_UP_PRESS); + Image downButton = (downModel == UIConstants.MODEL_NORMAL ? UIConstants.DRAG_DOWN_NORMAL : UIConstants.DRAG_DOWN_PRESS); + + g.drawImage(UIConstants.DRAG_BAR, 0, 0, getWidth(), getHeight(), null); + g.drawImage(UIConstants.DRAG_DOT, (getWidth() - toolPaneHeight) / 2, 3, toolPaneHeight, 5, null); + g.drawImage(upButton, ARROW_MARGIN, 3, toolPaneHeight, 5, null); + g.drawImage(downButton, getWidth() - toolPaneHeight - ARROW_MARGIN, 3, toolPaneHeight, 5, null); + } + } + + private class VerticalToolPane extends JPanel { + private int model = UIConstants.MODEL_NORMAL; + + public VerticalToolPane() { + super(); + addMouseMotionListener(new MouseMotionListener() { + + @Override + public void mouseMoved(MouseEvent e) { + if (e.getY() <= ARROW_RANGE_VERTICAL) { + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + model = UIConstants.MODEL_PRESS; + } else if (isLeftRightDragEnabled) { + setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); + } + repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + if (!isLeftRightDragEnabled) { + return; + } + upPane.setVisible(true); + downPane.setVisible(true); + if (direction == Constants.RIGHT) { + containerWidth = e.getXOnScreen() - UIResizableContainer.this.getLocationOnScreen().x; + } else if (direction == Constants.LEFT) { + containerWidth = UIResizableContainer.this.getWidth() + (UIResizableContainer.this.getLocationOnScreen().x - e.getXOnScreen()); + } + + containerWidth = containerWidth > MAX_WIDTH ? MAX_WIDTH : containerWidth; + containerWidth = containerWidth < MIN_WIDTH ? MIN_WIDTH : containerWidth; + if (containerWidth < MIN_WIDTH) { + upPane.setVisible(false); + downPane.setVisible(false); + containerWidth = toolPaneHeight; + } + refreshContainer(); + if (BaseUtils.isAuthorityEditing()) { + DesignerContext.getDesignerFrame().doResize(); + } + + + } + }); + addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + if (!isLeftRightDragEnabled) { + return; + } + setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); + } + + @Override + public void mouseExited(MouseEvent e) { + setCursor(Cursor.getDefaultCursor()); + model = UIConstants.MODEL_NORMAL; + repaint(); + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getY() <= ARROW_RANGE_VERTICAL) { + if (containerWidth == toolPaneHeight) { + containerWidth = preferredWidth; + } else { + setPreferredWidth(containerWidth); + containerWidth = toolPaneHeight; + } + refreshContainer(); + if (BaseUtils.isAuthorityEditing()) { + DesignerContext.getDesignerFrame().doResize(); + } + } + } + }); + } + + @Override + public void paint(Graphics g) { + Image button; + if (direction == Constants.RIGHT) { + g.drawImage(UIConstants.DRAG_BAR, 0, 0, toolPaneHeight, getHeight(), null); + if (containerWidth == toolPaneHeight) { + if (model == UIConstants.MODEL_NORMAL) { + button = UIConstants.DRAG_RIGHT_NORMAL; + } else { + button = UIConstants.DRAG_RIGHT_PRESS; + } + } else { + if (model == UIConstants.MODEL_NORMAL) { + button = UIConstants.DRAG_LEFT_NORMAL; + } else { + button = UIConstants.DRAG_LEFT_PRESS; + } + } + g.drawImage(button, 3, ARROW_MARGIN_VERTICAL, 5, toolPaneHeight, null); + } else { + g.drawImage(UIConstants.DRAG_BAR, 0, 0, toolPaneHeight, getHeight(), null); + if (containerWidth == toolPaneHeight) { + if (model == UIConstants.MODEL_NORMAL) { + button = UIConstants.DRAG_LEFT_NORMAL; + } else { + button = UIConstants.DRAG_LEFT_PRESS; + } + } else { + if (model == UIConstants.MODEL_NORMAL) { + button = UIConstants.DRAG_RIGHT_NORMAL; + } else { + button = UIConstants.DRAG_RIGHT_PRESS; + } + } + g.drawImage(button, 2, ARROW_MARGIN_VERTICAL, 5, toolPaneHeight, null); + } + if (isLeftRightDragEnabled) { + g.drawImage(UIConstants.DRAG_DOT_VERTICAL, 2, getHeight() / 2, 5, toolPaneHeight, null); + } + } + } + + /** + * 主函数 + * @param args 参数 + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + UIResizableContainer bb = new UIResizableContainer(Constants.LEFT); + JPanel cc = new JPanel(); + cc.setBackground(Color.blue); + content.add(bb, BorderLayout.EAST); + content.add(cc, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(500, 500); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UIScrollPane.java b/designer_base/src/com/fr/design/gui/icontainer/UIScrollPane.java new file mode 100644 index 0000000000..62a580c385 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UIScrollPane.java @@ -0,0 +1,44 @@ +package com.fr.design.gui.icontainer; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.iscrollbar.UIScrollBar; + +import javax.swing.*; +import java.awt.*; + +/** + * @author zhou + * @since 2012-5-9下午4:39:33 + */ +public class UIScrollPane extends JScrollPane { + + private static final long serialVersionUID = 1L; + + public UIScrollPane(Component c) { + super(c, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + this.setHorizontalScrollBar(createHorizontalScrollBar()); + this.getVerticalScrollBar().setUnitIncrement(30); + this.getVerticalScrollBar().setBlockIncrement(30); + } + + @Override + /** + * 生成水平滚动条 + */ + public JScrollBar createHorizontalScrollBar() { + UIScrollBar sbr = new UIScrollBar(JScrollBar.HORIZONTAL); + sbr.setBackground(UIConstants.NORMAL_BACKGROUND); + return sbr; + } + + @Override + /** + * 生成垂直滚动条 + */ + public JScrollBar createVerticalScrollBar() { + UIScrollBar sbr = new UIScrollBar(JScrollBar.VERTICAL); + sbr.setBackground(UIConstants.NORMAL_BACKGROUND); + return sbr; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneBorder.java b/designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneBorder.java new file mode 100644 index 0000000000..da4feaf72d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneBorder.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.icontainer; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-5 + * Time: 下午2:25 + */ +public class UIScrollPaneBorder extends AbstractBorder implements UIResource { + + private static final Insets DEFAULT_INSETS = new Insets(1, 1, 1, 1); + + public Insets getBorderInsets(Component c) { + return DEFAULT_INSETS; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + g.setColor(ThemeUtils.SCROLL_PANE_BORDER_COLOR); + g.drawRect(x, y, w - 1, h - 1); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneUI.java b/designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneUI.java new file mode 100644 index 0000000000..82d0363c70 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UIScrollPaneUI.java @@ -0,0 +1,57 @@ +package com.fr.design.gui.icontainer; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalScrollBarUI; +import javax.swing.plaf.metal.MetalScrollPaneUI; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-13 + * Time: 上午10:07 + */ +public class UIScrollPaneUI extends MetalScrollPaneUI implements PropertyChangeListener { + + /** + * 创建UI + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIScrollPaneUI(); + } + + /** + * 为组件初始化UI + * @param c 组件 + */ + public void installUI(JComponent c) { + super.installUI(c); + + // Note: It never happened before Java 1.5 that scrollbar is null + JScrollBar sb = scrollpane.getHorizontalScrollBar(); + if (sb != null) { + sb.putClientProperty(MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE); + } + + sb = scrollpane.getVerticalScrollBar(); + if (sb != null) { + sb.putClientProperty(MetalScrollBarUI.FREE_STANDING_PROP, Boolean.FALSE); + } + } + + protected PropertyChangeListener createScrollBarSwapListener() { + return this; + } + + /** + * 属性改变的方法 + * @param e 事件 + */ + public void propertyChange(PropertyChangeEvent e) { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UITableScrollPaneBorder.java b/designer_base/src/com/fr/design/gui/icontainer/UITableScrollPaneBorder.java new file mode 100644 index 0000000000..a63443f8ce --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UITableScrollPaneBorder.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.icontainer; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-6 + * Time: 上午11:28 + */ +public class UITableScrollPaneBorder extends AbstractBorder implements UIResource { + + private static final Insets INSETS = new Insets(1, 1, 1, 1); + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + g.setColor(ThemeUtils.TABLE_BORDER_LIGHT_COLOR); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); // right + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); // bottom + + g.setColor(ThemeUtils.TABLE_BORDER_DARK_COLOR); + g.drawLine(x, y, x, y + h - 1); // left + g.drawLine(x, y, x + w - 1, y); // top + } + + public Insets getBorderInsets(Component c) { + return INSETS; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/icontainer/UIVerticalScrollPane.java b/designer_base/src/com/fr/design/gui/icontainer/UIVerticalScrollPane.java new file mode 100644 index 0000000000..30605a4277 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/icontainer/UIVerticalScrollPane.java @@ -0,0 +1 @@ +package com.fr.design.gui.icontainer; import com.fr.design.constants.UIConstants; import com.fr.design.gui.iscrollbar.UIScrollBar; import javax.swing.*; import java.awt.*; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 12-12-25 * Time: 下午3:09 */ public class UIVerticalScrollPane extends JScrollPane { public UIVerticalScrollPane(Component c) { super(c, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); this.setHorizontalScrollBar(createHorizontalScrollBar()); this.getVerticalScrollBar().setUnitIncrement(30); this.getVerticalScrollBar().setBlockIncrement(30); } @Override /** * 生成水平滚动条 */ public JScrollBar createHorizontalScrollBar() { return null; } @Override /** * 生成垂直滚动条 */ public JScrollBar createVerticalScrollBar() { UIScrollBar sbr = new UIScrollBar(JScrollBar.VERTICAL); sbr.setBackground(UIConstants.NORMAL_BACKGROUND); return sbr; } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilable/ActionLabel.java b/designer_base/src/com/fr/design/gui/ilable/ActionLabel.java new file mode 100644 index 0000000000..bc3d0fda8e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilable/ActionLabel.java @@ -0,0 +1,87 @@ +package com.fr.design.gui.ilable; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.event.MouseInputAdapter; + +/** + * Action label + */ +public class ActionLabel extends UILabel { + private ActionListener actionListener; + + public ActionLabel(String text) { + super(text); + + this.setForeground(Color.blue); + this.addMouseListener(mouseInputAdapter); + this.addMouseMotionListener(mouseInputAdapter); + } + + public void addActionListener(ActionListener actionListener) { + this.actionListener = actionListener; + } + + /** + * Repaints the text. + */ + public void paintComponent(Graphics _gfx) { + super.paintComponent(_gfx); + + _gfx.setColor(Color.blue); + _gfx.drawLine(0, this.getHeight() - 1, this.getWidth(), this.getHeight() - 1); + } + + private MouseInputAdapter mouseInputAdapter = new MouseInputAdapter() { + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent evt) { + Object source = evt.getSource(); + + if (source instanceof UILabel) { + //Action. + if (actionListener != null) { + ActionEvent actionEvent = new ActionEvent(source, 99, ""); + actionListener.actionPerformed(actionEvent); + } + } + } + + public void mouseEntered(MouseEvent evt) { + Object source = evt.getSource(); + + if (source instanceof UILabel) { + ((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + } + + public void mouseExited(MouseEvent evt) { + Object source = evt.getSource(); + + if (source instanceof UILabel) { + ((UILabel) source).setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); + } + } + + public void mouseDragged(MouseEvent e) { + } + + public void mouseMoved(MouseEvent evt) { + Object source = evt.getSource(); + + if (source instanceof UILabel) { + ((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilable/BoldFontTextLabel.java b/designer_base/src/com/fr/design/gui/ilable/BoldFontTextLabel.java new file mode 100644 index 0000000000..4e25c31a8f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilable/BoldFontTextLabel.java @@ -0,0 +1,36 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.ilable; + +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; + +import com.fr.design.gui.ilable.UILabel; + +public class BoldFontTextLabel extends UILabel { + public BoldFontTextLabel() { + this(""); + } + + public BoldFontTextLabel(String text) { + super(text); + } + + public BoldFontTextLabel(String text,int horizontalAlignment) { + super(text,horizontalAlignment); + } + + public Dimension getPreferredSize() { + Font font = this.getFont(); + FontMetrics fm = this.getFontMetrics(font); + + if (font.isBold()) { + return new Dimension(fm.stringWidth(this.getText()), + super.getPreferredSize().height); + } else { + return super.getPreferredSize(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilable/FRExplainLabel.java b/designer_base/src/com/fr/design/gui/ilable/FRExplainLabel.java new file mode 100644 index 0000000000..a347ad4282 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilable/FRExplainLabel.java @@ -0,0 +1,24 @@ +package com.fr.design.gui.ilable; + +import java.awt.Color; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import com.fr.design.gui.ilable.UILabel; + +public class FRExplainLabel extends UILabel { + + private static final long serialVersionUID = 1L; + + private Icon icon = new ImageIcon("/com/fr/design/images/warnings/warning3.png"); + + public FRExplainLabel(String string){ + super(string, UILabel.CENTER); + init(); + } + + private void init(){ + setIcon(icon); + setForeground(new Color(255, 0, 0)); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilable/MultilineLabel.java b/designer_base/src/com/fr/design/gui/ilable/MultilineLabel.java new file mode 100644 index 0000000000..1be86d2a50 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilable/MultilineLabel.java @@ -0,0 +1,75 @@ +/* + * @(#)MultilineLabel.java + * + * Copyright 2002 JIDE Software. All rights reserved. + */ +package com.fr.design.gui.ilable; + +import java.awt.Dimension; +import java.awt.Rectangle; + +import javax.swing.LookAndFeel; +import javax.swing.text.DefaultCaret; + +import com.fr.design.gui.itextarea.UITextArea; + +/** + * Normal UILabel cannot have multiple lines. If you want to multiple + * label, you can use this class. + */ +public class MultilineLabel extends UITextArea { + public MultilineLabel() { + initComponents(); + } + + public MultilineLabel(String s) { + super(s); + initComponents(); + } + + private void initComponents() { + adjustUI(); + } + + /** + * Reloads the pluggable UI. The key used to fetch the + * new interface is getUIClassID(). The type of + * the UI is TextUI. invalidate + * is called after setting the UI. + */ + + public void updateUI() { + super.updateUI(); + adjustUI(); + } + + /** + * Adjusts UI to make sure it looks like a label instead of a text area. + */ + protected void adjustUI() { + setLineWrap(true); + setWrapStyleWord(true); + setEditable(false); + setRequestFocusEnabled(false); + setFocusable(false); + setOpaque(false); + setCaret(new DefaultCaret() { + protected void adjustVisibility(Rectangle nloc) { + } + }); + + LookAndFeel.installBorder(this, "Label.border"); + LookAndFeel.installColorsAndFont(this, "Label.background", "Label.foreground", "Label.font"); + } + + /** + * Overrides getMinimumSize to return getPreferredSize() instead. + * We did this because of a bug at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4824261. + * + * @return the preferred size as minimum size. + */ + + public Dimension getMinimumSize() { + return getPreferredSize(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilable/UILabel.java b/designer_base/src/com/fr/design/gui/ilable/UILabel.java new file mode 100644 index 0000000000..b1c90d8ff5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilable/UILabel.java @@ -0,0 +1,61 @@ +package com.fr.design.gui.ilable; + +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-1-23 + * Time: 下午3:15 + */ +public class UILabel extends JLabel { + + public UILabel(String text, Icon image, int horizontalAlignment) { + super(text, image, horizontalAlignment); + if (image != null && text != null) { + setIconTextGap(4); + } + } + + public UILabel(String text, int horizontalAlignment) { + super(text, horizontalAlignment); + } + + public UILabel(String text) { + super(text); + } + + public UILabel(Icon image, int horizontalAlignment) { + super(image, horizontalAlignment); + } + + public UILabel(Icon image) { + super(image); + } + + public UILabel() { + super(); + } + + + public static void main(String[] args) { +// UILabel label = new UILabel("shishi",SwingConstants.LEFT); + JFrame frame = new JFrame("Test"); + UILabel label = new UILabel("HELLO"); + frame.setSize(new Dimension(300, 400)); + JPanel panel = (JPanel) frame.getContentPane(); + panel.setLayout(new BorderLayout()); + label.setBackground(Color.GREEN); + panel.add(label, BorderLayout.CENTER); + GUICoreUtils.centerWindow(frame); + frame.setVisible(true); + + + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/ArrayListModel.java b/designer_base/src/com/fr/design/gui/ilist/ArrayListModel.java new file mode 100644 index 0000000000..62a360694d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/ArrayListModel.java @@ -0,0 +1,24 @@ +package com.fr.design.gui.ilist; + +import javax.swing.AbstractListModel; + +public class ArrayListModel extends AbstractListModel { + private Object[] array; + + public ArrayListModel() { + + } + + public ArrayListModel(Object[] array) { + this.array = array; + } + + public Object getElementAt(int index) { + return array != null ? array[index] : null; + } + + public int getSize() { + return array == null ? 0 : array.length; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/CheckBoxList.java b/designer_base/src/com/fr/design/gui/ilist/CheckBoxList.java new file mode 100644 index 0000000000..0ef0f829a0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/CheckBoxList.java @@ -0,0 +1,311 @@ +package com.fr.design.gui.ilist; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EventListener; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.stable.StringUtils; + +/** + * CheckBoxs + JList. + */ +public class CheckBoxList extends JComponent { + /** + * 选择状态----全选和全不选 + * + * @editor zhou + * @since 2012-4-1下午2:39:10 + */ + public static enum SelectedState { + ALL, NONE + } + + private boolean[] selects; + private JList jlist; + private UICheckBox chooseAll; + + public CheckBoxList(Object[] items) { + this(items, SelectedState.NONE, StringUtils.EMPTY); + } + + public CheckBoxList(Object[] items, String name) { + this(items, SelectedState.NONE, name); + } + + /** + * Class constructor. + * + * @param items + * Items with which to populate the list. + * @param default_state + * default state, true or false + */ + public CheckBoxList(Object[] items, SelectedState state, String name) { + jlist = new BOXLIST(items); + jlist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + this.selects = new boolean[items.length]; + boolean default_state = (state == SelectedState.ALL); + Arrays.fill(this.selects, default_state); + + jlist.setCellRenderer(new CheckListCellRenderer()); + jlist.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + doCheck(); + } + + public void mouseReleased(MouseEvent e) { + doCheck(); + } + }); + jlist.addKeyListener(new KeyAdapter() { + + @Override + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == ' ') { + doCheck(); + } + } + + }); + this.setLayout(new BorderLayout()); + chooseAll = new UICheckBox(name, default_state); + chooseAll.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (chooseAll.isSelected()) { + setSelected(true); + } else { + setSelected(false); + } + } + }); + this.add(chooseAll, BorderLayout.NORTH); + this.add(jlist, BorderLayout.CENTER); + } + + /* + * 用于CellRenderer显示value为text + */ + protected String value2Text(Object value) { + return value != null ? value.toString() : StringUtils.EMPTY; + } + + public void setItems(Object[] os) { + if (os == null) { + this.setSelected(false); + } else { + for (int i = 0, len = os.length; i < len; i++) { + Object o = os[i]; + for (int j = 0, jen = jlist.getModel().getSize(); j < jen; j++) { + if (o.equals(jlist.getModel().getElementAt(j))) { + this.setSelected(j, true); + } + } + } + } + this.repaint(); + } + + /** + * Is selected + */ + public boolean isSelected(int index) { + if (selects == null || index >= selects.length) { + return false; + } + + return selects[index]; + } + + public void setSelected(int index, boolean isSelected) { + if (selects == null || index >= selects.length) { + return; + } + + selects[index] = isSelected; + this.repaint(this.getBounds()); + + this.fireCheckBoxListSelectionChangeListener(); + } + + private void setSelected(boolean isSelected) { + if (selects == null) { + return; + } + for (int i = 0; i < selects.length; i++) { + selects[i] = isSelected; + } + this.repaint(this.getBounds()); + + this.fireCheckBoxListSelectionChangeListener(); + } + + /** + * Returns an array of the objects that have been selected. Overrides the + * JList method. + */ + public Object[] getSelectedValues() { + return this.jlist.getSelectedValues(); + } + + private class BOXLIST extends JList { + public BOXLIST(Object[] items) { + super(items); + } + + @Override + protected void processMouseEvent(MouseEvent e) { + if (e.getX() < 20) { + if (e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown()) { + int[] indices = getSelectedIndices(); + if (indices.length == 0) { + super.processMouseEvent(e); + } + } else { + super.processMouseEvent(e); + } + } else { + super.processMouseEvent(e); + } + int id = e.getID(); + switch (id) { + case MouseEvent.MOUSE_PRESSED: + break; + case MouseEvent.MOUSE_RELEASED: + break; + case MouseEvent.MOUSE_CLICKED: + doCheck(); + break; + case MouseEvent.MOUSE_EXITED: + break; + case MouseEvent.MOUSE_ENTERED: + break; + } + } + + @Override + protected void processMouseMotionEvent(MouseEvent e) { + if (e.getX() < 20) { + return; + } + + super.processMouseEvent(e); + } + + @Override + public Object[] getSelectedValues() { + List list = new ArrayList(selects.length); + for (int i = 0; i < selects.length; i++) { + if (selects[i]) { + list.add(this.getModel().getElementAt(i)); + } + } + + return list.toArray(); + } + + } + + private void doCheck() { + // p:这里必须改变所有选择checkbox. + int index = jlist.getSelectedIndex(); + boolean sValue = !selects[index]; + + // p:开始设置所有选择的checkbox. + int[] indices = jlist.getSelectedIndices(); + for (int i = 0; i < indices.length; i++) { + setSelected(indices[i], sValue); + } + for (boolean selected : selects) { + if (!selected) { + chooseAll.setSelected(false); + return; + } + } + chooseAll.setSelected(true); + repaint(); + } + + private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); + + private class CheckListCellRenderer extends UICheckBox implements ListCellRenderer { + + public CheckListCellRenderer() { + this.setOpaque(true); + this.setBorder(noFocusBorder); + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + this.setText(value2Text(value)); + this.setSelected(selects[index]); + this.setFont(list.getFont()); + + if (isSelected) { + this.setBackground(list.getSelectionBackground()); + this.setForeground(list.getSelectionForeground()); + } else { + this.setBackground(list.getBackground()); + this.setForeground(list.getForeground()); + } + + if (cellHasFocus) { + this.setBorder(UIManager.getBorder("List.focusCellHighlightBorder")); + } else { + this.setBorder(noFocusBorder); + } + + return this; + } + } + + public void addCheckBoxListSelectionChangeListener(CheckBoxListSelectionChangeListener l) { + this.listenerList.add(CheckBoxListSelectionChangeListener.class, l); + } + + public void removeCheckBoxListSelectionChangeListener(CheckBoxListSelectionChangeListener l) { + this.listenerList.remove(CheckBoxListSelectionChangeListener.class, l); + } + + public void fireCheckBoxListSelectionChangeListener() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == CheckBoxListSelectionChangeListener.class) { + ((CheckBoxListSelectionChangeListener)listeners[i + 1]).selectionChanged(this); + } + } + + } + + public static interface CheckBoxListSelectionChangeListener extends EventListener { + public void selectionChanged(CheckBoxList target); + } + + public ListModel getModel() { + return jlist.getModel(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/DefaultListCellEditor.java b/designer_base/src/com/fr/design/gui/ilist/DefaultListCellEditor.java new file mode 100644 index 0000000000..4360fe0e11 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/DefaultListCellEditor.java @@ -0,0 +1,50 @@ +package com.fr.design.gui.ilist; + +import java.awt.Component; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; + +import javax.swing.DefaultCellEditor; +import javax.swing.JList; + +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.gui.itextfield.UITextField; + + + +public class DefaultListCellEditor extends DefaultCellEditor implements ListCellEditor { + private UITextField textField; + + public DefaultListCellEditor(final UITextField textField) { + super(textField); + this.textField = textField; + } + + public DefaultListCellEditor(final UICheckBox checkBox) { + super(checkBox); + } + + public DefaultListCellEditor(final UIComboBox comboBox) { + super(comboBox); + } + + public Component getListCellEditorComponent(JList list, Object value, boolean isSelected, int index) { + delegate.setValue(value); + + if (textField != null) { + textField.addFocusListener(new FocusAdapter() { + + public void focusLost(FocusEvent e) { + + stopCellEditing(); + + } + + }); + } + + + return editorComponent; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/JNameEdList.java b/designer_base/src/com/fr/design/gui/ilist/JNameEdList.java new file mode 100644 index 0000000000..46630ce6cc --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/JNameEdList.java @@ -0,0 +1,395 @@ +package com.fr.design.gui.ilist; + +import com.fr.general.NameObject; +import com.fr.base.Utils; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.general.Inter; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; +import com.fr.stable.core.PropertyChangeAdapter; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Vector; + +public class JNameEdList extends UIList implements CellEditorListener { + private static final int TEST_LIST_LENTH = 20; + private static final int ICON_WIDTH = 20; + private boolean editable = true; + + // kunsnat: 是否强制ListName是数字 (int型) + private boolean isNameShouldNumber = false; + + transient protected ListCellEditor cellEditor; + transient protected Component editorComp; + transient protected int editingIndex; + private PropertyChangeAdapter editingListner; + private java.util.List ll = new ArrayList(); + + public JNameEdList(ListModel dataModel) { + super(dataModel); + } + + public JNameEdList(final Object[] listData) { + super(listData); + } + + public JNameEdList(final Vector listData) { + super(listData); + } + + public JNameEdList() { + super(); + } + + /* + * Sets是否可编辑 + */ + public void setEditable(boolean editable) { + this.editable = editable; + } + + /** + * 是否可编辑 + * + * @return 是则返回true + */ + public boolean isEditable() { + return this.editable; + } + + public void setNameShouldNumber(boolean isNameShouldNumber) { + this.isNameShouldNumber = isNameShouldNumber; + } + + /** + * 是否强制ListName是数字 (int型) + * + * @return 是则返回true + */ + public boolean isNameShouldNumber() { + return isNameShouldNumber; + } + + /** + * 添加名字改变时的listener + * + * @param l 监听器 + */ + public void addModNameActionListener(ModNameActionListener l) { + ll.add(l); + } + + /** + * 编辑时的监听器 + * + * @param l 监听器 + */ + public void addEditingListner(PropertyChangeAdapter l) { + this.editingListner = l; + } + + /** + * 移除某名字改变时的listener + * + * @param l 监听器 + */ + public void removeModNameActionListener(ModNameActionListener l) { + ll.remove(l); + } + + public ListCellEditor getCellEditor() { + if (cellEditor == null) { + UITextField editField = new UITextField(); + if (editingListner != null) { + editField.addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent e) { + editingListner.propertyChange(); + + } + + @Override + public void focusGained(FocusEvent e) { + // TODO Auto-generated method stub + + } + }); + } + cellEditor = new DefaultListCellEditor(editField) { + public boolean stopCellEditing() { + boolean isTrue = super.stopCellEditing(); + stopEditing(); + + return isTrue; + } + }; + cellEditor.addCellEditorListener(this); + } + + return cellEditor; + } + + protected void doAfterLostFocus() { + + } + + public void setCellEditor(ListCellEditor editor) { + this.cellEditor = editor; + } + + /* + * 取得index节点的名字 + */ + public String getNameAt(int index) { + Nameable nameable = ((ListModelElement) getModel().getElementAt(index)).wrapper; + if (nameable != null) { + return nameable.getName(); + } + + return null; + } + + public Object getType(int index) { + Nameable nameable = ((ListModelElement) getModel().getElementAt(index)).wrapper; + if (nameable != null && nameable instanceof NameObject) { + return ((NameObject) nameable).getObject(); + } + return null; + } + + + public void setWarnigText() { + setWarnigText(this.getSelectedIndex()); + } + + public void setWarnigText(int index) { + setNameAt(Inter.getLocText("Please_Rename") + "!", index); + this.repaint(); + } + + /* + * 设置index节点的名字 + */ + // b:edit改变name的时候怎么办? + public void setNameAt(String name, int index) { + Nameable nameable = ((ListModelElement) getModel().getElementAt(index)).wrapper; + if (nameable != null) { + String oldName = nameable.getName(); + + if (isNameShouldNumber()) { + // kunsnat: 限制只能是数字(int型) + Number number = Utils.string2Number(name); + if (number == null) { + nameable.setName(oldName); + } else { + int newName = number.intValue(); + nameable.setName(String.valueOf(newName)); + } + } else { + nameable.setName(name); + } + + for (int i = 0, len = ll.size(); i < len; i++) { + ll.get(i).nameModed(index, oldName, name); + } + } + } + + /* + * 编辑第index个item + */ + private String oldName; + + /** + * 编辑第index项 + * + * @param index 序号 + * @return 成功返回true + */ + public boolean editItemAt(int index) { + // 如果不可编辑,返回 + if (!this.editable) { + return false; + } + + if (cellEditor != null && !cellEditor.stopCellEditing()) { + return false; + } + if (index < 0 || index >= this.getModel().getSize()) { + return false; + } + + ListCellEditor editor = getCellEditor(); + Object value = editor.getCellEditorValue(); + if (!StringUtils.isBlank(value.toString())) { + oldName = value.toString(); + } + editorComp = prepareEditor(editor, index); + if (editorComp == null) { + return false; + } + Rectangle rect = this.getCellBounds(index, index); + // alex:所有的JNameEdList都有Icon,空出前面20 * 20的位置就是放的Icon + rect.setRect(createRect(rect, ICON_WIDTH)); + + editorComp.setBounds(rect); + add(editorComp); + editorComp.validate(); + editorComp.requestFocus(); + if (editorComp instanceof UITextField) { + ((UITextField) editorComp).selectAll(); + } + + setEditingIndex(index); + + return true; + } + + public Rectangle createRect(Rectangle rect, int iconWidth) { + return new Rectangle(rect.x + iconWidth, rect.y, rect.width - iconWidth, rect.height); + } + + public String getEditingName() { + return (String) getCellEditor().getCellEditorValue(); + } + + /* + * 根据ListCellEditor取得编辑器的Component + */ + private Component prepareEditor(ListCellEditor cellEditor, int index) { + String name = getNameAt(index); + boolean isSelected = this.isSelectedIndex(index); + Component comp = cellEditor.getListCellEditorComponent(this, name, isSelected, index); + + return comp; + } + + /* + * 记录正在编辑的index + */ + private void setEditingIndex(int idx) { + editingIndex = idx; + } + + /** + * 编辑取消 + * + * @param e 事件 + */ + public void editingCanceled(ChangeEvent e) { + removeComp(); + } + + /** + * 编辑结束 + * + * @param e 事件 + */ + public void editingStopped(ChangeEvent e) { + doAfterLostFocus(); + stopEditing(); + } + + /** + * 停止编辑事件 + */ + public void stopEditing() { + ListCellEditor editor = getCellEditor(); + if (editor != null && editorComp != null) { + Object value = editor.getCellEditorValue(); + String name = StringUtils.isBlank(value.toString()) ? oldName : value.toString(); + setNameAt(name, editingIndex); + removeComp(); + } + } + + public String[] getAllNames() { + int length = this.getModel().getSize(); + String[] names = new String[length]; + for (int i = 0; i < length; i++) { + names[i] = getNameAt(i); + } + return names; + } + + public Object[] getAllTypes() { + int length = this.getModel().getSize(); + Object[] types = new Object[length]; + for (int i = 0; i < length; i++) { + types[i] = getType(i); + } + return types; + } + + + /* + * 移除编辑器的Component + */ + private void removeComp() { + if (editorComp != null) { + remove(editorComp); + } + Rectangle cellRect = this.getCellBounds(editingIndex, editingIndex); + setEditingIndex(-1); + editorComp = null; + repaint(cellRect); + } + + /** + * 主函数 + * + * @param args 参数 + */ + public static void main(String... args) { + JFrame f = new JFrame(); + JPanel c = (JPanel) f.getContentPane(); + c.setLayout(new BorderLayout()); + ListModelElement[] data = new ListModelElement[TEST_LIST_LENTH]; + for (int i = 0; i < TEST_LIST_LENTH; i++) { + data[i] = new ListModelElement(new NameObject(i + 1 + "", i)); + } + final JNameEdList list = new JNameEdList(data); + list.setEditable(true); + list.addMouseListener(new MouseAdapter() { + public void mouseReleased(MouseEvent evt) { + list.stopEditing(); + if (evt.getClickCount() >= 2 + && SwingUtilities.isLeftMouseButton(evt)) { + list.editItemAt(list.getSelectedIndex()); + } + } + }) + ; + + list.setCellEditor(new DefaultListCellEditor(new UITextField())); + list.setCellRenderer(new NameableListCellRenderer()); + c.add(list, BorderLayout.CENTER); + f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + f.setSize(400, 600); + f.setVisible(true); + } + + private static class NameableListCellRenderer extends DefaultListCellRenderer { + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + if (value instanceof Nameable) { + Nameable wrappee = (Nameable) value; + this.setText(wrappee.getName()); + } + return this; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/ListCellEditor.java b/designer_base/src/com/fr/design/gui/ilist/ListCellEditor.java new file mode 100644 index 0000000000..4f98810511 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/ListCellEditor.java @@ -0,0 +1,8 @@ +package com.fr.design.gui.ilist; + +import javax.swing.CellEditor; + +public interface ListCellEditor extends CellEditor { + public java.awt.Component getListCellEditorComponent( + javax.swing.JList list, java.lang.Object value, boolean isSelected, int index); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/ListModelElement.java b/designer_base/src/com/fr/design/gui/ilist/ListModelElement.java new file mode 100644 index 0000000000..13ced9dc3c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/ListModelElement.java @@ -0,0 +1 @@ +package com.fr.design.gui.ilist; import com.fr.general.ComparatorUtils; import com.fr.stable.Nameable; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 13-1-2 * Time: 下午2:39 */ public class ListModelElement { public Nameable wrapper; public ListModelElement(Nameable nameable) { this.wrapper = nameable; } public boolean equals(Object o) { return o instanceof ListModelElement && ComparatorUtils.equals(((ListModelElement) o).wrapper, wrapper); } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/ModNameActionListener.java b/designer_base/src/com/fr/design/gui/ilist/ModNameActionListener.java new file mode 100644 index 0000000000..a892cfc98b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/ModNameActionListener.java @@ -0,0 +1,11 @@ +package com.fr.design.gui.ilist; + +/* + * 专门给JNameEdList用的,当名字改变时的执行的Action + */ +public interface ModNameActionListener { + /* + * 第index个item的名字由oldName改为newName了 + */ + public void nameModed(int index, String oldName, String newName); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/QuickList.java b/designer_base/src/com/fr/design/gui/ilist/QuickList.java new file mode 100644 index 0000000000..9e87e10197 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/QuickList.java @@ -0,0 +1,41 @@ +package com.fr.design.gui.ilist; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.JList; +import javax.swing.ListModel; + +import com.fr.general.ComparatorUtils; + +/** + * 支持键盘输入快速查找项的JList + * + * @editor zhou + * @since 2012-3-28下午3:10:58 + */ +public class QuickList extends JList { + private ListModel listModel; + + public QuickList(ListModel model) { + super(model); + this.listModel = model; + initList(); + } + + private void initList() { + this.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + String key = e.getKeyChar() + ""; + for (int i = 0; i < listModel.getSize(); i++) { + String first = listModel.getElementAt(i).toString(); + if (ComparatorUtils.equals(first, key) && !ComparatorUtils.equals(i, QuickList.this.getSelectedIndex())) { + QuickList.this.setSelectedIndex(i); + break; + } + } + } + }); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/TableViewList.java b/designer_base/src/com/fr/design/gui/ilist/TableViewList.java new file mode 100644 index 0000000000..f570033b55 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/TableViewList.java @@ -0,0 +1,278 @@ +package com.fr.design.gui.ilist; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.data.core.DataCoreUtils; +import com.fr.data.core.db.TableProcedure; +import com.fr.data.core.db.dialect.DialectFactory; +import com.fr.data.core.db.dialect.OracleDialect; +import com.fr.data.impl.Connection; +import com.fr.design.DesignerEnvManager; +import com.fr.design.constants.UIConstants; +import com.fr.design.mainframe.dnd.SerializableTransferable; +import com.fr.file.DatasourceManager; +import com.fr.file.DatasourceManagerProvider; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.dnd.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; +import java.util.concurrent.CancellationException; + +/** + * 表或者视图或者存储过程组成的一个下拉列表 + * + * @author zhou + * @since 2012-3-28下午10:07:34 + */ +public class TableViewList extends UIList { + + /** + * + */ + private static final long serialVersionUID = 2297780743855004708L; + private SwingWorker refreshList; + private Object object = null; + + + public TableViewList() { + super(); + this.setBackground(UIConstants.NORMAL_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + this.setCellRenderer(new TableListCellRenderer()); + new TableProcessorTreeDragSource(this, DnDConstants.ACTION_COPY); + this.addFocusListener(new FocusAdapter() { + + @Override + public void focusLost(FocusEvent e) { + TableViewList.this.clearSelection(); + } + }); + this.addMouseListener(new MouseAdapter() { + + public void mousePressed(MouseEvent e) { + object = getSelectedValue(); + } + + }); + + } + + /** + * august:databaseName是数据库名字,searchFilter是输入的过滤条件,typesFilter是视图、表、 + * 存储过程中的一者或者几者 + * + * @param databaseName + * @param searchFilter + * @param typesFilter + */ + public void populate(final String databaseName, final String searchFilter, final String... typesFilter) { + DefaultListModel defaultListModel = new DefaultListModel(); + defaultListModel.addElement(UIConstants.PENDING); + final DefaultListModel failed = new DefaultListModel(); + failed.addElement(UIConstants.CONNECTION_FAILED); + this.setModel(defaultListModel); + if (refreshList != null) { + refreshList.cancel(true); + } + refreshList = new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + Connection datasource = DatasourceManager.getProviderInstance().getConnection(databaseName); + boolean status = false; + int count = 3; + //总共给3次连接的机会 + while (!status && count > 0) { + status = FRContext.getCurrentEnv().testConnection(datasource); + count--; + } + if (!status) { + throw new Exception(Inter.getLocText("Datasource-Connection_failed")); + } + TableViewList.this.setModel(processDataInAnotherThread(databaseName, searchFilter, typesFilter)); + return null; + } + + public void done() { + try { + get(); + } catch (Exception e) { + if (!(e instanceof InterruptedException) && !(e instanceof CancellationException)) { + TableViewList.this.setModel(failed); + FRContext.getLogger().error(e.getMessage(), e); + } + } + } + }; + if (databaseName != null) { + refreshList.execute(); + } + } + + /** + * august:databaseName是数据库名字,searchFilter是输入的过滤条件,typesFilter是视图、表、 + * 存储过程中的一者或者几者 + * + * @param databaseName + * @param searchFilter + * @param typesFilter + */ + private DefaultListModel processDataInAnotherThread(String databaseName, String searchFilter, String... typesFilter) throws Exception { + DefaultListModel defaultListModel = new DefaultListModel(); + DatasourceManagerProvider datasourceManager = DatasourceManager.getProviderInstance(); + Connection datasource = datasourceManager.getConnection(databaseName); + if (datasource == null) { + return defaultListModel; + } + String[] schemas = DataCoreUtils.getDatabaseSchema(datasource); + + searchFilter = searchFilter.toLowerCase(); + + + boolean isOracle = FRContext.getCurrentEnv().isOracle(datasource); + boolean isOracleSystemSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); + // oracleb不勾选显示所有表,则只显示用户下的(包括存储过程和table表) + if (isOracle && !isOracleSystemSpace) { + java.sql.Connection connection = datasource.createConnection(); + OracleDialect orcDialect = (OracleDialect)DialectFactory.generateDialect(connection); + schemas = new String[]{orcDialect.getOracleCurrentUserSchema(connection)}; + } + + if (typesFilter.length == 1 && ComparatorUtils.equals(typesFilter[0], TableProcedure.PROCEDURE)) { + return processStoreProcedure(defaultListModel, schemas, datasource, isOracle, searchFilter); + } else { + return processTableAndView(defaultListModel, schemas, datasource, searchFilter, isOracle, typesFilter); + } + } + + private DefaultListModel processStoreProcedure(DefaultListModel defaultListModel, String[] schemas, Connection datasource, boolean isOracle, String searchFilter) throws Exception { + boolean isBlank = StringUtils.isBlank(searchFilter); + @SuppressWarnings("unchecked") + boolean isOracleSysSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); + List sqlTablees = DataCoreUtils.getProcedures(datasource, schemas, isOracle, isOracleSysSpace); + for (TableProcedure[] sqlTables : sqlTablees) { + if (sqlTables == null) { + continue; + } + for (TableProcedure sqlTable : sqlTables) { + String name = sqlTable.toString().toLowerCase(); + if (isBlank || name.indexOf(searchFilter) != -1) { + defaultListModel.addElement(sqlTable); + } + } + } + return defaultListModel; + } + + private DefaultListModel processTableAndView(DefaultListModel defaultListModel, String[] schemas, Connection datasource, String searchFilter, boolean isOracle, String... typesFilter) + throws Exception { + boolean isBlank = StringUtils.isBlank(searchFilter); + boolean isOracleSystemSpace = DesignerEnvManager.getEnvManager().isOracleSystemSpace(); + if (!isOracle) { + String schema = null; + for (String type : typesFilter) { + //非oracle数据库,默认都是显示所有表的,参数为true + TableProcedure[] sqlTables = DataCoreUtils.getTables(datasource, type, schema, true); + for (int i = 0; i < sqlTables.length; i++) { + if (isBlank || sqlTables[i].getName().toLowerCase().indexOf(searchFilter) != -1) { + defaultListModel.addElement(sqlTables[i]); + } + } + } + } else { + for (String type : typesFilter) { + for (String schema : schemas) { + TableProcedure[] sqlTables = DataCoreUtils.getTables(datasource, type, schema, isOracleSystemSpace); + // oracle的表名加上模式 + for (int i = 0; i < sqlTables.length; i++) { + TableProcedure ta = sqlTables[i]; + String name = ta.getSchema() + '.' + ta.getName(); + if (isBlank || name.toLowerCase().indexOf(searchFilter) != -1) { + defaultListModel.addElement(sqlTables[i]); + } + } + } + } + } + return defaultListModel; + } + + /** + * 显示器 + * + * @editor zhou + * @since 2012-3-28下午10:11:58 + */ + private class TableListCellRenderer extends DefaultListCellRenderer { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + TableProcedure tableProcedure = null; + if (value instanceof TableProcedure) { + tableProcedure = (TableProcedure) value; + this.setText(tableProcedure.toString()); + } else if (value == UIConstants.PENDING) { + this.setText(UIConstants.PENDING.toString()); + } else { + return this; + } + String type = tableProcedure == null ? null : tableProcedure.getType(); + Icon icon = null; + if (ComparatorUtils.equals(type, TableProcedure.TABLE)) { + icon = BaseUtils.readIcon("/com/fr/design/images/data/tables.png"); + } else if (ComparatorUtils.equals(type, TableProcedure.VIEW)) { + icon = BaseUtils.readIcon("/com/fr/design/images/data/views.png"); + } else { + icon = BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png"); + } + this.setIcon(icon); + + return this; + } + } + + /** + * 拖拽 + * + * @editor zhou + * @since 2012-3-28下午10:11:36 + */ + private class TableProcessorTreeDragSource extends DragSourceAdapter implements DragGestureListener { + private DragSource source; + + public TableProcessorTreeDragSource(JList jList, int actions) { + source = new DragSource(); + source.createDefaultDragGestureRecognizer(jList, actions, this); + } + + + /** + * Drag Gesture Handler + */ + public void dragGestureRecognized(DragGestureEvent dge) { + setSelectedValue(object, false); + Component comp = dge.getComponent(); + if (!(comp instanceof TableViewList)) { + return; + } + + TableViewList list = (TableViewList) comp; + TableProcedure tableProcedure = null; + Object obj = list.getSelectedValue(); + if (obj instanceof TableProcedure) { + tableProcedure = (TableProcedure) obj; + } + if (tableProcedure != null) { + source.startDrag(dge, DragSource.DefaultLinkDrop, new SerializableTransferable(tableProcedure), this); + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ilist/UIList.java b/designer_base/src/com/fr/design/gui/ilist/UIList.java new file mode 100644 index 0000000000..b01f40f0b8 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ilist/UIList.java @@ -0,0 +1,80 @@ +package com.fr.design.gui.ilist; + +import com.fr.data.core.db.TableProcedure; +import com.fr.design.gui.itooltip.UIToolTip; +import com.fr.design.mainframe.JTemplate; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.util.Vector; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-5-22 + * Time: 上午11:07 + * To change this template use File | Settings | File Templates. + */ +public class UIList extends JList{ + private Icon icon; + + public UIList() { + super(); + } + + public UIList(ListModel dataModel) { + super(dataModel); + } + + public UIList(Object[] listData) { + super(listData); + } + + public UIList(Vector listData) { + super(listData); + } + + public String getToolTipText(MouseEvent event) { + int index = locationToIndex(event.getPoint()); + icon = new ImageIcon(); + if (index != -1) { + Object value = getModel().getElementAt(index); + ListCellRenderer renderer = getCellRenderer(); + Component rendererComp = renderer.getListCellRendererComponent(this, value, index, true, false); + if (rendererComp.getPreferredSize().width > getVisibleRect().width) { + String tips = (rendererComp instanceof JComponent) ? ((JComponent) rendererComp).getToolTipText() : null; + if (tips == null) { + if(value instanceof JTemplate){ + tips = ((JTemplate) value).getEditingFILE().getName(); + icon = ((JTemplate) value).getEditingFILE().getIcon(); + } else if (value instanceof ListModelElement || value instanceof TableProcedure){ + tips = ((JLabel)rendererComp).getText(); + icon = ((JLabel)rendererComp).getIcon(); + } + } + return tips; + } else { + return null; + } + } + return null; + } + + @Override + public Point getToolTipLocation(MouseEvent event) { + int index = locationToIndex(event.getPoint()); + if (index != -1 && StringUtils.isNotEmpty(getToolTipText(event))) { + Rectangle cellBounds = getCellBounds(index, index); + return new Point(cellBounds.x - 2, cellBounds.y - 1); + } + return null; + } + public JToolTip createToolTip() { + UIToolTip tip = new UIToolTip(icon); + tip.setComponent(this); + tip.setOpaque(false); + return tip; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIBasicMenuItemUI.java b/designer_base/src/com/fr/design/gui/imenu/UIBasicMenuItemUI.java new file mode 100644 index 0000000000..a4a2eb9475 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIBasicMenuItemUI.java @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.imenu; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.*; +import javax.swing.plaf.basic.BasicGraphicsUtils; +import javax.swing.plaf.basic.BasicHTML; +import javax.swing.text.View; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-4 + * Time: 下午3:11 + */ +public class UIBasicMenuItemUI extends MenuItemUI { + /* diagnostic aids -- should be false for production builds. */ + private static final boolean TRACE = false; // trace creates and disposes + private static final boolean VERBOSE = false; // show reuse hits/misses + private static final boolean DEBUG = true; // show bad params, misc. + private static final int DEFAULT_TEXT_ICON_GAP = 8; // Should be from table + private static final int DEFAULT_ICON_GAP = 4; // Should be from table + + protected JMenuItem menuItem = null; + protected Color selectionBackground; + protected Color selectionForeground; + protected Color disabledForeground; + protected Color acceleratorForeground; + protected Color acceleratorSelectionForeground; + private String acceleratorDelimiter; + + protected static int defaultTextIconGap, defaultIconGap; + protected Font acceleratorFont; + + protected MouseInputListener mouseInputListener; + protected MenuDragMouseListener menuDragMouseListener; + protected MenuKeyListener menuKeyListener; + private PropertyChangeListener propertyChangeListener; + + protected Icon arrowIcon = null; + protected Icon checkIcon = null; + + protected boolean oldBorderPainted; + + /** + * Used for accelerator binding, lazily created. + */ + InputMap windowInputMap; + + /* Client Property keys for text and accelerator text widths */ + static final String MAX_TEXT_WIDTH = "maxTextWidth"; + static final String MAX_ACC_WIDTH = "maxAccWidth"; + static final String MAX_ICON_WIDTH = "maxIconWidth"; + + /** + * 加载UI + * + * @param c 组件 + */ + public void installUI(JComponent c) { + menuItem = (JMenuItem) c; + installDefaults(); + installComponents(menuItem); + installListeners(); + installKeyboardActions(); + } + + /** + * @since 1.3 + */ + protected void installComponents(JMenuItem menuItem) { + BasicHTML.updateRenderer(menuItem, menuItem.getText()); + } + + protected String getPropertyPrefix() { + return "MenuItem"; + } + + protected void installListeners() { + if ((mouseInputListener = createMouseInputListener(menuItem)) != null) { + menuItem.addMouseListener(mouseInputListener); + menuItem.addMouseMotionListener(mouseInputListener); + } + + if ((menuDragMouseListener = createMenuDragMouseListener(menuItem)) != null) { + menuItem.addMenuDragMouseListener(menuDragMouseListener); + } + + // removed in 1.3.06 because installing additional listeners + // is unnecessary and caused malfunctions with sub menus +// if((menuKeyListener = createMenuKeyListener(menuItem)) != null) { +// menuItem.addMenuKeyListener(menuKeyListener); +// } + + if ((propertyChangeListener = createPropertyChangeListener(menuItem)) != null) { + menuItem.addPropertyChangeListener(propertyChangeListener); + } + } + + protected void installKeyboardActions() { + ActionMap actionMap = getActionMap(); + + SwingUtilities.replaceUIActionMap(menuItem, actionMap); + updateAcceleratorBinding(); + } + + /** + * 去除UI + * + * @param c 组件 + */ + public void uninstallUI(JComponent c) { + menuItem = (JMenuItem) c; + uninstallDefaults(); + uninstallComponents(menuItem); + uninstallListeners(); + uninstallKeyboardActions(); + + //Remove the textWidth and accWidth values from the parent's Client Properties. + Container parent = menuItem.getParent(); + if ((parent != null && parent instanceof JComponent) && !(menuItem instanceof JMenu && ((JMenu) menuItem).isTopLevelMenu())) { + JComponent p = (JComponent) parent; + p.putClientProperty(MAX_ACC_WIDTH, null); + p.putClientProperty(MAX_TEXT_WIDTH, null); + } + + menuItem = null; + } + + protected void uninstallDefaults() { + LookAndFeel.uninstallBorder(menuItem); + menuItem.setBorderPainted(oldBorderPainted); + if (menuItem.getMargin() instanceof UIResource) { + menuItem.setMargin(null); + } + if (arrowIcon instanceof UIResource) { + arrowIcon = null; + } + if (checkIcon instanceof UIResource) { + checkIcon = null; + } + } + + /** + * @since 1.3 + */ + protected void uninstallComponents(JMenuItem menuItem) { + BasicHTML.updateRenderer(menuItem, ""); + } + + protected void uninstallListeners() { + if (mouseInputListener != null) { + menuItem.removeMouseListener(mouseInputListener); + menuItem.removeMouseMotionListener(mouseInputListener); + } + if (menuDragMouseListener != null) { + menuItem.removeMenuDragMouseListener(menuDragMouseListener); + } +// if(menuKeyListener != null) { +// menuItem.removeMenuKeyListener(menuKeyListener); +// } + if (propertyChangeListener != null) { + menuItem.removePropertyChangeListener(propertyChangeListener); + } + + mouseInputListener = null; + menuDragMouseListener = null; + menuKeyListener = null; + propertyChangeListener = null; + } + + protected void uninstallKeyboardActions() { + SwingUtilities.replaceUIActionMap(menuItem, null); + if (windowInputMap != null) { + SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, null); + windowInputMap = null; + } + } + + protected MouseInputListener createMouseInputListener(JComponent c) { + return new MouseInputHandler(); + } + + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) { + return new MenuDragMouseHandler(); + } + + private PropertyChangeListener createPropertyChangeListener(JComponent c) { + return new PropertyChangeHandler(); + } + + ActionMap getActionMap() { + String propertyPrefix = getPropertyPrefix(); + String uiKey = propertyPrefix + ".actionMap"; + ActionMap am = (ActionMap) UIManager.get(uiKey); + + if (am == null) { + am = createActionMap(); + UIManager.getLookAndFeelDefaults().put(uiKey, am); + } + + return am; + } + + ActionMap createActionMap() { + ActionMap map = new ActionMapUIResource(); + map.put("doClick", new ClickAction()); + + return map; + } + + InputMap createInputMap(int condition) { + if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) { + return new ComponentInputMapUIResource(menuItem); + } + return null; + } + + void updateAcceleratorBinding() { + KeyStroke accelerator = menuItem.getAccelerator(); + + if (windowInputMap != null) { + windowInputMap.clear(); + } + + if (accelerator != null) { + if (windowInputMap == null) { + windowInputMap = createInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + SwingUtilities.replaceUIInputMap(menuItem, + JComponent.WHEN_IN_FOCUSED_WINDOW, windowInputMap); + } + windowInputMap.put(accelerator, "doClick"); + } + } + + public Dimension getMinimumSize(JComponent c) { + Dimension d = null; + View v = (View) c.getClientProperty(BasicHTML.propertyKey); + if (v != null) { + d = getPreferredSize(c); + d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS); + } + return d; + } + + public Dimension getPreferredSize(JComponent c) { + return getPreferredMenuItemSize(c, checkIcon, arrowIcon, DEFAULT_TEXT_ICON_GAP); + } + + /** + * Renders the text of the current menu item. + *

+ * + * @param g graphics context + * @param menuItem menu item to render + * @param textRect bounding rectangle for rendering the text + * @param text string to render + * @since 1.4 + */ + protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { + ButtonModel model = menuItem.getModel(); + FontMetrics fm = g.getFontMetrics(); + int mnemIndex = menuItem.getDisplayedMnemonicIndex(); + + if (!model.isEnabled()) { + // *** paint the text disabled + g.setColor(ThemeUtils.MENU_DISABLED_FG_COLOR); + BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); + } else { + boolean isSelected = menuItem instanceof JMenu && model.isSelected(); + // *** paint the text normally + if (isTopLevelMenu()) { + if (menuItem.getClientProperty("rollover") == Boolean.TRUE && + ThemeUtils.MENU_ROLLOVER && !model.isSelected()) { + g.setColor(ThemeUtils.MENU_ROLLOVER_FG_COLOR); + } else { + if (!(menuItem.getForeground() instanceof ColorUIResource)) { + g.setColor(menuItem.getForeground()); + } else { + g.setColor(ThemeUtils.MENU_FONT_COLOR); + } + } + } else if (model.isArmed() || isSelected) { + g.setColor(ThemeUtils.MENU_SELECTED_TEXT_COLOR); + } else { + // normal + g.setColor(menuItem.getForeground()); + } + + BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent()); + } + } + + public Dimension getMaximumSize(JComponent c) { + Dimension d = null; + View v = (View) c.getClientProperty(BasicHTML.propertyKey); + if (v != null) { + d = getPreferredSize(c); + d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS); + } + return d; + } + + // these rects are used for painting and preferredsize calculations. + // they used to be regenerated constantly. Now they are reused. + static Rectangle zeroRect = new Rectangle(0, 0, 0, 0); + static Rectangle iconRect = new Rectangle(); + static Rectangle textRect = new Rectangle(); + static Rectangle acceleratorRect = new Rectangle(); + static Rectangle checkIconRect = new Rectangle(); + static Rectangle arrowIconRect = new Rectangle(); + static Rectangle viewRect = new Rectangle(Short.MAX_VALUE, Short.MAX_VALUE); + static Rectangle r = new Rectangle(); + + private void resetRects() { + iconRect.setBounds(zeroRect); + textRect.setBounds(zeroRect); + acceleratorRect.setBounds(zeroRect); + checkIconRect.setBounds(zeroRect); + arrowIconRect.setBounds(zeroRect); + viewRect.setBounds(0, 0, Short.MAX_VALUE, Short.MAX_VALUE); + r.setBounds(zeroRect); + } + + /** + * We draw the background in paintMenuItem() + * so override update (which fills the background of opaque + * components by default) to just call paint(). + */ + public void update(Graphics g, JComponent c) { + paint(g, c); + } + + public void paint(Graphics g, JComponent c) { + paintMenuItem(g, c, checkIcon, arrowIcon, + selectionBackground, selectionForeground, DEFAULT_TEXT_ICON_GAP); + } + + /* + * Returns true if the component is a JMenu and it is a top + * level menu (on the menubar). + */ + private boolean isTopLevelMenu() { + if ((menuItem instanceof JMenu) && (((JMenu) menuItem).isTopLevelMenu())) { + return true; + } + + return false; + } + + public MenuElement[] getPath() { + MenuSelectionManager m = MenuSelectionManager.defaultManager(); + MenuElement[] oldPath = m.getSelectedPath(); + MenuElement[] newPath; + int i = oldPath.length; + if (i == 0) { + return new MenuElement[0]; + } + Component parent = menuItem.getParent(); + if (oldPath[i - 1].getComponent() == parent) { + // The parent popup menu is the last so far + newPath = new MenuElement[i + 1]; + System.arraycopy(oldPath, 0, newPath, 0, i); + newPath[i] = menuItem; + } else { + // A sibling menuitem is the current selection + // + // This probably needs to handle 'exit submenu into + // a menu item. Search backwards along the current + // selection until you find the parent popup menu, + // then copy up to that and add yourself... + int j; + for (j = oldPath.length - 1; j >= 0; j--) { + if (oldPath[j].getComponent() == parent) { + break; + } + } + newPath = new MenuElement[j + 2]; + System.arraycopy(oldPath, 0, newPath, 0, j + 1); + newPath[j + 1] = menuItem; + + } + return newPath; + } + + protected class MouseInputHandler implements MouseInputListener { + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + Point p = e.getPoint(); + boolean isxContains = p.x >= 0 && p.x < menuItem.getWidth(); + boolean isyContains = p.y >= 0 && p.y < menuItem.getHeight(); + if (isxContains && isyContains) { + doClick(manager); + } else { + manager.processMouseEvent(e); + } + } + + public void mouseEntered(MouseEvent e) { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + int modifiers = e.getModifiers(); + // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2 + if ((modifiers & (InputEvent.BUTTON1_MASK | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) != 0) { + MenuSelectionManager.defaultManager().processMouseEvent(e); + } else { + manager.setSelectedPath(getPath()); + } + } + + public void mouseExited(MouseEvent e) { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + + int modifiers = e.getModifiers(); + // 4188027: drag enter/exit added in JDK 1.1.7A, JDK1.2 + if ((modifiers & (InputEvent.BUTTON1_MASK | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK)) != 0) { + MenuSelectionManager.defaultManager().processMouseEvent(e); + } else { + + MenuElement[] path = manager.getSelectedPath(); + if (path.length > 1) { + MenuElement[] newPath = new MenuElement[path.length - 1]; + int i, c; + for (i = 0, c = path.length - 1; i < c; i++) { + newPath[i] = path[i]; + } + manager.setSelectedPath(newPath); + } + } + } + + public void mouseDragged(MouseEvent e) { + MenuSelectionManager.defaultManager().processMouseEvent(e); + } + + public void mouseMoved(MouseEvent e) { + } + } + + private class MenuDragMouseHandler implements MenuDragMouseListener { + public void menuDragMouseEntered(MenuDragMouseEvent e) { + } + + public void menuDragMouseDragged(MenuDragMouseEvent e) { + MenuSelectionManager manager = e.getMenuSelectionManager(); + MenuElement[] path = e.getPath(); + manager.setSelectedPath(path); + } + + public void menuDragMouseExited(MenuDragMouseEvent e) { + } + + public void menuDragMouseReleased(MenuDragMouseEvent e) { + MenuSelectionManager manager = e.getMenuSelectionManager(); + Point p = e.getPoint(); + boolean isxContains = p.x >= 0 && p.x < menuItem.getWidth(); + boolean isyContains = p.y >= 0 && p.y < menuItem.getHeight(); + if (isxContains && isyContains) { + doClick(manager); + } else { + manager.clearSelectedPath(); + } + } + } + + private class PropertyChangeHandler implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent e) { + String name = e.getPropertyName(); + boolean isquick = ComparatorUtils.equals(name, "displayedMnemonic") || ComparatorUtils.equals(name, "accelerator"); + boolean istextRelate = ComparatorUtils.equals(name, "text") || ComparatorUtils.equals(name, "font"); + if (ComparatorUtils.equals(name, "labelFor") || isquick) { + updateAcceleratorBinding(); + } else if (istextRelate || ComparatorUtils.equals(name, "foreground")) { + // remove the old html view client property if one + // existed, and install a new one if the text installed + // into the JLabel is html source. + JMenuItem lbl = ((JMenuItem) e.getSource()); + String text = lbl.getText(); + BasicHTML.updateRenderer(lbl, text); + } + } + } + + private static class ClickAction extends AbstractAction { + public void actionPerformed(ActionEvent e) { + JMenuItem mi = (JMenuItem) e.getSource(); + MenuSelectionManager.defaultManager().clearSelectedPath(); + mi.doClick(); + } + } + + /** + * Call this method when a menu item is to be activated. + * This method handles some of the details of menu item activation + * such as clearing the selected path and messaging the + * JMenuItem's doClick() method. + * + * @param msm A MenuSelectionManager. The visual feedback and + * internal bookkeeping tasks are delegated to + * this MenuSelectionManager. If null is + * passed as this argument, the + * MenuSelectionManager.defaultManager is + * used. + * @see MenuSelectionManager + * @see JMenuItem#doClick(int) + * @since 1.4 + */ + protected void doClick(MenuSelectionManager msm) { + // Visual feedback + if (msm == null) { + msm = MenuSelectionManager.defaultManager(); + } + msm.clearSelectedPath(); + menuItem.doClick(0); + } + + /** + * This is to see if the menu item in question is part of the + * system menu on an internal frame. + * The Strings that are being checked can be found in + * MetalInternalFrameTitlePaneUI.java, + * WindowsInternalFrameTitlePaneUI.java, and + * MotifInternalFrameTitlePaneUI.java. + * + * @since 1.4 + */ + private boolean isInternalFrameSystemMenu() { + String actionCommand = menuItem.getActionCommand(); + return (actionCommand == "Close") || (actionCommand == "Minimize") || (actionCommand == "Restore") || (actionCommand == "Maximize"); + } + + ////////////////////////////////////////////////////////// + + public static class EmptyIcon implements Icon { + int width; + int height; + + public EmptyIcon(int width, int height) { + this.height = height; + this.width = width; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + return; + } + + public int getIconWidth() { + return width; + } + + public int getIconHeight() { + return height; + } + } + + /** + * 创建UI + * + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIBasicMenuItemUI(); + } + + protected void installDefaults() { + String prefix = getPropertyPrefix(); + + acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont"); + + menuItem.setOpaque(true); + if (menuItem.getMargin() == null || (menuItem.getMargin() instanceof UIResource)) { + menuItem.setMargin(UIManager.getInsets(prefix + ".margin")); + } + + LookAndFeel.installBorder(menuItem, prefix + ".border"); + oldBorderPainted = menuItem.isBorderPainted(); + menuItem.setBorderPainted(((Boolean) (UIManager.get(prefix + ".borderPainted"))).booleanValue()); + LookAndFeel.installColorsAndFont(menuItem, prefix + ".background", prefix + ".foreground", prefix + ".font"); + + // MenuItem specific defaults + if (selectionBackground == null || selectionBackground instanceof UIResource) { + selectionBackground = UIManager.getColor(prefix + ".selectionBackground"); + } + if (selectionForeground == null || selectionForeground instanceof UIResource) { + selectionForeground = UIManager.getColor(prefix + ".selectionForeground"); + } + if (disabledForeground == null || disabledForeground instanceof UIResource) { + disabledForeground = UIManager.getColor(prefix + ".disabledForeground"); + } + if (acceleratorForeground == null || acceleratorForeground instanceof UIResource) { + acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground"); + } + if (acceleratorSelectionForeground == null || acceleratorSelectionForeground instanceof UIResource) { + acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground"); + } + + // Get accelerator delimiter + acceleratorDelimiter = UIManager.getString("MenuItem.acceleratorDelimiter"); + if (acceleratorDelimiter == null) { + acceleratorDelimiter = "+"; + } + + // Icons + if (arrowIcon == null || arrowIcon instanceof UIResource) { + arrowIcon = UIManager.getIcon(prefix + ".arrowIcon"); + } + if (checkIcon == null || checkIcon instanceof UIResource) { + checkIcon = UIManager.getIcon(prefix + ".checkIcon"); + } + + defaultTextIconGap = DEFAULT_TEXT_ICON_GAP; // Should be from table + defaultIconGap = DEFAULT_ICON_GAP; // Should be from table + } + + protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon, + Icon arrowIcon, int defaultTextIconGap) { + JMenuItem b = (JMenuItem) c; + Icon icon = b.getIcon(); + String text = b.getText(); + KeyStroke accelerator = b.getAccelerator(); + String acceleratorText = ""; + if (accelerator != null) { + int modifiers = accelerator.getModifiers(); + if (modifiers > 0) { + acceleratorText = KeyEvent.getKeyModifiersText(modifiers); + //acceleratorText += "-"; + acceleratorText += acceleratorDelimiter; + } + int keyCode = accelerator.getKeyCode(); + if (keyCode != 0) { + acceleratorText += KeyEvent.getKeyText(keyCode); + } else { + acceleratorText += accelerator.getKeyChar(); + } + } + caulateFont(b, icon, text, acceleratorText); + Container parent = menuItem.getParent(); + doWithTopMenu(parent, icon); + if (!isTopLevelMenu()) { + // Add in the checkIcon + r.width += checkIconRect.width; + r.width += defaultTextIconGap; + // Add in the arrowIcon + r.width += defaultTextIconGap; + r.width += arrowIconRect.width; + } + r.width += 2 * defaultTextIconGap; + Insets insets = b.getInsets(); + if (insets != null) { + r.width += insets.left + insets.right; + r.height += insets.top + insets.bottom; + } + // if the width is even, bump it up one. This is critical + // for the focus dash line to draw properly + if (r.width % 2 == 0) { + r.width++; + } + if (r.height % 2 == 0) { + r.height++; + } + return r.getSize(); + } + + private void doWithTopMenu(Container parent, Icon icon) { + if (parent != null && parent instanceof JComponent && + !(menuItem instanceof JMenu && ((JMenu) menuItem).isTopLevelMenu())) { + JComponent p = (JComponent) parent; + + //Get widest text so far from parent, if no one exists null is returned. + Integer maxTextWidth = (Integer) p.getClientProperty(MAX_TEXT_WIDTH); + Integer maxAccWidth = (Integer) p.getClientProperty(MAX_ACC_WIDTH); + Integer maxIconWidth = (Integer) p.getClientProperty(MAX_ICON_WIDTH); // WAS ME + + int maxTextValue = maxTextWidth != null ? maxTextWidth.intValue() : 0; + int maxAccValue = maxAccWidth != null ? maxAccWidth.intValue() : 0; + int maxIconValue = maxIconWidth != null ? maxIconWidth.intValue() : 0; + + //Compare the text widths, and adjust the r.width to the widest. + if (r.width < maxTextValue) { + r.width = maxTextValue; + } else { + p.putClientProperty(UIBasicMenuItemUI.MAX_TEXT_WIDTH, new Integer(r.width)); + } + + //Compare the accelarator widths. + if (acceleratorRect.width > maxAccValue) { + maxAccValue = acceleratorRect.width; + p.putClientProperty(UIBasicMenuItemUI.MAX_ACC_WIDTH, new Integer(acceleratorRect.width)); + } + + //Compare the accelarator widths. + if (icon != null && icon.getIconWidth() > maxIconValue) { + maxIconValue = icon.getIconWidth(); + p.putClientProperty(UIBasicMenuItemUI.MAX_ICON_WIDTH, new Integer(maxIconValue)); + } + + //Add on the widest accelerator + // If-clause added in 1.3.03 + if (maxAccValue > 0) { + r.width += maxAccValue; + r.width += defaultTextIconGap; + } + } + } + + private void caulateFont(JMenuItem b, Icon icon, String text, String acceleratorText) { + Font font = b.getFont(); + FontMetrics fm = b.getFontMetrics(font); + FontMetrics fmAccel = b.getFontMetrics(acceleratorFont); + + resetRects(); + + layoutMenuItem(fm, text, fmAccel, acceleratorText, icon, checkIcon, arrowIcon, + b.getVerticalAlignment(), b.getHorizontalAlignment(), b.getVerticalTextPosition(), + b.getHorizontalTextPosition(), viewRect, iconRect, textRect, acceleratorRect, + checkIconRect, arrowIconRect, text == null ? 0 : defaultTextIconGap, DEFAULT_ICON_GAP); + // find the union of the icon and text rects + r.setBounds(textRect); + r = SwingUtilities.computeUnion(iconRect.x, iconRect.y, iconRect.width, iconRect.height, r); + + // Added in 1.3.03 for compensation + if (icon != null || checkIcon != null) { + r.width -= 3 * UIBasicMenuItemUI.DEFAULT_TEXT_ICON_GAP; + } + } + + protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, int defaultTextIconGap) { + JMenuItem b = (JMenuItem) c; + ButtonModel model = b.getModel(); + JComponent p = (JComponent) b.getParent(); + Integer maxValueInt = (Integer) p.getClientProperty(UIBasicMenuItemUI.MAX_ICON_WIDTH); + int maxValue = maxValueInt == null ? 16 : maxValueInt.intValue(); + int menuWidth = b.getWidth(); + int menuHeight = b.getHeight(); + Insets i = c.getInsets(); + resetRects(); + viewRect.setBounds(0, 0, menuWidth, menuHeight); + viewRect.x += 0; + viewRect.y += i.top; + viewRect.width -= (i.right + viewRect.x); + viewRect.height -= (i.bottom + viewRect.y); + Font holdf = g.getFont(); + Font f = c.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + FontMetrics fmAccel = g.getFontMetrics(acceleratorFont); + int offset = 0; + // layout the text and icon + Icon ic = b.getIcon(); + Icon iCheck = checkIcon; + Icon paintIcon = ic; + // get Accelerator text + KeyStroke accelerator = b.getAccelerator(); + String acceleratorText = ""; + drawMenu(acceleratorText, accelerator, c, ic, maxValue, offset, paintIcon, b); + String text = layoutMenuItem(fm, b.getText(), fmAccel, acceleratorText, ic, null, + arrowIcon, b.getVerticalAlignment(), b.getHorizontalAlignment(), + b.getVerticalTextPosition(), b.getHorizontalTextPosition(), viewRect, + iconRect, textRect, acceleratorRect, checkIconRect, arrowIconRect, + b.getText() == null ? 0 : defaultTextIconGap, DEFAULT_ICON_GAP); + // Paint background + paintBackground(g, b, background); + Color holdc = g.getColor(); + paintCheck(g, c, model, offset, foreground, holdc); + paintIcon(b, g, c, paintIcon, model, offset); + paintText(text, b, g, c); + drawAccText(acceleratorText, g, p, model, fmAccel, c); + paintArrow(g, model, c, foreground); + g.setColor(holdc); + g.setFont(holdf); + } + + private void drawMenu(String acceleratorText, KeyStroke accelerator, JComponent c, + Icon ic, int maxValue, int offset, Icon paintIcon, JMenuItem b) { + if (accelerator != null) { + int modifiers = accelerator.getModifiers(); + if (modifiers > 0) { + acceleratorText = KeyEvent.getKeyModifiersText(modifiers); + //acceleratorText += "-"; + acceleratorText += acceleratorDelimiter; + } + + int keyCode = accelerator.getKeyCode(); + if (keyCode != 0) { + acceleratorText += KeyEvent.getKeyText(keyCode); + } else { + acceleratorText += accelerator.getKeyChar(); + } + } + if (!isTopLevelMenu()) { + if (c instanceof JCheckBoxMenuItem || c instanceof JRadioButtonMenuItem) { + ic = checkIcon; + if (checkIcon.getIconWidth() < maxValue) { + ic = new EmptyIcon(maxValue, checkIcon.getIconHeight()); + offset = (maxValue - checkIcon.getIconWidth()) / 2; + } + paintIcon = null; + } else if (c instanceof JMenuItem) { + if (ic == null || ic.getIconWidth() < maxValue) { + int height = (ic == null) ? 2 : b.getIcon().getIconHeight(); + int width = (ic == null) ? 2 : b.getIcon().getIconWidth(); + offset = (maxValue - width) / 2; + ic = new EmptyIcon(maxValue, height); + } + } + } + } + + + private void drawAccText(String acceleratorText, Graphics g, JComponent p, ButtonModel model, FontMetrics fmAccel, JComponent c) { + if (acceleratorText != null && !ComparatorUtils.equals(acceleratorText, "")) { + //Get the maxAccWidth from the parent to calculate the offset. + int accOffset = 0; + Container parent = menuItem.getParent(); + if (parent != null && parent instanceof JComponent) { + Integer amaxValueInt = (Integer) p.getClientProperty(UIBasicMenuItemUI.MAX_ACC_WIDTH); + int amaxValue = amaxValueInt != null ? amaxValueInt.intValue() : acceleratorRect.width; + + //Calculate the offset, with which the accelerator texts will be drawn with. + accOffset = amaxValue - acceleratorRect.width; + } + + g.setFont(acceleratorFont); + if (!model.isEnabled()) { + g.setColor(ThemeUtils.MENU_ICON_SHADOW_COLOR); + BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x - accOffset, acceleratorRect.y + fmAccel.getAscent()); + g.setColor(ThemeUtils.MENU_ICON_DISABLED_COLOR); + BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x - accOffset - 1, acceleratorRect.y + fmAccel.getAscent() - 1); + //} + } else { + boolean isMenuSelected = c instanceof JMenu && model.isSelected(); + if (model.isArmed() || isMenuSelected) { + //g.setColor(acceleratorSelectionForeground); + g.setColor(ThemeUtils.MENU_SELECTED_TEXT_COLOR); + } else { + g.setColor(ThemeUtils.MENU_ITEM_FONT_COLOR); + } + + BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x - accOffset, acceleratorRect.y + fmAccel.getAscent()); + } + } + } + + private void paintArrow(Graphics g, ButtonModel model, JComponent c, Color foreground) { + if (arrowIcon != null) { + boolean isMenuSelected = c instanceof JMenu && model.isSelected(); + if (model.isArmed() || isMenuSelected) { + g.setColor(foreground); + } + if (!isTopLevelMenu()) { + arrowIcon.paintIcon(c, g, arrowIconRect.x, arrowIconRect.y); + } + } + } + + private void paintText(String text, JMenuItem b, Graphics g, JComponent c) { + if (text != null) { + View v = (View) c.getClientProperty(BasicHTML.propertyKey); + g.setColor(ThemeUtils.MENU_ITEM_FONT_COLOR); + + if (v != null) { + v.paint(g, textRect); + } else { + paintText(g, b, textRect, text); + } + } + } + + private void paintIcon(JMenuItem b, Graphics g, JComponent c, Icon paintIcon, ButtonModel model, int offset) { + if (paintIcon != null) { + Icon icon; + if (!model.isEnabled()) { + icon = (Icon) b.getDisabledIcon(); + if (icon != null) { + icon.paintIcon(c, g, iconRect.x + offset, iconRect.y); + } + } else if (model.isPressed() && model.isArmed()) { + icon = (Icon) b.getPressedIcon(); + if (icon == null) { + // Use default icon + icon = (Icon) b.getIcon(); + } + if (icon != null) { + icon.paintIcon(c, g, iconRect.x + offset, iconRect.y); + } + } else if (model.isArmed() || model.isSelected()) { + icon = (Icon) b.getIcon(); + if (icon != null) { + icon.paintIcon(c, g, iconRect.x + offset, iconRect.y); + } + } else { + icon = (Icon) b.getIcon(); + if (icon != null) { + icon.paintIcon(c, g, iconRect.x + offset, iconRect.y); + } + } + + } + } + + private void paintCheck(Graphics g, JComponent c, ButtonModel model, int offset, Color foreground, Color holdc) { + if (checkIcon != null) { + boolean isMenuSelected = c instanceof JMenu && model.isSelected(); + if (model.isArmed() || isMenuSelected) { + g.setColor(foreground); + } else { + g.setColor(holdc); + } + if (!isTopLevelMenu()) { + checkIcon.paintIcon(c, g, iconRect.x + offset, iconRect.y); + } + g.setColor(holdc); + } + + } + + /** + * Draws the background of one menu item. + * + * @param g the paint graphics + * @param menuItem menu item to be painted + * @param bgColor unused + * @since 1.4 + */ + protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { + if (!menuItem.isOpaque()) { + return; + } + ButtonModel model = menuItem.getModel(); + Color oldColor = g.getColor(); + int menuWidth = menuItem.getWidth(); + int menuHeight = menuItem.getHeight(); + boolean armed = + (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())); + + if ((menuItem instanceof JMenu) && ((JMenu) menuItem).isTopLevelMenu()) { + // TopLevelMenu + if (model.isSelected()) { + g.setColor(ThemeUtils.MENU_BAR_COLOR); + g.fillRect(0, 0, menuWidth, menuHeight); + drawXpTopMenuBorder(g, 0, 0, menuWidth, menuHeight, true); + } else if (menuItem.getClientProperty("rollover") == Boolean.TRUE && ThemeUtils.MENU_ROLLOVER) { + g.setColor(ThemeUtils.MENU_ROLLOVER_BG_COLOR); + g.fillRect(0, 0, menuWidth - 8, menuHeight); + g.setColor(ThemeUtils.MENU_BAR_COLOR); + g.fillRect(menuWidth - 8, 0, 8, menuHeight); + drawXpTopMenuBorder(g, 0, 0, menuWidth, menuHeight, false); + } else { + if (menuItem.getBackground() instanceof ColorUIResource) { + g.setColor(ThemeUtils.MENU_BAR_COLOR); + } else { + g.setColor(menuItem.getBackground()); + } + + g.fillRect(0, 0, menuWidth, menuHeight); + } + } else if (armed) { + // Item rollover + g.setColor(ThemeUtils.MENU_ITEM_ROLLOVER_COLOR); + g.fillRect(0, 0, menuWidth, menuHeight); + } else { + // Item normal + if (menuItem.getBackground() instanceof ColorUIResource) { + g.setColor(ThemeUtils.MENU_POPUP_COLOR); + } else { + g.setColor(menuItem.getBackground()); + } + + g.fillRect(0, 0, menuWidth, menuHeight); + } + + g.setColor(oldColor); + } + + + private void drawXpTopMenuBorder( + Graphics g, int x, int y, int w, int h, boolean selected) { + g.setColor(ThemeUtils.MENU_BORDER_COLOR); + if (selected) { + g.drawLine(x, y, x + w - 8, y); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x + w - 8, y, x + w - 8, y + h - 1); + + // shadow + drawXpShadow(g, + ColorRoutines.darken(ThemeUtils.MENU_BORDER_COLOR, 15), + ThemeUtils.MENU_BAR_COLOR, + x + w - 7, y + 6, 6, h - 6); + } else { + g.drawRect(x, y, w - 8, h - 1); + } + } + + + private void drawXpShadow(Graphics g, Color c1, Color c2, + int x1, int y1, int w, int h) { + Color c; + for (int x = 0; x < w; x++) { + c = ColorRoutines.getGradient(c1, c2, w, x); + g.setColor(c); + g.drawLine(x1 + x, y1, x1 + x, y1 + h); + + int index = 0; + for (int y = y1 - 1; y >= y1 - 6; y--) { + g.setColor(ColorRoutines.getGradient(c, c2, 5, index++)); + g.drawLine(x1 + x, y, x1 + x, y); + } + } + } + + /** + * Compute and return the location of the icons origin, the + * location of origin of the text baseline, and a possibly clipped + * version of the compound labels string. Locations are computed + * relative to the viewRect rectangle. + */ + + private String layoutMenuItem(FontMetrics fm, String text, FontMetrics fmAccel, + String acceleratorText, Icon icon, Icon checkIcon, Icon arrowIcon, + int verticalAlignment, int horizontalAlignment, int verticalTextPosition, + int horizontalTextPosition, Rectangle viewRect, Rectangle iconRect, + Rectangle textRect, Rectangle acceleratorRect, Rectangle checkIconRect, + Rectangle arrowIconRect, int textIconGap, int menuItemGap) { + SwingUtilities.layoutCompoundLabel(menuItem, fm, text, icon, verticalAlignment, + horizontalAlignment, verticalTextPosition, horizontalTextPosition, viewRect, + iconRect, textRect, textIconGap); + if ((acceleratorText == null) ||ComparatorUtils.equals(acceleratorText,"")) { + acceleratorRect.width = acceleratorRect.height = 0; + acceleratorText = ""; + } else { + acceleratorRect.width = SwingUtilities.computeStringWidth(fmAccel, acceleratorText); + acceleratorRect.height = fmAccel.getHeight(); + } + if (!isTopLevelMenu()) { + if (checkIcon != null) { + checkIconRect.height = checkIcon.getIconHeight(); + checkIconRect.width = checkIcon.getIconWidth(); + } else { + checkIconRect.width = checkIconRect.height = 0; + } + if (arrowIcon != null) { + arrowIconRect.width = arrowIcon.getIconWidth(); + arrowIconRect.height = arrowIcon.getIconHeight(); + } else { + arrowIconRect.width = arrowIconRect.height = 0; + } + } else { + checkIconRect.width = checkIconRect.height = 0; + arrowIconRect.width = arrowIconRect.height = 0; + } + Rectangle labelRect = iconRect.union(textRect); + if (checkIcon != null) { + checkIconRect.x += menuItemGap; + } else { + textRect.x += menuItemGap; + iconRect.x += menuItemGap; + } + acceleratorRect.x = viewRect.x + viewRect.width - arrowIconRect.width - menuItemGap - acceleratorRect.width; + acceleratorRect.y = labelRect.y + (labelRect.height / 2) - (acceleratorRect.height / 2); + if (!isTopLevelMenu()) { + arrowIconRect.y = labelRect.y + (labelRect.height / 2) - (arrowIconRect.height / 2); + checkIconRect.y = labelRect.y + (labelRect.height / 2) - (checkIconRect.height / 2); + arrowIconRect.x = viewRect.x + viewRect.width - menuItemGap + - arrowIconRect.width; + } + return text; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIBasicMenuUI.java b/designer_base/src/com/fr/design/gui/imenu/UIBasicMenuUI.java new file mode 100644 index 0000000000..7fd4e1b30f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIBasicMenuUI.java @@ -0,0 +1,689 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.imenu; + + +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.ComboPopup; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-11 + * Time: 上午11:21 + */ +public class UIBasicMenuUI extends UIBasicMenuItemUI { + private static final boolean DEBUG = false; // show bad params, misc. + private static final int MENU_POSITION4 = 4; + private static final int MENU_POSITION3 = 3; + + protected ChangeListener changeListener; + protected PropertyChangeListener propertyChangeListener; + + private int lastMnemonic = 0; + private static boolean crossMenuMnemonic = true; + + /** + * 创建UI + * + * @param x 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent x) { + return new UIBasicMenuUI(); + } + + protected void installDefaults() { + super.installDefaults(); + ((JMenu) menuItem).setDelay(200); + crossMenuMnemonic = UIManager.getBoolean("Menu.crossMenuMnemonic"); + } + + /** + * The ActionMap for BasicMenUI can not be shared, this is subclassed + * to create a new one for each invocation. + */ + ActionMap getActionMap() { + return createActionMap(); + } + + /** + * Invoked to create the ActionMap. + */ + ActionMap createActionMap() { + ActionMap am = super.createActionMap(); + if (am != null) { + am.put("selectMenu", new PostAction((JMenu) menuItem, true)); + } + return am; + } + + protected String getPropertyPrefix() { + return "Menu"; + } + + protected void installListeners() { + super.installListeners(); + + if (changeListener == null) { + changeListener = createChangeListener(menuItem); + } + + if (changeListener != null) { + menuItem.addChangeListener(changeListener); + } + + if (propertyChangeListener == null) { + propertyChangeListener = createPropertyChangeListener(menuItem); + } + + if (propertyChangeListener != null) { + menuItem.addPropertyChangeListener(propertyChangeListener); + } + + } + + protected void installKeyboardActions() { + super.installKeyboardActions(); // installs only ActionMap + updateMnemonicBinding(); + } + + void updateMnemonicBinding() { + int mnemonic = menuItem.getModel().getMnemonic(); + int[] shortcutKeys = (int[]) UIManager.get("Menu.shortcutKeys"); + + if (mnemonic == lastMnemonic || shortcutKeys == null) { + return; + } + + if (lastMnemonic != 0 && windowInputMap != null) { + for (int i = 0; i < shortcutKeys.length; i++) { + windowInputMap.remove(KeyStroke.getKeyStroke(lastMnemonic, shortcutKeys[i], false)); + } + } + + if (mnemonic != 0) { + if (windowInputMap == null) { + windowInputMap = createInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, windowInputMap); + } + + for (int i = 0; i < shortcutKeys.length; i++) { + windowInputMap.put(KeyStroke.getKeyStroke(mnemonic, shortcutKeys[i], false), "selectMenu"); + } + } + + lastMnemonic = mnemonic; + } + + protected MouseInputListener createMouseInputListener(JComponent c) { + return new MouseInputHandler(); + } + + protected ChangeListener createChangeListener(JComponent c) { + return null; + } + + protected PropertyChangeListener createPropertyChangeListener(JComponent c) { + return new PropertyChangeHandler(); + } + + protected void uninstallDefaults() { + menuItem.setArmed(false); + menuItem.setSelected(false); + menuItem.resetKeyboardActions(); + super.uninstallDefaults(); + } + + protected void uninstallListeners() { + super.uninstallListeners(); + + if (changeListener != null) { + menuItem.removeChangeListener(changeListener); + changeListener = null; + } + + if (propertyChangeListener != null) { + menuItem.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + if (menuKeyListener != null) { + menuItem.removeMenuKeyListener(menuKeyListener); + menuKeyListener = null; + } + } + + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) { + return new MenuDragMouseHandler(); + } + + protected MenuKeyListener createMenuKeyListener(JComponent c) { + return new MenuKeyHandler(); + } + + + public Dimension getMaximumSize(JComponent c) { + if (((JMenu) menuItem).isTopLevelMenu() == true) { + Dimension d = c.getPreferredSize(); + return new Dimension(d.width, Short.MAX_VALUE); + } + return null; + } + + protected void setupPostTimer(JMenu menu) { + Timer timer = new Timer(menu.getDelay(), new PostAction(menu, false)); + timer.setRepeats(false); + timer.start(); + } + + private static void appendPath(MenuElement[] path, MenuElement elem) { + MenuElement[] newPath = new MenuElement[path.length + 1]; + System.arraycopy(path, 0, newPath, 0, path.length); + newPath[path.length] = elem; + MenuSelectionManager.defaultManager().setSelectedPath(newPath); + } + + private static class PostAction extends AbstractAction { + JMenu menu; + boolean force = false; + + PostAction(JMenu menu, boolean shouldForce) { + this.menu = menu; + this.force = shouldForce; + } + + public void actionPerformed(ActionEvent e) { + if (!crossMenuMnemonic) { + JPopupMenu pm = getActivePopupMenu(); + + if (pm != null && pm != menu.getParent()) { + return; + } + } + + final MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager(); + if (force) { + Container cnt = menu.getParent(); + if (cnt != null && cnt instanceof JMenuBar) { + MenuElement[] me; + MenuElement[] subElements; + + subElements = menu.getPopupMenu().getSubElements(); + if (subElements.length > 0) { + me = new MenuElement[MENU_POSITION4]; + me[0] = (MenuElement) cnt; + me[1] = (MenuElement) menu; + me[2] = (MenuElement) menu.getPopupMenu(); + me[3] = subElements[0]; + } else { + me = new MenuElement[MENU_POSITION3]; + me[0] = (MenuElement) cnt; + me[1] = menu; + me[2] = (MenuElement) menu.getPopupMenu(); + } + defaultManager.setSelectedPath(me); + } + } else { + MenuElement[] path = defaultManager.getSelectedPath(); + if (path.length > 0 && path[path.length - 1] == menu) { + appendPath(path, menu.getPopupMenu()); + } + } + } + + public boolean isEnabled() { + return menu.getModel().isEnabled(); + } + } + + private class PropertyChangeHandler implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent e) { + if (ComparatorUtils.equals(e.getPropertyName(), AbstractButton.MNEMONIC_CHANGED_PROPERTY)) { + updateMnemonicBinding(); + } + } + } + + /** + * Instantiated and used by a menu item to handle the current menu selection + * from mouse events. A MouseInputHandler processes and forwards all mouse events + * to a shared instance of the MenuSelectionManager. + *

+ * This class is protected so that it can be subclassed by other look and + * feels to implement their own mouse handling behavior. All overridden + * methods should call the parent methods so that the menu selection + * is correct. + * + * @see javax.swing.MenuSelectionManager + * @since 1.4 + */ + protected class MouseInputHandler implements MouseInputListener { + public void mouseClicked(MouseEvent e) { + } + + /** + * Invoked when the mouse has been clicked on the menu. This + * method clears or sets the selection path of the + * MenuSelectionManager. + * + * @param e the mouse event + */ + public void mousePressed(MouseEvent e) { + JMenu menu = (JMenu) menuItem; + if (!menu.isEnabled()) { + return; + } + + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + if (menu.isTopLevelMenu()) { + if (menu.isSelected()) { + manager.clearSelectedPath(); + } else { + Container cnt = menu.getParent(); + if (cnt != null && cnt instanceof JMenuBar) { + MenuElement[] me = new MenuElement[2]; + me[0] = (MenuElement) cnt; + me[1] = menu; + manager.setSelectedPath(me); + } + } + } + + MenuElement[] selectedPath = manager.getSelectedPath(); + if (selectedPath.length > 0 && selectedPath[selectedPath.length - 1] != menu.getPopupMenu()) { + + if (menu.isTopLevelMenu() || menu.getDelay() == 0) { + appendPath(selectedPath, menu.getPopupMenu()); + } else { + setupPostTimer(menu); + } + } + } + + /** + * Invoked when the mouse has been released on the menu. Delegates the + * mouse event to the MenuSelectionManager. + * + * @param e the mouse event + */ + public void mouseReleased(MouseEvent e) { + JMenu menu = (JMenu) menuItem; + if (!menu.isEnabled()) { + return; + } + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + if (!e.isConsumed()) { + manager.clearSelectedPath(); + } + } + + /** + * Invoked when the cursor enters the menu. This method sets the selected + * path for the MenuSelectionManager and handles the case + * in which a menu item is used to pop up an additional menu, as in a + * hierarchical menu system. + * + * @param e the mouse event; not used + */ + public void mouseEntered(MouseEvent e) { + JMenu menu = (JMenu) menuItem; + + if (!menu.isEnabled() || menu.getClientProperty("isSystemMenu") == Boolean.TRUE) { + return; + } + + menu.putClientProperty("rollover", Boolean.TRUE); + + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + MenuElement[] selectedPath = manager.getSelectedPath(); + + if (!menu.isTopLevelMenu()) { + if (!(selectedPath.length > 0 && selectedPath[selectedPath.length - 1] == menu.getPopupMenu())) { + if (menu.getDelay() == 0) { + appendPath(getPath(), menu.getPopupMenu()); + } else { + manager.setSelectedPath(getPath()); + setupPostTimer(menu); + } + } + } else { + if (selectedPath.length > 0 && selectedPath[0] == menu.getParent()) { + MenuElement[] newPath = new MenuElement[3]; + // A top level menu's parent is by definition + // a JMenuBar + newPath[0] = (MenuElement) menu.getParent(); + newPath[1] = menu; + newPath[2] = menu.getPopupMenu(); + manager.setSelectedPath(newPath); + } + } + + if (menu.isTopLevelMenu()) { + menu.repaint(); + } + } + + public void mouseExited(MouseEvent e) { + JMenu menu = (JMenu) menuItem; + + if (!menu.isEnabled() || menu.getClientProperty("isSystemMenu") == Boolean.TRUE) { + return; + } + + menu.putClientProperty("rollover", Boolean.FALSE); + + if (menu.isTopLevelMenu()) { + menu.repaint(); + } + } + + /** + * Invoked when a mouse button is pressed on the menu and then dragged. + * Delegates the mouse event to the MenuSelectionManager. + * + * @param e the mouse event + * @see java.awt.event.MouseMotionListener#mouseDragged + */ + public void mouseDragged(MouseEvent e) { + JMenu menu = (JMenu) menuItem; + if (!menu.isEnabled()) { + return; + } + MenuSelectionManager.defaultManager().processMouseEvent(e); + } + + public void mouseMoved(MouseEvent e) { + } + } + + private class MenuDragMouseHandler implements MenuDragMouseListener { + public void menuDragMouseEntered(MenuDragMouseEvent e) { + } + + public void menuDragMouseDragged(MenuDragMouseEvent e) { + if (menuItem.isEnabled() == false) { + return; + } + + MenuSelectionManager manager = e.getMenuSelectionManager(); + MenuElement[] path = e.getPath(); + + Point p = e.getPoint(); + boolean isContainsX = p.x >= 0 && p.x < menuItem.getWidth(); + boolean isContainsY = p.y >= 0 && p.y < menuItem.getHeight(); + if (isContainsX && isContainsY) { + JMenu menu = (JMenu) menuItem; + MenuElement[] selectedPath = manager.getSelectedPath(); + if (!(selectedPath.length > 0 && selectedPath[selectedPath.length - 1] == menu.getPopupMenu())) { + boolean isMenuTop = menu.isTopLevelMenu() || menu.getDelay() == 0; + if (isMenuTop || e.getID() == MouseEvent.MOUSE_DRAGGED) { + appendPath(path, menu.getPopupMenu()); + } else { + manager.setSelectedPath(path); + setupPostTimer(menu); + } + } + } else if (e.getID() == MouseEvent.MOUSE_RELEASED) { + Component comp = manager.componentForPoint(e.getComponent(), e.getPoint()); + if (comp == null) { + manager.clearSelectedPath(); + } + } + + } + + public void menuDragMouseExited(MenuDragMouseEvent e) { + } + + public void menuDragMouseReleased(MenuDragMouseEvent e) { + } + } + + static JPopupMenu getActivePopupMenu() { + MenuElement[] path = MenuSelectionManager.defaultManager().getSelectedPath(); + for (int i = path.length - 1; i >= 0; i--) { + MenuElement elem = path[i]; + if (elem instanceof JPopupMenu) { + return (JPopupMenu) elem; + } + } + return null; + } + + // Currently not installed (1.3.6) + private static class MenuHandler implements MenuListener { + public void menuSelected(MenuEvent e) { + } + + public void menuDeselected(MenuEvent e) { + } + + public void menuCanceled(MenuEvent e) { + JMenu m = (JMenu) e.getSource(); + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + + if (manager.isComponentPartOfCurrentMenu(m)) { + MenuSelectionManager.defaultManager().clearSelectedPath(); + } + } + } + + /** + * Handles the mnemonic handling for the JMenu and JMenuItems. + */ + private class MenuKeyHandler implements MenuKeyListener { + + // fields for handling duplicate mnemonics. + private int indexes[]; + private char lastMnemonic; + private int lastIndex; + private int matches; + + /** + * Opens the SubMenu + */ + public void menuKeyTyped(MenuKeyEvent e) { + if (menuItem == null){ + return; + } + + if (DEBUG) { + FRLogger.getLogger().info("in TinyMenuUI.menuKeyTyped for " + menuItem.getText()); + } + + if (!crossMenuMnemonic) { + JPopupMenu pm = getActivePopupMenu(); + + if (pm != null && pm != menuItem.getParent()) { + return; + } + } + + int key = menuItem.getMnemonic(); + if (key == 0) { + return; + } + MenuElement[] path = e.getPath(); + if (lower((char) key) == lower(e.getKeyChar())) { + JPopupMenu popupMenu = ((JMenu) menuItem).getPopupMenu(); + MenuElement[] sub = popupMenu.getSubElements(); + if (sub.length > 0) { + MenuSelectionManager manager = e.getMenuSelectionManager(); + MenuElement[] newPath = new MenuElement[path.length + 2]; + System.arraycopy(path, 0, newPath, 0, path.length); + newPath[path.length] = popupMenu; + newPath[path.length + 1] = sub[0]; + manager.setSelectedPath(newPath); + } + e.consume(); + } + } + + /** + * Handles the mnemonics for the menu items. Will also handle duplicate mnemonics. + * Perhaps this should be moved into BasicPopupMenuUI. See 4670831 + */ + public void menuKeyPressed(MenuKeyEvent e) { + if (menuItem == null) { + return; + } + if (DEBUG) { + FRLogger.getLogger().info("in TinyMenuUI.menuKeyPressed for " + menuItem.getText()); + } + char keyChar = e.getKeyChar(); + if (!Character.isLetterOrDigit(keyChar)){ + return; } + MenuSelectionManager manager = e.getMenuSelectionManager(); + MenuElement[] path = e.getPath(); MenuElement[] selectedPath = manager.getSelectedPath(); + for (int i = selectedPath.length - 1; i >= 0; i--) { + if (selectedPath[i] == menuItem) { + JPopupMenu popupMenu = ((JMenu) menuItem).getPopupMenu(); + MenuElement[] items = popupMenu.getSubElements(); + if (indexes == null || lastMnemonic != keyChar) { + matches = 0; + lastIndex = 0; + indexes = new int[items.length]; + for (int j = 0; j < items.length; j++) { + int key = ((JMenuItem) items[j]).getMnemonic(); + if (lower((char) key) == lower(keyChar)) { + indexes[matches++] = j; + } + } + lastMnemonic = keyChar; + } + if (matches == 0) { + ; + } else if (matches == 1) { + JMenuItem item = (JMenuItem) items[indexes[0]]; + if (!(item instanceof JMenu)) { + manager.clearSelectedPath(); + item.doClick(); + } + } else { + if (lastIndex == matches) { + lastIndex = 0; + } + MenuElement menuItem = items[indexes[lastIndex++]]; + MenuElement[] newPath = new MenuElement[path.length + 2]; + System.arraycopy(path, 0, newPath, 0, path.length); + newPath[path.length] = popupMenu; + newPath[path.length + 1] = menuItem; + manager.setSelectedPath(newPath); + } + e.consume(); return; + } + } + } + + public void menuKeyReleased(MenuKeyEvent e) { + } + + private char lower(char keyChar) { + return Character.toLowerCase(keyChar); + } + } + + static class AltProcessor implements KeyEventPostProcessor { + static boolean altKeyPressed = false; + static boolean menuCanceledOnPress = false; + static JRootPane root = null; + static Window winAncestor = null; + + void altPressed(KeyEvent ev) { + MenuSelectionManager msm = + MenuSelectionManager.defaultManager(); + MenuElement[] path = msm.getSelectedPath(); + + if (path.length > 0 && !(path[0] instanceof ComboPopup)) { + msm.clearSelectedPath(); + menuCanceledOnPress = true; + ev.consume(); + } else if (path.length > 0) { // We are in ComboBox + menuCanceledOnPress = false; + ev.consume(); + } else { + menuCanceledOnPress = false; + JMenuBar mbar = root != null ? root.getJMenuBar() : null; + + if (mbar == null && winAncestor instanceof JFrame) { + mbar = ((JFrame) winAncestor).getJMenuBar(); + } + + JMenu menu = mbar != null ? mbar.getMenu(0) : null; + + if (menu != null) { + ev.consume(); + } + } + } + + void altReleased(KeyEvent ev) { + if (menuCanceledOnPress) { + return; + } + + MenuSelectionManager msm = MenuSelectionManager.defaultManager(); + + if (msm.getSelectedPath().length == 0) { + // if no menu is active, we try activating the menubar + JMenuBar mbar = root != null ? root.getJMenuBar() : null; + + if (mbar == null && winAncestor instanceof JFrame) { + mbar = ((JFrame) winAncestor).getJMenuBar(); + } + + JMenu menu = mbar != null ? mbar.getMenu(0) : null; + + if (menu != null) { + MenuElement[] path = new MenuElement[2]; + path[0] = mbar; + path[1] = menu; + msm.setSelectedPath(path); + } + } + } + + public boolean postProcessKeyEvent(KeyEvent ev) { + if (ev.getKeyCode() == KeyEvent.VK_ALT) { + root = SwingUtilities.getRootPane(ev.getComponent()); + winAncestor = SwingUtilities.getWindowAncestor(root); + + if (ev.getID() == KeyEvent.KEY_PRESSED) { + if (!altKeyPressed) { + altPressed(ev); + } + + altKeyPressed = true; + return true; + } else if (ev.getID() == KeyEvent.KEY_RELEASED) { + if (altKeyPressed) { + altReleased(ev); + } + + altKeyPressed = false; + } + } else { + altKeyPressed = false; + } + + return false; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UICheckBoxMenuItem.java b/designer_base/src/com/fr/design/gui/imenu/UICheckBoxMenuItem.java new file mode 100644 index 0000000000..0d36b0d6af --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UICheckBoxMenuItem.java @@ -0,0 +1,29 @@ +package com.fr.design.gui.imenu; + +import com.fr.design.constants.UIConstants; + +public class UICheckBoxMenuItem extends UIMenuItem { + + public UICheckBoxMenuItem(String name) { + super(name); + } + + + public void setState(boolean b) { + synchronized (this) { + setSelected(b); + } + } + + @Override + public void setSelected(boolean b) { + super.setSelected(b); + if (this.isSelected()) { + setIcon(UIConstants.CHOOSEN_ICON); + } else { + setIcon(UIConstants.BLACK_ICON); + } + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIListPopup.java b/designer_base/src/com/fr/design/gui/imenu/UIListPopup.java new file mode 100644 index 0000000000..24298ab5a5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIListPopup.java @@ -0,0 +1,183 @@ +package com.fr.design.gui.imenu; + +import java.awt.BorderLayout; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Enumeration; + +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.MouseInputListener; + +public class UIListPopup extends JPopupMenu implements MouseInputListener { + + private JList list; + private JScrollPane pane; + private ArrayList listeners = new ArrayList(); + + public void addListSelectionListener(ListSelectionListener l) { + if (!listeners.contains(l)) + listeners.add(l); + } + + public void setSelectedIndex(int index) { + if (index >= list.getModel().getSize()) + index = 0; + if (index < 0) + index = list.getModel().getSize() - 1; + list.ensureIndexIsVisible(index); + list.setSelectedIndex(index); + } + + public Object getSelectedValue() { + return list.getSelectedValue(); + } + + public int getSelectedIndex() { + return list.getSelectedIndex(); + } + + public boolean isSelected() { + return list.getSelectedIndex() != -1; + } + + public void setLastOneSelected() { + int count = list.getModel().getSize(); + if (count > 0) { + list.ensureIndexIsVisible(count - 1); + list.setSelectedIndex(count - 1); + } + } + + public void removeListSelectionListener(ListSelectionListener l) { + if (listeners.contains(l)) + listeners.remove(l); + } + + private void fireValueChanged(ListSelectionEvent e) { + for (ListSelectionListener l : listeners) { + l.valueChanged(e); + } + } + + public UIListPopup() { + setLayout(new BorderLayout()); + list = new JList(); + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.addMouseListener(this); + list.addMouseMotionListener(this); + list.setModel(new DefaultListModel()); + pane = new JScrollPane(list); + pane.setBorder(null); + add(pane, BorderLayout.CENTER); + } + + public int getItemCount() { + DefaultListModel model = (DefaultListModel) list.getModel(); + return model.getSize(); + } + + public Object getItem(int index) { + DefaultListModel model = (DefaultListModel) list.getModel(); + return model.get(index); + } + + public void addItem(Object o) { + DefaultListModel model = (DefaultListModel) list.getModel(); + model.addElement(o); + list.repaint(); + } + + public void removeItem(Object o) { + DefaultListModel model = (DefaultListModel) list.getModel(); + model.removeElement(o); + list.repaint(); + } + + public void setList(Iterable iterable) { + DefaultListModel model = new DefaultListModel(); + for (Object o : iterable) { + model.addElement(o); + } + list.setModel(model); + list.repaint(); + } + + public void setList(Enumeration e) { + DefaultListModel model = new DefaultListModel(); + while (e.hasMoreElements()) { + model.addElement(e.nextElement()); + } + list.setModel(model); + list.repaint(); + } + + public void setList(Object... objects) { + DefaultListModel model = new DefaultListModel(); + for (Object o : objects) { + model.addElement(o); + } + list.setModel(model); + list.repaint(); + } + + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + if (list.getSelectedIndex() != -1) + fireValueChanged(new ListSelectionEvent(list, list.getSelectedIndex(), list.getSelectedIndex(), true)); + } + + public void mouseReleased(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseMoved(MouseEvent anEvent) { + if (anEvent.getSource() == list) { + Point location = anEvent.getPoint(); + Rectangle r = new Rectangle(); + list.computeVisibleRect(r); + if (r.contains(location)) { + updateListBoxSelectionForEvent(anEvent, false); + } + } + } + + protected void updateListBoxSelectionForEvent(MouseEvent anEvent, boolean shouldScroll) { + + Point location = anEvent.getPoint(); + if (list == null) { + return; + } + int index = list.locationToIndex(location); + if (index == -1) { + if (location.y < 0) { + index = 0; + } else { + index = list.getModel().getSize() - 1; + } + } + if (list.getSelectedIndex() != index) { + list.setSelectedIndex(index); + if (shouldScroll) { + list.ensureIndexIsVisible(index); + } + } + } + + public void mouseDragged(MouseEvent e) { + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIMenu.java b/designer_base/src/com/fr/design/gui/imenu/UIMenu.java new file mode 100644 index 0000000000..ecce5059c0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIMenu.java @@ -0,0 +1,57 @@ +package com.fr.design.gui.imenu; + +import com.fr.design.constants.UIConstants; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.border.Border; +import java.awt.*; + +public class UIMenu extends JMenu { + public UIMenu(String name) { + super(name); + setName(name); + setRolloverEnabled(true); + setBackground(UIConstants.NORMAL_BACKGROUND); + } + + @Override + public String getText() { + if (this.getParent() instanceof JPopupMenu) { + return StringUtils.BLANK + super.getText(); + } + return " " + super.getText(); + } + + public JPopupMenu getPopupMenu() { + JPopupMenu popupMenu = super.getPopupMenu(); + popupMenu.setBorder(new Border() { + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + g.setColor(UIConstants.LINE_COLOR); + g.drawRect(x, y, width - 1, height - 1); + if (!(UIMenu.this.getParent() instanceof JPopupMenu)) { + g.setColor(UIConstants.NORMAL_BACKGROUND); + g.drawLine(1, 0, UIMenu.this.getWidth() - 2, 0); + } + } + + @Override + public boolean isBorderOpaque() { + return false; + } + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(5, 2, 10, 10); + } + }); + return popupMenu; + } + + @Override + public void updateUI() { + setUI(new UIMenuUI()); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIMenuBar.java b/designer_base/src/com/fr/design/gui/imenu/UIMenuBar.java new file mode 100644 index 0000000000..154479c233 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIMenuBar.java @@ -0,0 +1,29 @@ +package com.fr.design.gui.imenu; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-30 + * Time: 上午10:30 + */ +public class UIMenuBar extends JMenuBar { + + private static final int LEFT_GAP = 5; + + public UIMenuBar() { + super(); + this.setBorder(new EmptyBorder(0, LEFT_GAP, 0, 0)); + + } + + /** + * 更新UI + */ + public void updateUI() { + setUI(new UIMenuBarUI()); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIMenuBarUI.java b/designer_base/src/com/fr/design/gui/imenu/UIMenuBarUI.java new file mode 100644 index 0000000000..015d1c3e10 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIMenuBarUI.java @@ -0,0 +1,33 @@ +package com.fr.design.gui.imenu; + +import com.fr.design.constants.UIConstants; + +import javax.swing.plaf.basic.BasicMenuBarUI; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-30 + * Time: 上午10:36 + */ +public class UIMenuBarUI extends BasicMenuBarUI { + + public UIMenuBarUI() { + } + + public void paint(java.awt.Graphics g, javax.swing.JComponent c) { + //是否完全不透明 + super.paint(g, c); + if (!c.isOpaque()) { + return; + } + Color oldColor = g.getColor(); + g.setColor(UIConstants.NORMAL_BACKGROUND); + g.fillRect(0, 0, c.getWidth(), c.getHeight()); + g.setColor(oldColor); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIMenuHighLight.java b/designer_base/src/com/fr/design/gui/imenu/UIMenuHighLight.java new file mode 100644 index 0000000000..ac29a729dc --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIMenuHighLight.java @@ -0,0 +1,25 @@ +package com.fr.design.gui.imenu; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JPanel; + +import com.fr.design.constants.UIConstants; + +public class UIMenuHighLight extends JPanel{ + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = 2; + return dim; + } + public void paint(Graphics g) { + g.setColor(UIConstants.LINE_COLOR); + g.drawLine(0, 0, getWidth(), 0); + g.setColor(Color.WHITE); + g.drawLine(0, 1, getWidth(), 1); + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIMenuItem.java b/designer_base/src/com/fr/design/gui/imenu/UIMenuItem.java new file mode 100644 index 0000000000..e5370d3223 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIMenuItem.java @@ -0,0 +1,107 @@ +package com.fr.design.gui.imenu; + +import java.awt.*; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicMenuItemUI; + +import com.fr.design.constants.UIConstants; +import com.fr.stable.Constants; +import com.fr.stable.StringUtils; +import com.fr.design.utils.gui.GUIPaintUtils; +import sun.swing.SwingUtilities2; + +public class UIMenuItem extends JMenuItem{ + public UIMenuItem() { + this(StringUtils.BLANK); + } + + public UIMenuItem(String string) { + this(string, null); + + } + + public UIMenuItem(String string, Icon pageSmallIcon) { + super(string, pageSmallIcon); + setBackground(UIConstants.NORMAL_BACKGROUND); + setUI(new UIMenuItemUI()); + } + + public UIMenuItem(String string, int key) { + super(string, key); + setBackground(UIConstants.NORMAL_BACKGROUND); + setUI(new UIMenuItemUI()); + } + + public UIMenuItem(Action action) { + this(); + setAction(action); + } + + @Override + public String getText() { + return StringUtils.BLANK + super.getText(); + } + + private class UIMenuItemUI extends BasicMenuItemUI { + @Override + protected void paintBackground(Graphics g, JMenuItem menuItem,Color bgColor) { + if(menuItem.getIcon() == null) { + super.paintBackground(g, menuItem, bgColor); + return; + } + ButtonModel model = menuItem.getModel(); + Color oldColor = g.getColor(); + int menuWidth = menuItem.getWidth(); + int menuHeight = menuItem.getHeight(); + + g.setColor(UIConstants.NORMAL_BACKGROUND); + g.fillRect(0, 0, menuWidth, menuHeight); + if(menuItem.isOpaque()) { + if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) { + GUIPaintUtils.fillPaint((Graphics2D)g, 30, 0, menuWidth - 30, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, 7); + } else { + GUIPaintUtils.fillPaint((Graphics2D)g, 30, 0, menuWidth - 30, menuHeight, true, Constants.NULL, menuItem.getBackground(), 7); + } + g.setColor(oldColor); + } + else if (model.isArmed() || (menuItem instanceof JMenu && + model.isSelected())) { + GUIPaintUtils.fillPaint((Graphics2D)g, 30, 0, menuWidth - 30, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, 7); + g.setColor(oldColor); + } + } + + protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { + ButtonModel model = menuItem.getModel(); + FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g); + int mnemIndex = menuItem.getDisplayedMnemonicIndex(); + + if(!model.isEnabled()) { + // *** paint the text disabled + if ( UIManager.get("MenuItem.disabledForeground") instanceof Color ) { + g.setColor( UIManager.getColor("MenuItem.disabledForeground") ); + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text, + -1, textRect.x, textRect.y + fm.getAscent()); + } else { + g.setColor(menuItem.getBackground().brighter()); + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text, + -1, textRect.x, textRect.y + fm.getAscent()); + g.setColor(menuItem.getBackground().darker()); + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text, + -1, textRect.x - 1, textRect.y + + fm.getAscent() - 1); + } + } else { + // *** paint the text normally + if (model.isArmed()|| (menuItem instanceof JMenu && model.isSelected())) { + g.setColor(selectionForeground); // Uses protected field. + } + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g,text, + -1, textRect.x, textRect.y + fm.getAscent()); + } + } + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIMenuUI.java b/designer_base/src/com/fr/design/gui/imenu/UIMenuUI.java new file mode 100644 index 0000000000..e4b56da28d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIMenuUI.java @@ -0,0 +1,83 @@ +package com.fr.design.gui.imenu; + +import com.fr.design.constants.UIConstants; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUIPaintUtils; +import sun.swing.SwingUtilities2; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicMenuUI; +import java.awt.*; + +public class UIMenuUI extends BasicMenuUI { + @Override + protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { + super.paintBackground(g, menuItem, bgColor); + ButtonModel model = menuItem.getModel(); + Color oldColor = g.getColor(); + int menuWidth = menuItem.getWidth(); + int menuHeight = menuItem.getHeight(); + if (menuItem.isOpaque()) { + if (menuItem.getParent() instanceof JPopupMenu && model.isSelected()) { + g.setColor(UIConstants.NORMAL_BACKGROUND); + g.fillRect(0, 0, menuWidth, menuHeight); + GUIPaintUtils.fillPaint((Graphics2D) g, 30, 0, menuWidth - 30, menuHeight, true, Constants.NULL, UIConstants.FLESH_BLUE, 7); + } else if (model.isSelected()) { + paintPressed(g, menuWidth, menuHeight); + } else { + paintRollOver(g, menuWidth, menuHeight); + } + g.setColor(oldColor); + } else if (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) { + g.setColor(bgColor); + g.fillRect(0, 0, menuWidth, menuHeight); + g.setColor(oldColor); + } + } + + protected void paintPressed(Graphics g, int w, int h) { + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(UIConstants.NORMAL_BACKGROUND); + g2d.fillRect(0, 0, w, h); + g2d.setColor(UIConstants.LINE_COLOR); + g2d.drawLine(0, 0, 0, h - 1); + g2d.drawLine(w - 1, 0, w - 1, h - 1); + } + + protected void paintRollOver(Graphics g, int w, int h) { + Graphics2D g2d = (Graphics2D) g; + g2d.setColor(UIConstants.NORMAL_BACKGROUND); + g2d.fillRect(0, 0, w, h); + } + + protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { + ButtonModel model = menuItem.getModel(); + FontMetrics fm = SwingUtilities2.getFontMetrics(menuItem, g); + int mnemIndex = -1; + + if (!model.isEnabled()) { + // *** paint the text disabled + if (UIManager.get("MenuItem.disabledForeground") instanceof Color) { + g.setColor(UIManager.getColor("MenuItem.disabledForeground")); + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text, + mnemIndex, textRect.x, textRect.y + fm.getAscent()); + } else { + g.setColor(menuItem.getBackground().brighter()); + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text, + mnemIndex, textRect.x, textRect.y + fm.getAscent()); + g.setColor(menuItem.getBackground().darker()); + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text, + mnemIndex, textRect.x - 1, textRect.y + + fm.getAscent() - 1); + } + } else { + // *** paint the text normally + if (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) { + g.setColor(selectionForeground); // Uses protected field. + } + SwingUtilities2.drawStringUnderlineCharAt(menuItem, g, text, + mnemIndex, textRect.x, textRect.y + fm.getAscent()); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIPopupMenu.java b/designer_base/src/com/fr/design/gui/imenu/UIPopupMenu.java new file mode 100644 index 0000000000..9555689f6e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIPopupMenu.java @@ -0,0 +1,34 @@ +package com.fr.design.gui.imenu; + +import java.awt.Graphics; +import java.awt.Insets; + +import javax.swing.JPopupMenu; + +import com.fr.design.constants.UIConstants; + +public class UIPopupMenu extends JPopupMenu{ + private boolean onlyText = false; + public UIPopupMenu() { + super(); + setBackground(UIConstants.NORMAL_BACKGROUND); + } + + @Override + protected void paintBorder(Graphics g) { + g.setColor(UIConstants.LINE_COLOR); + g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); + } + + @Override + public Insets getInsets() { + if(onlyText) { + return super.getInsets(); + } + return new Insets(10, 2, 10, 10); + } + + public void setOnlyText(boolean onlyText) { + this.onlyText = onlyText; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIPopupMenuBorder.java b/designer_base/src/com/fr/design/gui/imenu/UIPopupMenuBorder.java new file mode 100644 index 0000000000..8ea8574763 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIPopupMenuBorder.java @@ -0,0 +1,62 @@ +package com.fr.design.gui.imenu; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-1-2 + * Time: 上午10:10 + */ +public class UIPopupMenuBorder extends AbstractBorder implements UIResource { + + /** + * Draws a simple 3d border for the given component. + * + * @param mainColor The component to draw its border. + * @param g The graphics context. + * @param x The x coordinate of the top left corner. + * @param y The y coordinate of the top left corner. + * @param w The width. + * @param h The height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + + g.translate(x, y); + // Inner highlight: + g.setColor(new ColorUIResource(255, 255, 255)); + g.drawLine(1, 1, w - 3, 1); + g.drawLine(1, 1, 1, h - 3); + + // Inner shadow: + g.setColor(new ColorUIResource(213, 212, 207)); + g.drawLine(w - 2, 1, w - 2, h - 2); + g.drawLine(1, h - 2, w - 2, h - 2); + + // Outer highlight: + g.setColor(new ColorUIResource(173, 170, 153)); + g.drawLine(0, 0, w - 2, 0); + g.drawLine(0, 0, 0, h - 1); + + // Outer shadow: + g.setColor(new ColorUIResource(173, 170, 153)); + g.drawLine(w - 1, 0, w - 1, h - 1); + g.drawLine(0, h - 1, w - 1, h - 1); + g.translate(-x, -y); + + } + + /** + * Gets the border insets for a given component. + * + * @param mainColor The component to get its border insets. + * @return Always returns the same insets as defined in insets. + */ + public Insets getBorderInsets(Component c) { + return new Insets(2, 2, 2, 2); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIPopupMenuSeparatorUI.java b/designer_base/src/com/fr/design/gui/imenu/UIPopupMenuSeparatorUI.java new file mode 100644 index 0000000000..28700b6726 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIPopupMenuSeparatorUI.java @@ -0,0 +1,31 @@ +package com.fr.design.gui.imenu; + + +import javax.swing.*; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalSeparatorUI; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-1-2 + * Time: 上午10:00 + */ +public class UIPopupMenuSeparatorUI extends MetalSeparatorUI { + public static ComponentUI createUI(JComponent c) { + return new UIPopupMenuSeparatorUI(); + } + + + public void paint(Graphics g, JComponent c) { + Dimension s = c.getSize(); + g.setColor(new ColorUIResource(255, 255, 255)); + g.fillRect(0, 0, s.width, s.height); + + g.setColor(new ColorUIResource(173, 170, 153)); + g.drawLine(2, 1, s.width - 3, 1); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIScrollMenu.java b/designer_base/src/com/fr/design/gui/imenu/UIScrollMenu.java new file mode 100644 index 0000000000..afe9db6478 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIScrollMenu.java @@ -0,0 +1,312 @@ +package com.fr.design.gui.imenu; + +/** + * Created with IntelliJ IDEA. + * User: richie + * Date: 13-12-5 + * Time: 上午11:11 + */ + +import javax.swing.*; +import java.awt.*; + + +public class UIScrollMenu extends UIMenu { + // Covers the one in the JMenu because the method that creates it in JMenu is private + /** + * The popup menu portion of the menu. + */ + private JPopupMenu popupMenu; + + + /** + * Constructs a new JMenu with no text. + */ + public UIScrollMenu() { + this(""); + } + + /** + * Constructs a new JMenu with the supplied string as its text. + * + * @param s the text for the menu label + */ + public UIScrollMenu(String s) { + super(s); + } + + /** + * Constructs a menu whose properties are taken from the Action supplied. + * + * @param a an Action + */ + public UIScrollMenu(Action a) { + this(); + setAction(a); + } + + + /** + * Lazily creates the popup menu. This method will create the popup using the JScrollPopupMenu class. + */ + protected void ensurePopupMenuCreated() { + if (popupMenu == null) { + this.popupMenu = new UIScrollPopUpMenu(); + popupMenu.setInvoker(this); + popupListener = createWinListener(popupMenu); + } + } + + ////////////////////////////// +//// All of these methods are necessary because ensurePopupMenuCreated() is private in JMenu +////////////////////////////// + + /** + *画界面 + */ + public void updateUI() { + setUI(new UIMenuUI()); + } + + + /** + * 判断popupmeu是否隐藏 + * @return 如果隐藏 返回true + */ + public boolean isPopupMenuVisible() { + ensurePopupMenuCreated(); + return popupMenu.isVisible(); + } + + + /** + * 设置popupmenu位置 + * @param x + * @param y + */ + public void setMenuLocation(int x, int y) { + super.setMenuLocation(x, y); + if (popupMenu != null) { + popupMenu.setLocation(x, y); + } + } + + /** + * 向popupmenu添加 JMenuItem + * @param menuItem 菜单项 + * @return 菜单项 + */ + public JMenuItem add(JMenuItem menuItem) { + ensurePopupMenuCreated(); + return popupMenu.add(menuItem); + } + + /** + * 添加组件 + * @param c 组件 + * @return 组件 + */ + public Component add(Component c) { + ensurePopupMenuCreated(); + popupMenu.add(c); + return c; + } + + /** + * 向指定位置添加组件 + * @param c 组件 + * @param index 位置 + * @return 组件 + */ + public Component add(Component c, int index) { + ensurePopupMenuCreated(); + popupMenu.add(c, index); + return c; + } + + + /** + * 添加分隔符 + */ + public void addSeparator() { + ensurePopupMenuCreated(); + popupMenu.addSeparator(); + } + + /** + * 添加menuitem到指定位置 + * @param s 字符 + * @param pos 位置 + */ + public void insert(String s, int pos) { + if (pos < 0) { + throw new IllegalArgumentException("index less than zero."); + } + + ensurePopupMenuCreated(); + popupMenu.insert(new JMenuItem(s), pos); + } + + /** + * 添加么会特么到指定位置 + * @param mi 菜单项 + * @param pos 位置 + * @return 菜单项 + */ + public JMenuItem insert(JMenuItem mi, int pos) { + if (pos < 0) { + throw new IllegalArgumentException("index less than zero."); + } + ensurePopupMenuCreated(); + popupMenu.insert(mi, pos); + return mi; + } + + /** + * 添加到指定位置 + * @param a 事件 + * @param pos 位置 + * @return 菜单项 + */ + public JMenuItem insert(Action a, int pos) { + if (pos < 0) { + throw new IllegalArgumentException("index less than zero."); + } + + ensurePopupMenuCreated(); + JMenuItem mi = new JMenuItem(a); + mi.setHorizontalTextPosition(JButton.TRAILING); + mi.setVerticalTextPosition(JButton.CENTER); + popupMenu.insert(mi, pos); + return mi; + } + + /** + * 添加分隔符到指定位置 + * @param index 指定位置 + */ + public void insertSeparator(int index) { + if (index < 0) { + throw new IllegalArgumentException("index less than zero."); + } + + ensurePopupMenuCreated(); + popupMenu.insert(new JPopupMenu.Separator(), index); + } + + + /** + * 移除 + * @param item 菜单项 + */ + public void remove(JMenuItem item) { + if (popupMenu != null) { + popupMenu.remove(item); + } + } + + /** + * 移除指定位置菜单项 + * @param pos 指定位置 + */ + public void remove(int pos) { + if (pos < 0) { + throw new IllegalArgumentException("index less than zero."); + } + if (pos > getItemCount()) { + throw new IllegalArgumentException("index greater than the number of items."); + } + if (popupMenu != null) { + popupMenu.remove(pos); + } + } + + /** + * 移除组件 + * @param c 组件 + */ + public void remove(Component c) { + if (popupMenu != null) { + popupMenu.remove(c); + } + } + + /** + * 移除所有 + */ + public void removeAll() { + if (popupMenu != null) { + popupMenu.removeAll(); + } + } + + /** + * 组件总数 + * @return 组件总数 + */ + public int getMenuComponentCount() { + return (popupMenu == null) ? 0 : popupMenu.getComponentCount(); + } + + /** + * 指定位置组件 + * @param n 指定位置 + * @return 组件 + */ + public Component getMenuComponent(int n) { + return (popupMenu == null) ? null : popupMenu.getComponent(n); + } + + /** + * 所有组件 + * @return 所有组件 + */ + public Component[] getMenuComponents() { + return (popupMenu == null) ? new Component[0] : popupMenu.getComponents(); + } + + /** + * 取得弹出菜单 + * @return 菜单 + */ + public JPopupMenu getPopupMenu() { + ensurePopupMenuCreated(); + return popupMenu; + } + + /** + * 得到子元素 + * @return 子元素 + */ + public MenuElement[] getSubElements() { + return popupMenu == null ? new MenuElement[0] : new MenuElement[]{popupMenu}; + } + + + /** + * 设置所有组件方位 + * @param o 方位 + */ + public void applyComponentOrientation(ComponentOrientation o) { + super.applyComponentOrientation(o); + + if (popupMenu != null) { + int ncomponents = getMenuComponentCount(); + for (int i = 0; i < ncomponents; ++i) { + getMenuComponent(i).applyComponentOrientation(o); + } + popupMenu.setComponentOrientation(o); + } + } + + /** + * 设置所有组件方位 + * @param o 方位 + */ + public void setComponentOrientation(ComponentOrientation o) { + super.setComponentOrientation(o); + if (popupMenu != null) { + popupMenu.setComponentOrientation(o); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIScrollMenuDemo.java b/designer_base/src/com/fr/design/gui/imenu/UIScrollMenuDemo.java new file mode 100644 index 0000000000..6b2f50c7c5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIScrollMenuDemo.java @@ -0,0 +1,71 @@ +package com.fr.design.gui.imenu; + +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import java.awt.event.KeyEvent; + +/** + * Created with IntelliJ IDEA. + * User: richie + * Date: 13-12-5 + * Time: 上午11:12 + */ +public class UIScrollMenuDemo extends JFrame { + public UIScrollMenuDemo() { + UIMenuBar menuBar = new UIMenuBar(); + + // File Menu, F - Mnemonic + JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic(KeyEvent.VK_F); + menuBar.add(fileMenu); + + // File->New, N - Mnemonic + UIMenuItem newMenuItem = new UIMenuItem("New", KeyEvent.VK_N); + fileMenu.add(newMenuItem); + + // Edit->Options Submenu, O - Mnemonic, at.gif - Icon Image File + UIMenu findOptionsMenu = new UIScrollMenu("Options"); + Icon atIcon = new ImageIcon("at.gif"); + findOptionsMenu.setIcon(atIcon); + findOptionsMenu.setMnemonic(KeyEvent.VK_O); + fileMenu.add(findOptionsMenu); + + // ButtonGroup for radio buttons + ButtonGroup directionGroup = new ButtonGroup(); + + // Edit->Options->Forward, F - Mnemonic, in group + JRadioButtonMenuItem forwardMenuItem = new JRadioButtonMenuItem("Forward", true); + forwardMenuItem.setMnemonic(KeyEvent.VK_F); + findOptionsMenu.add(forwardMenuItem); + directionGroup.add(forwardMenuItem); + + // Edit->Options->Backward, B - Mnemonic, in group + JRadioButtonMenuItem backwardMenuItem = new JRadioButtonMenuItem("Backward"); + backwardMenuItem.setMnemonic(KeyEvent.VK_B); + findOptionsMenu.add(backwardMenuItem); + directionGroup.add(backwardMenuItem); + + for (int i = 0; i < 100; i ++) { + JRadioButtonMenuItem m = new JRadioButtonMenuItem("Backward" + i); + m.setMnemonic(KeyEvent.VK_B); + findOptionsMenu.add(m); + directionGroup.add(m); + } + + + setJMenuBar(menuBar); + + setSize(400, 400); + GUICoreUtils.centerWindow(this); + } + + public static void main(String... args) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + new UIScrollMenuDemo().setVisible(true); + } + }); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenu/UIScrollPopUpMenu.java b/designer_base/src/com/fr/design/gui/imenu/UIScrollPopUpMenu.java new file mode 100644 index 0000000000..3f8fd6a423 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenu/UIScrollPopUpMenu.java @@ -0,0 +1,221 @@ +package com.fr.design.gui.imenu; + + +import com.fr.design.gui.iscrollbar.UIScrollBar; + +import java.awt.*; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +/** + * Author : daisy + * Date: 13-8-27 + * Time: 上午9:12 + */ +public class UIScrollPopUpMenu extends UIPopupMenu { + private static final int MAX_SHOW_NUM = 27; + + private UIScrollBar scrollBar; + + + public UIScrollPopUpMenu() { + super(); + setLayout(new ScrollPopupMenuLayout()); + super.add(getScrollBar()); + addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + UIScrollBar scrollBar = getScrollBar(); + int amount = (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) + ? e.getUnitsToScroll() * scrollBar.getUnitIncrement() + : (e.getWheelRotation() < 0 ? -1 : 1) * scrollBar.getBlockIncrement(); + + scrollBar.setValue(scrollBar.getValue() + amount); + e.consume(); + } + }); + } + + + public void paintChildren(Graphics g) { + Insets insets = getInsets(); + g.clipRect(insets.left, insets.top, getWidth(), getHeight() - insets.top - insets.bottom); + super.paintChildren(g); + } + + /** + * 展现 popupmenu + * @param invoker 组件 + * @param x 定位 + * @param y 定位 + */ + public void show(Component invoker, int x, int y) { + UIScrollBar scrollBar = getScrollBar(); + if (scrollBar.isVisible()) { + int extent = 0; + int max = 0; + int i = 0; + int unit = -1; + int width = 0; + for (Component comp : getComponents()) { + if (!(comp instanceof UIScrollBar)) { + Dimension preferredSize = comp.getPreferredSize(); + width = Math.max(width, preferredSize.width); + if (unit < 0) { + unit = preferredSize.height; + } + if (i++ < MAX_SHOW_NUM) { + extent += preferredSize.height; + } + max += preferredSize.height; + } + } + + Insets insets = getInsets(); + width += insets.left + insets.right + scrollBar.getWidth(); + int heightMargin = insets.top + insets.bottom; + scrollBar.setUnitIncrement(unit); + scrollBar.setBlockIncrement(extent); + scrollBar.setValues(0, heightMargin + extent, 0, heightMargin + max); + int height = heightMargin + extent; + + setPopupSize(new Dimension(width, height)); + } + + super.show(invoker, x, y); + } + + + private UIScrollBar getScrollBar() { + if (scrollBar == null) { + scrollBar = new UIScrollBar(UIScrollBar.VERTICAL); + scrollBar.addAdjustmentListener(new AdjustmentListener() { + public void adjustmentValueChanged(AdjustmentEvent e) { + doLayout(); + repaint(); + } + }); + + scrollBar.setVisible(false); + } + + return scrollBar; + } + + + protected void addImpl(Component comp, Object constraints, int index) { + super.addImpl(comp, constraints, index); + + if (MAX_SHOW_NUM < getComponentCount() - 1) { + getScrollBar().setVisible(true); + } + } + /** + * 移除 + * @param index 指定位置 + */ + public void remove(int index) { + // can't remove the scrollbar + ++index; + + super.remove(index); + + if (MAX_SHOW_NUM >= getComponentCount() - 1) { + getScrollBar().setVisible(false); + } + } + + + private class ScrollPopupMenuLayout implements LayoutManager { + @Override + public void addLayoutComponent(String name, Component comp) { + } + + @Override + public void removeLayoutComponent(Component comp) { + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + int scrollBarWidth = 0; + int visibleAmount = Integer.MAX_VALUE; + Dimension dim = new Dimension(); + for (Component comp : parent.getComponents()) { + if (comp.isVisible()) { + if (comp instanceof UIScrollBar) { + UIScrollBar scrollBar = (UIScrollBar) comp; + scrollBarWidth = scrollBar.getWidth(); + visibleAmount = scrollBar.getVisibleAmount(); + } else { + Dimension pref = comp.getPreferredSize(); + dim.width = Math.max(dim.width, pref.width); + dim.height += pref.height; + } + } + } + + Insets insets = parent.getInsets(); + dim.width += insets.left + insets.right + scrollBarWidth; + dim.height = Math.min(dim.height + insets.top + insets.bottom, visibleAmount); + + return dim; + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + int visibleAmount = Integer.MAX_VALUE; + Dimension dim = new Dimension(); + for (Component comp : parent.getComponents()) { + if (comp.isVisible()) { + if (comp instanceof UIScrollBar) { + UIScrollBar scrollBar = (UIScrollBar) comp; + visibleAmount = scrollBar.getVisibleAmount(); + } else { + Dimension min = comp.getMinimumSize(); + dim.width = Math.max(dim.width, min.width); + dim.height += min.height; + } + } + } + + Insets insets = parent.getInsets(); + dim.width += insets.left + insets.right; + dim.height = Math.min(dim.height + insets.top + insets.bottom, visibleAmount); + + return dim; + } + + @Override + public void layoutContainer(Container parent) { + Insets insets = parent.getInsets(); + + int width = parent.getPreferredSize().width - insets.left - insets.right; + int height = parent.getHeight() - insets.top - insets.bottom; + + int x = insets.left; + int y = insets.top; + int position = 0; + + for (Component comp : parent.getComponents()) { + if ((comp instanceof UIScrollBar) && comp.isVisible()) { + UIScrollBar scrollBar = (UIScrollBar) comp; + Dimension dim = scrollBar.getPreferredSize(); + scrollBar.setBounds(x + width - 1, y, dim.width, height); + width -= dim.width; + position = scrollBar.getValue(); + } + } + + y -= position; + for (Component comp : parent.getComponents()) { + if (!(comp instanceof UIScrollBar) && comp.isVisible()) { + Dimension pref = comp.getPreferredSize(); + comp.setBounds(x, y, width, pref.height); + y += pref.height; + } + } + + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenutable/UIMenuNameableCreator.java b/designer_base/src/com/fr/design/gui/imenutable/UIMenuNameableCreator.java new file mode 100644 index 0000000000..5b6f8606df --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenutable/UIMenuNameableCreator.java @@ -0,0 +1,65 @@ +package com.fr.design.gui.imenutable; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.general.FRLogger; +import com.fr.stable.Nameable; + +public class UIMenuNameableCreator implements Nameable{ + + protected String name; + protected Object obj; + protected Class paneClazz; + + public UIMenuNameableCreator(String name, Object obj, Class paneClazz) { + this.name = name; + this.obj = obj; + this.paneClazz = paneClazz; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + public Object getObj() { + return obj; + } + + public void setObj(Object obj) { + this.obj = obj; + } + + /** + * 覆盖的clone方法 + */ + public UIMenuNameableCreator clone() { + Object cloneObj = null; + try { + cloneObj = obj.getClass().newInstance(); + } catch (InstantiationException e) { + FRLogger.getLogger().error("UIMenuNameableCreator InstantiationException"); + } catch (IllegalAccessException e) { + FRLogger.getLogger().error("UIMenuNameableCreator IllegalAccessException"); + } + return new UIMenuNameableCreator(name, cloneObj, this.paneClazz); + + } + + public BasicBeanPane getPane() { + try { + return this.paneClazz.newInstance(); + } catch (InstantiationException e) { + + } catch (IllegalAccessException e) { + + } + return null; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenutable/UIMenuTable.java b/designer_base/src/com/fr/design/gui/imenutable/UIMenuTable.java new file mode 100644 index 0000000000..caf95a40df --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenutable/UIMenuTable.java @@ -0,0 +1,240 @@ +package com.fr.design.gui.imenutable; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.JFrame; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.TableUI; +import javax.swing.table.TableCellRenderer; + +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.gui.itable.UITable; +import com.fr.design.hyperlink.ReportletHyperlinkPane; +import com.fr.design.hyperlink.WebHyperlinkPane; +import com.fr.design.javascript.EmailPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.UIDialog; +import com.fr.general.Inter; +import com.fr.js.EmailJavaScript; +import com.fr.js.ReportletHyperlink; +import com.fr.js.WebHyperlink; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UIMenuTable extends JTable { + protected int selectedRowIndex = -1; + protected int rollOverRowIndex = -1; + protected int draggingIndex = -1; + + public UIMenuTable() { + super(new UIMenuTableDataModel()); + initComponents(); + } + + public void populateBean(List values) { + ((UIMenuTableDataModel)dataModel).populateBean(values); + } + + public List updateBean() { + return ((UIMenuTableDataModel)dataModel).updateBean(); + } + + public void editingEvent(int rowIndex, int mouseY) { + selectedRowIndex = rowIndex; + repaint(); + + final UIMenuNameableCreator nameObject = UIMenuTable.this.getLine(rowIndex); + + final BasicBeanPane baseShowPane = nameObject.getPane(); + + final Object showValue = nameObject.getObj(); + + baseShowPane.populateBean(showValue); + + UIDialog dialog = baseShowPane.showUnsizedWindow(SwingUtilities.getWindowAncestor(new JPanel()), new DialogActionAdapter() { + public void doOk() { + baseShowPane.updateBean(showValue); + fireTargetChanged(); + } + }); + + dialog.setSize(500, 600); + GUICoreUtils.centerWindow(dialog); + + dialog.setVisible(true); + } + + protected Color getRenderBackground(int row) { + if(selectedRowIndex == row ) { + return UIConstants.SKY_BLUE; + } else { + return (rollOverRowIndex == row) ? UIConstants.LIGHT_BLUE : UIConstants.NORMAL_BACKGROUND; + } + } + + /** + * + * @param value 该行列的值(字符串) + * @param row + * @param column + * @return 列表中默认显示的东西,如果有很多内容,可以装载一个JPanel里再嵌进来 + */ + protected JComponent getRenderCompoment(Object value, int row,int column) { + UILabel text = new UILabel(); + if(value != null) { + text.setText(value.toString()); + } + return text; + } + + /** + * @param line 该行的内容 + * 在table底部增加一行内容 + */ + public void addLine(UIMenuNameableCreator line) { + ((UIMenuTableDataModel)dataModel).addLine(line); + } + + /** + * @param rowIndex + * @return 某一行的内容 + */ + public UIMenuNameableCreator getLine(int rowIndex) { + return ((UIMenuTableDataModel)dataModel).getLine(rowIndex); + } + + /** + * 删除某行内容 + * @param rowIndex + */ + public void removeLine(int rowIndex) { + ((UIMenuTableDataModel)dataModel).removeLine(rowIndex); + } + + /** + * 清除所有的内容 + */ + public void clearAll() { + int rowCount = dataModel.getRowCount(); + for(int i = 0; i < rowCount; i++) { + removeLine(i); + } + } + + /** + * 对某一行拖动时进行排序 + * @param rowIndex + * @param positive 鼠标移动的距离 + */ + public void dragSort(int rowIndex, boolean positive) { + ((UIMenuTableDataModel)dataModel).dragSort(rowIndex, positive); + } + + @Override + public boolean isCellEditable(int row, int column) { + if(column == 0) { + return false; + } else { + return super.isCellEditable(row, column); + } + } + + @Override + public TableUI getUI() { + return new UIMenuTableUI(); + } + + private void initComponents() { + setShowGrid(false); + setRowHeight(20); + setDragEnabled(false); + setDefaultRenderer(UITable.class, new UITableRender()); + setUI(getUI()); + } + + @Override + public TableCellRenderer getDefaultRenderer(Class columnClass) { + columnClass = UITable.class; + return super.getDefaultRenderer(columnClass); + } + + private class UITableRender implements TableCellRenderer { + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column) { + JPanel pane = new JPanel(new BorderLayout(4,0)); + Color back = getRenderBackground(row); + pane.setBackground(back); + + if(draggingIndex == row) { + return pane; + } + pane.add(getRenderCompoment(value, row, column), BorderLayout.CENTER); + return pane; + } + } + + protected void setRollOverRowIndex(int rowIndex) { + this.rollOverRowIndex = rowIndex; + } + + protected void setDraggingRowIndex(int rowIndex) { + this.draggingIndex = rowIndex; + } + + public void fireTargetChanged() { + repaint(); + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener)listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel)jf.getContentPane(); + content.setLayout(new BorderLayout()); + List data = new ArrayList(); + UIMenuNameableCreator reportlet = new UIMenuNameableCreator(Inter.getLocText("Reportlet"), + new ReportletHyperlink(), true ? ReportletHyperlinkPane.CHART.class : ReportletHyperlinkPane.class); + + UIMenuNameableCreator email = new UIMenuNameableCreator(Inter.getLocText("Email"), + new EmailJavaScript(), EmailPane.class); + + UIMenuNameableCreator web = new UIMenuNameableCreator(Inter.getLocText("Hyperlink-Web_link"), + new WebHyperlink(), true ? WebHyperlinkPane.CHART.class : WebHyperlinkPane.class ); + data.add(reportlet); + data.add(email); + data.add(web); + UIMenuTable pane = new UIMenuTable(); + pane.populateBean(data); + content.add(pane, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenutable/UIMenuTableDataModel.java b/designer_base/src/com/fr/design/gui/imenutable/UIMenuTableDataModel.java new file mode 100644 index 0000000000..4aca6b74a4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenutable/UIMenuTableDataModel.java @@ -0,0 +1,119 @@ +package com.fr.design.gui.imenutable; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; + + +public class UIMenuTableDataModel implements TableModel{ + private List values; + + public UIMenuTableDataModel() { + values = new ArrayList(); + } + + + public void populateBean(List values) { + if(values == null) { + return; + } + this.values.clear(); + this.values = values; + } + + public List updateBean() { + return values; + } + + public void dragSort(int rowIndex, boolean positive) { + if(values == null || rowIndex == -1) { + return; + } + + if(positive && rowIndex < values.size() - 1) { + UIMenuNameableCreator tmp = values.get(rowIndex); + values.set(rowIndex, values.get(rowIndex + 1)); + values.set(rowIndex + 1, tmp); + tmp = null; + } else if(!positive && rowIndex > 1) { + UIMenuNameableCreator tmp = values.get(rowIndex); + values.set(rowIndex, values.get(rowIndex - 1)); + values.set(rowIndex - 1, tmp); + tmp = null; + } + } + + public UIMenuNameableCreator getLine(int rowIndex) { + if(rowIndex >= values.size() || rowIndex < 0) { + return null; + } + return values.get(rowIndex); + } + + public void removeLine(int rowIndex) { + if(rowIndex >= values.size() || rowIndex < 0) { + return; + } + values.remove(rowIndex); + } + + public void addLine(UIMenuNameableCreator line) { + values.add(line); + } + + @Override + public int getRowCount() { + return values.size(); + } + + @Override + public int getColumnCount() { + return 1; + } + + @Override + public String getColumnName(int columnIndex) { + return null; + } + + @Override + public Class getColumnClass(int columnIndex) { + return null; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return true; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if(rowIndex >= values.size()) { + return null; + } + return values.get(rowIndex).getName(); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if(rowIndex >= values.size()) { + return; + } + values.get(rowIndex).setName(aValue.toString()); + } + + @Override + public void addTableModelListener(TableModelListener l) { + // TODO Auto-generated method stub + + } + + @Override + public void removeTableModelListener(TableModelListener l) { + // TODO Auto-generated method stub + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/imenutable/UIMenuTableUI.java b/designer_base/src/com/fr/design/gui/imenutable/UIMenuTableUI.java new file mode 100644 index 0000000000..1fafc1495c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/imenutable/UIMenuTableUI.java @@ -0,0 +1,124 @@ +package com.fr.design.gui.imenutable; + +import java.awt.Graphics2D; +import java.awt.event.MouseEvent; + +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.event.MouseInputListener; + +import com.fr.base.GraphHelper; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.itable.UITableUI; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +public class UIMenuTableUI extends UITableUI{ + private UIMenuTable uiTable; + + protected void startDragTab(MouseEvent e) { + rollOverRowIndex = -1; + dragStartY = e.getY(); + dragStartRowIndex = table.rowAtPoint(e.getPoint()); + uiTable.setDraggingRowIndex(table.rowAtPoint(e.getPoint())); + uiTable.setRollOverRowIndex(-1); + } + + protected void resetDragTab() { + dragStartY = -1; + dragEndY = -1; + isReleased = true; + uiTable.setDraggingRowIndex(-1); + uiTable.setRollOverRowIndex(-1); + } + + protected void paintDragTab(Graphics2D g2d) { + if(dragEndY != -1 && dragEndY <= table.getHeight() + table.getRowHeight()) { + g2d.setColor(UIConstants.LIGHT_BLUE); + g2d.fillRect(0, dragEndY, table.getWidth(), table.getRowHeight()); + UIMenuNameableCreator values = uiTable.getLine(dragStartRowIndex); + if(values == null) { + return; + } + g2d.setColor(UIConstants.LINE_COLOR); + String text = values.getName(); + if(!StringUtils.isEmpty(text)) { + GraphHelper.drawString(g2d, text, 0, dragEndY + table.getRowHeight() - 5); + } + } + } + + public void installUI(JComponent c) { + table = (UIMenuTable)c; + uiTable = (UIMenuTable) table; + rendererPane = new CellRendererPane(); + table.add(rendererPane); + installDefaults(); + installListeners(); + installKeyboardActions(); + } + + protected MouseInputListener createMouseInputListener() { + return new MyMouseListener() { + public void mouseMoved(MouseEvent e) { + int tmp = table.rowAtPoint(e.getPoint()); + if(rollOverRowIndex != tmp && isReleased) { + rollOverRowIndex = tmp; + uiTable.setRollOverRowIndex(rollOverRowIndex); + table.repaint(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (e.getX() >= table.getWidth() - 20) { + int val = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Utils-Are_you_sure_to_remove_the_selected_item") + "?", + Inter.getLocText("Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (val == JOptionPane.OK_OPTION) { + uiTable.removeLine(table.rowAtPoint(e.getPoint())); + uiTable.fireTargetChanged(); + uiTable.getParent().doLayout(); + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if(!isReleased) { + resetDragTab(); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + int rowIndex = table.rowAtPoint(e.getPoint()); + int columnIndex = table.columnAtPoint(e.getPoint()); + if ((rowIndex == -1) || (columnIndex == -1)) { + return; + } + uiTable.editingEvent(rowIndex, e.getLocationOnScreen().y); + } + + @Override + public void mouseDragged(MouseEvent e) { + + if(isReleased) { + startDragTab(e); + } + isReleased = false; + dragEndY = e.getY(); + int dierta = dragEndY - dragStartY; + if(Math.abs(dierta) >= table.getRowHeight()) { + uiTable.dragSort(dragStartRowIndex, dierta > 0); + uiTable.fireTargetChanged(); + startDragTab(e); + return; + } + + table.repaint(); + } + }; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ipasswordfield/UIPassWordField.java b/designer_base/src/com/fr/design/gui/ipasswordfield/UIPassWordField.java new file mode 100644 index 0000000000..c7910d0cd4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ipasswordfield/UIPassWordField.java @@ -0,0 +1,35 @@ +package com.fr.design.gui.ipasswordfield; + + +import javax.swing.*; +import javax.swing.text.Document; + +/** + * Created with IntelliJ IDEA. + * User: 小灰灰 + * Date: 13-7-22 + * Time: 下午4:44 + * To change this template use File | Settings | File Templates. + */ +public class UIPassWordField extends JPasswordField { + + public UIPassWordField () { + super(); + } + + public UIPassWordField (String text) { + super(text); + } + + public UIPassWordField (int columns) { + super(columns); + } + + public UIPassWordField (String text, int columns) { + super(text, columns); + } + + public UIPassWordField (Document doc, String txt, int columns) { + super(doc, txt, columns); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ipoppane/PopupHider.java b/designer_base/src/com/fr/design/gui/ipoppane/PopupHider.java new file mode 100644 index 0000000000..cb31d95c6b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ipoppane/PopupHider.java @@ -0,0 +1,5 @@ +package com.fr.design.gui.ipoppane; + +public interface PopupHider { + public void hidePopupMenu(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iprogressbar/AutoProgressBar.java b/designer_base/src/com/fr/design/gui/iprogressbar/AutoProgressBar.java new file mode 100644 index 0000000000..41399caecf --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iprogressbar/AutoProgressBar.java @@ -0,0 +1,50 @@ +package com.fr.design.gui.iprogressbar; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-6-5 + * Time: 下午3:52 + * To change this template use File | Settings | File Templates. + */ +public abstract class AutoProgressBar implements MonitorCancelWork{ + private ProgressMonitor monitor; + private Timer timer; + private int i; + + public AutoProgressBar(Component parentComponent, Object message, String note, int min, int max) { + monitor = new ProgressMonitor(parentComponent, message, note, min, max); + monitor.setProgress(0); + monitor.setMillisToDecideToPopup(0); + timer = new Timer(50, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + i = i > 99 ? 0 : i; + monitor.setProgress(i); + i++; + if (monitor.isCanceled()) { + doMonitorCanceled(); + timer.stop(); + } + } + }); + } + + public void start() { + i = 0; + timer.start(); + } + + public void close() { + timer.stop(); + monitor.setProgress(100); + monitor.close(); + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iprogressbar/FRProgressBar.java b/designer_base/src/com/fr/design/gui/iprogressbar/FRProgressBar.java new file mode 100644 index 0000000000..a4829124b7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iprogressbar/FRProgressBar.java @@ -0,0 +1,43 @@ +package com.fr.design.gui.iprogressbar; + +import javax.swing.*; +import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class FRProgressBar { + private ProgressMonitor monitor; + private SwingWorker worker; + + public FRProgressBar(SwingWorker worker, Component parentComponent, Object message, String note, int min, int max) { + monitor = new ProgressMonitor(parentComponent, message, note, min, max); + monitor.setProgress(0); + monitor.setMillisToDecideToPopup(0); + this.worker = worker; + + this.worker.addPropertyChangeListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + int progress = FRProgressBar.this.worker.getProgress(); + monitor.setProgress(progress); + + if (ismonitorCanceled()) { + FRProgressBar.this.worker.cancel(true); + } + } + }); + } + + public void start() { + this.worker.execute(); + } + + public void close() { + monitor.close(); + } + + public boolean ismonitorCanceled() { + return monitor.isCanceled(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iprogressbar/MonitorCancelWork.java b/designer_base/src/com/fr/design/gui/iprogressbar/MonitorCancelWork.java new file mode 100644 index 0000000000..d1dfe92118 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iprogressbar/MonitorCancelWork.java @@ -0,0 +1,12 @@ +package com.fr.design.gui.iprogressbar; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-6-5 + * Time: 下午7:24 + * To change this template use File | Settings | File Templates. + */ +public interface MonitorCancelWork { + public void doMonitorCanceled(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarBorder.java b/designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarBorder.java new file mode 100644 index 0000000000..4d0fa6748f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarBorder.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.iprogressbar; + +import com.fr.design.utils.DrawRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.border.AbstractBorder; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-4 + * Time: 上午11:03 + */ +public class UIProgressBarBorder extends AbstractBorder implements UIResource { + protected static final Insets INSETS_YQ = new Insets(3, 3, 3, 3); + + /** + * Draws the button border for the given component. + * + * @param c The component to draw its border. + * @param g The graphics context. + * @param x The x coordinate of the top left corner. + * @param y The y coordinate of the top left corner. + * @param w The width. + * @param h The height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + DrawRoutines.drawProgressBarBorder(g, + ThemeUtils.PROCESS_BORDER_COLOR, x, y, w, h); + + DrawRoutines.drawProgressBarBorder(g, + ThemeUtils.PROCESS_DARK_COLOR, x + 1, y + 1, w - 2, h - 2); + + + w -= 4; + h -= 4; + x += 2; + y += 2; + g.setColor(ThemeUtils.PROCESS_LIGHT_COLOR); + // rect + g.drawLine(x + 1, y, x + w - 2, y); + g.drawLine(x, y + 1, x, y + h - 2); + + // track + g.setColor(ThemeUtils.PROCESS_TRACK_COLOR); + g.drawLine(x + 1, y + h - 1, x + w - 2, y + h - 1); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 2); + + } + + /** + * Gets the border insets for a given component. + * + * @param c The component to get its border insets. + * @return Always returns the same insets as defined in insets. + */ + public Insets getBorderInsets(Component c) { + return INSETS_YQ; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarUI.java b/designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarUI.java new file mode 100644 index 0000000000..add99b0ad5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iprogressbar/UIProgressBarUI.java @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.iprogressbar; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ColorRoutines; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicProgressBarUI; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-4 + * Time: 上午10:41 + */ +public class UIProgressBarUI extends BasicProgressBarUI { + + static HashMap cache = new HashMap(); + + /* "Override" the dimensions from BasicProgressBarUI */ + private static final Dimension PREFERRED_YQ_HORIZONTAL = new Dimension(146, 7); + private static final Dimension PREFERRED_YQ_VERTICAL = new Dimension(7, 146); + + protected Dimension getPreferredInnerHorizontal() { + return PREFERRED_YQ_HORIZONTAL; + } + + protected Dimension getPreferredInnerVertical() { + return PREFERRED_YQ_VERTICAL; + } + + /** + * 创建UI + * + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIProgressBarUI(); + } + + protected void paintDeterminate(Graphics g, JComponent c) { + Insets b = progressBar.getInsets(); // area for border + int barRectWidth = progressBar.getWidth() - (b.right + b.left); + int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { + int amountFull = getAmountFull(b, barRectWidth, barRectHeight); + drawXpHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); + // Deal with possible text painting + if (progressBar.isStringPainted()) { + g.setFont(c.getFont()); + paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b); + } + } else { // VERTICAL + int amountFull = getAmountFull(b, barRectWidth, barRectHeight); + drawXpVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, amountFull); + // Deal with possible text painting + if (progressBar.isStringPainted()) { + g.setFont(c.getFont()); + paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b); + } + } + } + + // draw determinate + private void drawXpHorzProgress(Graphics g, int x, int y, + int w, int h, int amountFull) { + g.translate(x, y); + if (!progressBar.isOpaque()) { + g.setColor(progressBar.getBackground()); + g.fillRect(0, 0, w, h); + } + ProgressKey key = new ProgressKey( + progressBar.getForeground(), true, h); + Object value = cache.get(key); + if (value == null) { + // create new image + Image img = new BufferedImage(6, h, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + // draw into image graphics + Color c = progressBar.getForeground(); + Color c2 = ColorRoutines.lighten(c, 15); + Color c3 = ColorRoutines.lighten(c, 35); + Color c4 = ColorRoutines.lighten(c, 60); + imgGraphics.setColor(c4); + imgGraphics.drawLine(0, 0, 5, 0); + imgGraphics.drawLine(0, h - 1, 5, h - 1); + imgGraphics.setColor(c3); + imgGraphics.drawLine(0, 1, 5, 1); + imgGraphics.drawLine(0, h - 2, 5, h - 2); + imgGraphics.setColor(c2); + imgGraphics.drawLine(0, 2, 5, 2); + imgGraphics.drawLine(0, h - 3, 5, h - 3); + imgGraphics.setColor(c); + imgGraphics.fillRect(0, 3, 6, h - 6); + // dispose of image graphics + imgGraphics.dispose(); + cache.put(key, img); + value = img; + } + int mx = 0; + while (mx < amountFull) { + if (mx + 6 > w) { + // paint partially + g.drawImage((Image) value, mx, 0, w - mx, h, progressBar); + } else { + g.drawImage((Image) value, mx, 0, progressBar); + } + mx += 8; + } + g.translate(-x, -y); + } + + + // draw determinate + private void drawXpVertProgress(Graphics g, int x, int y, + int w, int h, int amountFull) { + g.translate(x, y); + // paint the track + if (!progressBar.isOpaque()) { + g.setColor(progressBar.getBackground()); + g.fillRect(0, 0, w, h); + } + ProgressKey key = new ProgressKey( + progressBar.getForeground(), false, w); + Object value = cache.get(key); + if (value == null) { + // create new image + Image img = new BufferedImage(w, 6, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + Color c = progressBar.getForeground(); + Color c2 = ColorRoutines.lighten(c, 15); + Color c3 = ColorRoutines.lighten(c, 35); + Color c4 = ColorRoutines.lighten(c, 60); + imgGraphics.setColor(c4); + imgGraphics.drawLine(0, 0, 0, 5); + imgGraphics.drawLine(w - 1, 0, w - 1, 5); + imgGraphics.setColor(c3); + imgGraphics.drawLine(1, 0, 1, 5); + imgGraphics.drawLine(w - 2, 0, w - 2, 5); + imgGraphics.setColor(c2); + imgGraphics.drawLine(2, 0, 2, 5); + imgGraphics.drawLine(w - 3, 0, w - 3, 5); + imgGraphics.setColor(c); + imgGraphics.fillRect(3, 0, w - 6, 6); + imgGraphics.dispose(); + cache.put(key, img); + value = img; + } + // paints bottom to top... + int my = 0; + while (my < amountFull) { + if (my + 6 > h) { + // paint partially + g.drawImage((Image) value, 0, + 0, w, h - my, progressBar); + } else { + g.drawImage((Image) value, 0, h - my - 6, progressBar); + } + + my += 8; + } + g.translate(-x, -y); + } + + protected void paintIndeterminate(Graphics g, JComponent c) { + Insets b = progressBar.getInsets(); // area for border + int barRectWidth = progressBar.getWidth() - (b.right + b.left); + int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); + + Rectangle boxRect = new Rectangle(); + + try { + boxRect = getBox(boxRect); + } catch (NullPointerException ignore) { + } + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { + drawXpHorzProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); + } else { + drawXpVertProgress(g, b.left, b.top, barRectWidth, barRectHeight, boxRect); + + } + + // Deal with possible text painting + if (progressBar.isStringPainted()) { + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { + paintString(g, b.left, b.top, barRectWidth, barRectHeight, boxRect.x, boxRect.width, b); + } else { + paintString(g, b.left, b.top, barRectWidth, barRectHeight, boxRect.y, boxRect.height, b); + } + } + } + + private void paintString(Graphics g, int x, int y, int width, int height, int fillStart, int amountFull, Insets b) { + if (!(g instanceof Graphics2D)) { + return; + } + + Graphics2D g2 = (Graphics2D) g; + String progressString = progressBar.getString(); + g2.setFont(progressBar.getFont()); + Point renderLocation = getStringPlacement(g2, progressString, x, y, width, height); + Rectangle oldClip = g2.getClipBounds(); + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { + g2.setColor(getSelectionBackground()); + g2.drawString(progressString, renderLocation.x, renderLocation.y); + g2.setColor(getSelectionForeground()); + g2.clipRect(fillStart, y, amountFull, height); + g.drawString(progressString, renderLocation.x, renderLocation.y); + } else { // VERTICAL + g2.setColor(getSelectionBackground()); + AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2); + g2.setFont(progressBar.getFont().deriveFont(rotate)); + renderLocation = getStringPlacement(g2, progressString, x, y, width, height); + g2.drawString(progressString, renderLocation.x, renderLocation.y); + g2.setColor(getSelectionForeground()); + g2.clipRect(x, fillStart, width, amountFull); + g2.drawString(progressString, renderLocation.x, renderLocation.y); + } + g2.setClip(oldClip); + } + + /* + * Inserted this to fix a bug that came with 1.4.2_02 and caused NPE at + * javax.swing.plaf.basic.BasicProgressBarUI.updateSizes(BasicProgressBarUI.java:439). + * + * @see javax.swing.plaf.basic.BasicProgressBarUI#paintString(java.awt.Graphics, int, int, int, int, int, java.awt.Insets) + */ + protected void paintString(Graphics g, int x, int y, int width, + int height, int amountFull, Insets b) { + Rectangle boxRect = new Rectangle(); // * + try { // * The Fix + boxRect = getBox(boxRect); // * + } catch (NullPointerException ignore) { + } // * + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { + if (progressBar.getComponentOrientation().isLeftToRight()) { + if (progressBar.isIndeterminate()) { + paintString(g, x, y, width, height, boxRect.x, boxRect.width, b); + } else { + paintString(g, x, y, width, height, x, amountFull, b); + } + } else { + paintString(g, x, y, width, height, x + width - amountFull, amountFull, b); + } + } else { + if (progressBar.isIndeterminate()) { + paintString(g, x, y, width, height, boxRect.y, boxRect.height, b); + } else { + paintString(g, x, y, width, height, y + height - amountFull, amountFull, b); + } + } + } + + + // draw indeterminate + private void drawXpHorzProgress(Graphics g, int x, int y, + int w, int h, Rectangle boxRect) { + // paint the track + if (!progressBar.isOpaque()) { + g.setColor(progressBar.getBackground()); + g.fillRect(x, y, w, h); + } + g.translate(boxRect.x, boxRect.y); + ProgressKey key = new ProgressKey( + progressBar.getForeground(), true, h); + Object value = cache.get(key); + if (value == null) { + // create new image + Image img = new BufferedImage(6, h, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + // draw into image graphics + Color c = progressBar.getForeground(); + Color c2 = ColorRoutines.lighten(c, 15); + Color c3 = ColorRoutines.lighten(c, 35); + Color c4 = ColorRoutines.lighten(c, 60); + imgGraphics.setColor(c4); + imgGraphics.drawLine(0, 0, 5, 0); + imgGraphics.drawLine(0, h - 1, 5, h - 1); + imgGraphics.setColor(c3); + imgGraphics.drawLine(0, 1, 5, 1); + imgGraphics.drawLine(0, h - 2, 5, h - 2); + imgGraphics.setColor(c2); + imgGraphics.drawLine(0, 2, 5, 2); + imgGraphics.drawLine(0, h - 3, 5, h - 3); + imgGraphics.setColor(c); + imgGraphics.fillRect(0, 3, 6, h - 6); + // dispose of image graphics + imgGraphics.dispose(); + cache.put(key, img); + value = img; + } + int mx = 0; + while (mx + 6 < boxRect.width) { + g.drawImage((Image) value, mx, 0, progressBar); + + mx += 8; + } + g.translate(-boxRect.x, -boxRect.y); + } + + // draw indeterminate + private void drawXpVertProgress(Graphics g, int x, int y, + int w, int h, Rectangle boxRect) { + // paint the track + if (!progressBar.isOpaque()) { + g.setColor(progressBar.getBackground()); + g.fillRect(x, y, w, h); + } + g.translate(boxRect.x, boxRect.y); + ProgressKey key = new ProgressKey( + progressBar.getForeground(), false, w); + Object value = cache.get(key); + if (value == null) { + // create new image + Image img = new BufferedImage(w, 6, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + // draw into image graphics + Color c = progressBar.getForeground(); + Color c2 = ColorRoutines.lighten(c, 15); + Color c3 = ColorRoutines.lighten(c, 35); + Color c4 = ColorRoutines.lighten(c, 60); + imgGraphics.setColor(c4); + imgGraphics.drawLine(0, 0, 0, 5); + imgGraphics.drawLine(w - 1, 0, w - 1, 5); + imgGraphics.setColor(c3); + imgGraphics.drawLine(1, 0, 1, 5); + imgGraphics.drawLine(w - 2, 0, w - 2, 5); + imgGraphics.setColor(c2); + imgGraphics.drawLine(2, 0, 2, 5); + imgGraphics.drawLine(w - 3, 0, w - 3, 5); + imgGraphics.setColor(c); + imgGraphics.fillRect(3, 0, w - 6, 6); + // dispose of image graphics + imgGraphics.dispose(); + cache.put(key, img); + value = img; + } + int my = 0; + while (my + 6 < boxRect.height) { + g.drawImage((Image) value, 0, my, progressBar); + + my += 8; + } + g.translate(-boxRect.x, -boxRect.y); + } + + protected Color getSelectionForeground() { + return ThemeUtils.PROCESS_SELECTED_FORECOLOR; + } + + protected Color getSelectionBackground() { + return ThemeUtils.PROCESS_SELECTED_BACKCOLOR; + } + + protected void installDefaults() { + LookAndFeel.installBorder(progressBar, "ProgressBar.border"); + LookAndFeel.installColorsAndFont(progressBar, + "ProgressBar.background", "ProgressBar.foreground", "ProgressBar.font"); + } + + /* + * ProgressKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + */ + static class ProgressKey { + + private Color c; + private boolean horizontal; + private int size; + + ProgressKey(Color c, boolean horizontal, int size) { + this.c = c; + this.horizontal = horizontal; + this.size = size; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof ProgressKey)) { + return false; + } + ProgressKey other = (ProgressKey) o; + return ComparatorUtils.equals(size, other.size) && + ComparatorUtils.equals(horizontal, other.horizontal) && + ComparatorUtils.equals(c, other.c); + } + + public int hashCode() { + return c.hashCode() * (horizontal ? 1 : 2) * size; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iscrollbar/UIBasicScrollBarUI.java b/designer_base/src/com/fr/design/gui/iscrollbar/UIBasicScrollBarUI.java new file mode 100644 index 0000000000..e452b0b2e7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iscrollbar/UIBasicScrollBarUI.java @@ -0,0 +1,348 @@ +package com.fr.design.gui.iscrollbar; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollBarUI; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-17 + * Time: 上午9:58 + */ +public class UIBasicScrollBarUI extends BasicScrollBarUI { + + static final int ALPHA = 92; // 255 is full opaque + + private static final int WIDTH_GAP = 10; + + /** + * true if thumb is in rollover state + */ + protected boolean isRollover = false; + /** + * true if thumb was in rollover state + */ + protected boolean wasRollover = false; + + /** + * The free standing property of this scrollbar UI delegate. + */ + private boolean freeStanding = false; + + private int scrollBarWidth; + + public UIBasicScrollBarUI() { + } + + /** + * Installs some default values. + */ + protected void installDefaults() { + scrollBarWidth = UIScrollButton.size.width; + super.installDefaults(); + scrollbar.setBorder(null); + minimumThumbSize = new Dimension(17, 17); + } + + protected Dimension getMaximumThumbSize() { + return maximumThumbSize; + } + + /** + * 创建组件UI + * + * @param c 组件 + * @return 返回组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIBasicScrollBarUI(); + } + + /** + * Creates the decrease button of the scrollbar. + * + * @param orientation The button's orientation. + * @return The created button. + */ + protected JButton createDecreaseButton(int orientation) { + return new UIScrollButton(orientation, this); + } + + /** + * Creates the increase button of the scrollbar. + * + * @param orientation The button's orientation. + * @return The created button. + */ + protected JButton createIncreaseButton(int orientation) { + return new UIScrollButton(orientation, this); + } + + /// From MetalUI + public Dimension getPreferredSize(JComponent c) { + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + return new Dimension(scrollBarWidth, scrollBarWidth * 3 + WIDTH_GAP); + } else // Horizontal + { + return new Dimension(scrollBarWidth * 3 + WIDTH_GAP, scrollBarWidth); + } + + } + + public void paintTrack(Graphics g, JComponent c, Rectangle t) { + // borders depend on the scrollbar's style + if (isThumbVisible()) { + g.setColor(ThemeUtils.SCROLL_TRACK_COLOR); + } else { + g.setColor(ThemeUtils.SCROLL_TRACK_DISABLED_COLOR); + } + + g.fillRect(t.x, t.y, t.width, t.height); + + if (isThumbVisible()) { + g.setColor(ThemeUtils.SCROLL_TRACK_BORDER_COLOR); + } else { + g.setColor(ThemeUtils.SCROLL_TRACK_BORDER_DISABLED_COLOR); + } + + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + g.drawLine(t.x, t.y, t.x, t.y + t.height - 1); + g.drawLine(t.x + t.width - 1, t.y, t.x + t.width - 1, t.y + t.height - 1); + } else { + g.drawLine(t.x, t.y, t.x + t.width - 1, t.y); + g.drawLine(t.x, t.y + t.height - 1, t.x + t.width - 1, t.y + t.height - 1); + } + } + + + public void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { + drawXpThumb(g, thumbBounds); + } + + private void drawXpThumb(Graphics g, Rectangle t) { + Color color = null; + if (isDragging && isRollover) { + color = ThemeUtils.SCROLL_THUMB_PRESSED_COLOR; + } else if (isRollover && ThemeUtils.SCROLL_ROLLOVER) { + color = ThemeUtils.SCROLL_THUMB_ROLLOVER_COLOR; + } else { + color = ThemeUtils.SCROLL_THUMB_COLOR; + } + + g.setColor(color); + + int xs = t.x + 1; + int ys = t.y + 1; + int x2 = t.x + t.width - 1; + int y2 = t.y + t.height - 1; + + Color pressedColor = ThemeUtils.ROLLOVER_PRESSED_COLOR_8; + Color rolloverColor = ThemeUtils.ROLLOVER_PRESSED_COLOR_8; + Color normalColor = ThemeUtils.NORMAL__COLOR_8; + + switch (scrollbar.getOrientation()) { + //harry: 垂直滚动条和水平滚动条的画法分开。 + case JScrollBar.VERTICAL: + drawVertical(g, t, xs, ys, x2, pressedColor, rolloverColor, normalColor); + break; + case JScrollBar.HORIZONTAL: + drawHorizontal(g, t, xs, ys, x2, pressedColor, rolloverColor, normalColor); + break; + } + + // draw Grip +// if (t.height < 11) { +// return; +// } +// drawColorAndLength(g, t, x2, y2, color); + } + + private void drawColorAndLength(Graphics g, Rectangle t, int x2, int y2, Color color) { + + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + int y1 = t.y + (t.height) / 2 - 4; + y2 = Math.min(y1 + 8, t.y + t.height - 5); + + int y = y1; + // we take only saturation & brightness and apply them + // to the background color (normal/rollover/pressed) + g.setColor(UISBChooser.getAdjustedColor(color, 0, 71)); + while (y < y2) { + g.drawLine(5, y, 11, y); + y += 2; + } + + y = y1 + 1; + g.setColor(UISBChooser.getAdjustedColor(color, 0, -13)); + while (y < y2) { + g.drawLine(6, y, 12, y); + y += 2; + } + } else { + int x1 = t.x + (t.width) / 2 - 4; + x2 = Math.min(x1 + 8, t.x + t.width - 5); + + int x = x1 + 1; + // we take only saturation & brightness and apply them + // to the background color (normal/rollover/pressed) + g.setColor(UISBChooser.getAdjustedColor(color, 0, 71)); + while (x < x2) { + g.drawLine(x, 5, x, 11); + x += 2; + } + + x = x1; + g.setColor(UISBChooser.getAdjustedColor(color, 0, -13)); + while (x < x2) { + g.drawLine(x, 6, x, 12); + x += 2; + } + } + } + + + private void drawVertical(Graphics g, Rectangle t, int xs, int ys, int x2, + Color pressedColor, Color rolloverColor, + Color normalColor) { + Color a = ThemeUtils.SCROLL_BORDER_COLOR; + Graphics2D g2 = (Graphics2D) g; + GradientPaint scrollBarBg = null; + if (isDragging && isRollover) { + scrollBarBg = new GradientPaint(xs, ys, pressedColor, x2, ys, pressedColor); + } else if (isRollover && ThemeUtils.SCROLL_ROLLOVER) { + scrollBarBg = new GradientPaint(xs, ys, rolloverColor, x2, ys, rolloverColor); + } else { + scrollBarBg = new GradientPaint(xs, ys, normalColor, x2, ys, normalColor); + } + + g2.setPaint(scrollBarBg); + g2.fillRoundRect(xs, ys, t.width - 2, t.height - 2, 0, 0); + } + + private void drawHorizontal(Graphics g, Rectangle t, int xs, int ys, int y2, + Color pressedColor, Color rolloverColor, + Color normalColor) { + GradientPaint scrollBarBg = null; + Graphics2D g2H = (Graphics2D) g; + if (isDragging && isRollover) { + scrollBarBg = new GradientPaint(xs, ys, pressedColor, xs, y2, pressedColor); + } else if (isRollover && ThemeUtils.SCROLL_ROLLOVER) { + scrollBarBg = new GradientPaint(xs, ys, rolloverColor, xs, y2, rolloverColor); + } else { + scrollBarBg = new GradientPaint(xs, ys, normalColor, xs, y2, normalColor); + } + + g2H.setPaint(scrollBarBg); + g2H.fillRoundRect(xs, ys, t.width - 2, t.height - 2, 0, 0); + } + + /** + * 是否可见 + * + * @return 可见返回true + */ + public boolean isThumbVisible() { + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + return getThumbBounds().height > 0; + } else { + return getThumbBounds().width > 0; + } + } + + // From BasicUI + protected TrackListener createTrackListener() { + return new MyTrackListener(); + } + + /** + * Basically does BasicScrollBarUI.TrackListener the right job, it just needs + * an additional repaint and rollover management + */ + protected class MyTrackListener extends BasicScrollBarUI.TrackListener { + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + scrollbar.repaint(); + } + + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + scrollbar.repaint(); + } + + public void mouseEntered(MouseEvent e) { + isRollover = false; + wasRollover = false; + if (getThumbBounds().contains(e.getPoint())) { + isRollover = true; + wasRollover = isRollover; + scrollbar.repaint(); + } + } + + public void mouseExited(MouseEvent e) { + isRollover = false; + if (isRollover != wasRollover) { + wasRollover = isRollover; + scrollbar.repaint(); + } + } + + public void mouseDragged(MouseEvent e) { + if (getThumbBounds().contains(e.getPoint())) { + isDragging = true; + } + super.mouseDragged(e); + } + + public void mouseMoved(MouseEvent e) { + if (getThumbBounds().contains(e.getPoint())) { + isRollover = true; + if (isRollover != wasRollover) { + scrollbar.repaint(); + wasRollover = isRollover; + } + } else { + isRollover = false; + if (isRollover != wasRollover) { + scrollbar.repaint(); + wasRollover = isRollover; + } + } + } + } + + protected class OrientationChangeListener implements PropertyChangeListener { + + public void propertyChange(PropertyChangeEvent e) { + Integer orient = (Integer) e.getNewValue(); + + if (scrollbar.getComponentOrientation().isLeftToRight()) { + if (incrButton instanceof UIScrollButton) { + ((UIScrollButton) incrButton).setDirection(orient.intValue() == HORIZONTAL ? + EAST : SOUTH); + } + if (decrButton instanceof UIScrollButton) { + ((UIScrollButton) decrButton).setDirection(orient.intValue() == HORIZONTAL ? + WEST : NORTH); + } + } else { + if (incrButton instanceof UIScrollButton) { + ((UIScrollButton) incrButton).setDirection(orient.intValue() == HORIZONTAL ? + WEST : SOUTH); + } + if (decrButton instanceof UIScrollButton) { + ((UIScrollButton) decrButton).setDirection(orient.intValue() == HORIZONTAL ? + EAST : NORTH); + } + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iscrollbar/UISBChooser.java b/designer_base/src/com/fr/design/gui/iscrollbar/UISBChooser.java new file mode 100644 index 0000000000..c04722907f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iscrollbar/UISBChooser.java @@ -0,0 +1,452 @@ +package com.fr.design.gui.iscrollbar; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ColorRoutines; + +import javax.swing.*; +import javax.swing.border.EtchedBorder; +import javax.swing.border.LineBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-17 + * Time: 上午10:16 + */ +public class UISBChooser extends JDialog { + private static final int VALUE = 100; + private static final int STEP_GAP = 10; + private static final int DECREASE = 38; + private static final int INCREASE = 40; + private static UISBChooser myInstance; + private static int sat, bri; + private Color reference, outColor; + private JSlider satSlider, briSlider; + private JTextField satField, briField; + private JTextField redField, greenField, blueField; + private TwoColorField twoColorField; + private ColorField referenceField; + private boolean keyInput = false; + private boolean valueIsAdjusting = false; + + public UISBChooser(Frame frame) { + super(frame, "Saturation/Lightness", true); + setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); + + setupUI(frame); + } + + private void setupUI(Frame frame) { + ChangeListener sliderAction = new SliderAction(); + JPanel p1 = new JPanel(new BorderLayout(12, 0)); + JPanel p2 = new JPanel(new GridLayout(2, 1, 0, 8)); + JPanel p3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 4)); + JPanel p4 = new JPanel(new BorderLayout(4, 0)); + // sliders + JPanel p5 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + initOther(sliderAction); + p4.add(new JLabel("Saturation"), BorderLayout.NORTH); + p4.add(satSlider, BorderLayout.CENTER); + p5.add(satField); + p4.add(p5, BorderLayout.EAST); + p2.add(p4); + p5 = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); + p4 = new JPanel(new BorderLayout(4, 0)); + p4.add(new JLabel("Lightness"), BorderLayout.NORTH); + p4.add(briSlider, BorderLayout.CENTER); + p5.add(briField); + p4.add(p5, BorderLayout.EAST); + p2.add(p4); + p3.add(p2); + p1.add(p3, BorderLayout.CENTER); + // color panel + p2 = new JPanel(new BorderLayout(0, 6)); + p3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 4)); + twoColorField = new TwoColorField(reference); + p2.add(twoColorField, BorderLayout.NORTH); + referenceField = new ColorField(reference); + p2.add(referenceField, BorderLayout.CENTER); + p3.add(p2); + p1.add(p3, BorderLayout.EAST); + // RGB fields + initP3(p3, p1); + pack(); + Dimension size = getSize(); + setLocation(frame.getLocationOnScreen().x + + (frame.getWidth() - getSize().width) / 2, + frame.getLocationOnScreen().y + + (frame.getHeight() - getSize().height) / 2); + } + + private void initP3(JPanel p3, JPanel p1) { + p3 = new JPanel(new FlowLayout(FlowLayout.LEFT, 3, 8)); + p3.add(new JLabel("R:")); + p3.add(redField); + p3.add(new JLabel(" G:")); + p3.add(greenField); + p3.add(new JLabel(" B:")); + p3.add(blueField); + p1.add(p3, BorderLayout.SOUTH); + getContentPane().add(p1, BorderLayout.CENTER); + // buttons + p3 = new JPanel(new FlowLayout(FlowLayout.RIGHT, 12, 4)); + p3.setBorder(new EtchedBorder()); + JButton b = new JButton("Cancel"); + b.addActionListener(new CancelAction()); + p3.add(b); + b = new JButton("OK"); + getRootPane().setDefaultButton(b); + b.addActionListener(new OKAction()); + p3.add(b); + getContentPane().add(p3, BorderLayout.SOUTH); + + } + + private void initOther(ChangeListener sliderAction) { + satSlider = new JSlider(-VALUE, VALUE, sat); + satSlider.addChangeListener(sliderAction); + satSlider.setMajorTickSpacing(VALUE); + satSlider.setPaintTicks(true); + satField = new JTextField("" + satSlider.getValue(), 4); + satField.getDocument().addDocumentListener(new SatInputListener()); + satField.addKeyListener(new ArrowKeyAction(satField, -VALUE, VALUE)); + satField.setHorizontalAlignment(JTextField.CENTER); + briSlider = new JSlider(-VALUE, VALUE, bri); + briSlider.addChangeListener(sliderAction); + briSlider.setMajorTickSpacing(VALUE); + briSlider.setPaintTicks(true); + briField = new JTextField("" + briSlider.getValue(), 4); + briField.getDocument().addDocumentListener(new BriInputListener()); + briField.addKeyListener(new ArrowKeyAction(briField, -VALUE, VALUE)); + briField.setHorizontalAlignment(JTextField.CENTER); + redField = new JTextField(4); + redField.setHorizontalAlignment(JTextField.CENTER); + redField.setEditable(false); + greenField = new JTextField(4); + greenField.setHorizontalAlignment(JTextField.CENTER); + greenField.setEditable(false); + blueField = new JTextField(4); + blueField.setHorizontalAlignment(JTextField.CENTER); + blueField.setEditable(false); + } + + /** + * 显示这个Chooser + * + * @param frame 框架 + * @param ref 颜色 + * @param inColor 颜色 + * @param s int值S + * @param b 亮度 + * @return 返回颜色 + */ + public static Color showSBChooser(Frame frame, Color ref, Color inColor, int s, int b) { + if (myInstance == null) { + myInstance = new UISBChooser(frame); + } + + myInstance.setColor(ref, inColor, s, b); + myInstance.setVisible(true); + + return myInstance.outColor; + } + + /** + * 删除实例 + */ + public static void deleteInstance() { + myInstance = null; + } + + public void setColor(Color ref, Color inColor, int s, int b) { + reference = ref; + outColor = inColor; + sat = s; + bri = b; + + valueIsAdjusting = true; + satSlider.setValue(sat); + briSlider.setValue(bri); + valueIsAdjusting = false; + + referenceField.setBackground(reference); + twoColorField.setLowerColor(inColor); + adjustColor(); + } + + private void showColor(int s, int b) { + sat = s; + bri = b; + adjustColor(); + } + + private void adjustColor() { + outColor = getAdjustedColor(reference, sat, bri); + + twoColorField.setUpperColor(outColor); + } + + public static Color getAdjustedColor(Color inColor, int sat, int bri) { + Color briColor = inColor; + + // first do brightening + if (bri < 0) { + briColor = ColorRoutines.darken(inColor, -bri); + } else if (bri > 0) { + briColor = ColorRoutines.lighten(inColor, bri); + } + + // then do saturation + Color satColor = ColorRoutines.getMaxSaturation( + briColor, + ColorRoutines.getHue(inColor)); + int r, g, b; + + if (sat >= 0) { + int dr = briColor.getRed() - satColor.getRed(); + int dg = briColor.getGreen() - satColor.getGreen(); + int db = briColor.getBlue() - satColor.getBlue(); + + r = briColor.getRed() - (int) Math.round(dr * sat / VALUE * 1.0); + g = briColor.getGreen() - (int) Math.round(dg * sat / VALUE * 1.0); + b = briColor.getBlue() - (int) Math.round(db * sat / VALUE * 1.0); + } else { + float d = ColorRoutines.getGreyValue(briColor); + float dr = briColor.getRed() - d; + float dg = briColor.getGreen() - d; + float db = briColor.getBlue() - d; + + r = (int) Math.round(briColor.getRed() + dr * sat / VALUE * 1.0); + g = (int) Math.round(briColor.getGreen() + dg * sat / VALUE * 1.0); + b = (int) Math.round(briColor.getBlue() + db * sat / VALUE * 1.0); + } + + return new Color(r, g, b); + } + + public static int getSat() { + return sat; + } + + public static int getBri() { + return bri; + } + + class TwoColorField extends JPanel { + + private Dimension size = new Dimension(60, 68); + private Color upperColor, lowerColor; + + TwoColorField(Color c) { + setBorder(new LineBorder(Color.BLACK, 1)); + + upperColor = outColor; + lowerColor = c; + } + + public Dimension getPreferredSize() { + return size; + } + + void setUpperColor(Color c) { + upperColor = c; + redField.setText("" + c.getRed()); + greenField.setText("" + c.getGreen()); + blueField.setText("" + c.getBlue()); + repaint(0); + } + + void setLowerColor(Color c) { + lowerColor = c; + repaint(0); + } + + public void paint(Graphics g) { + super.paintBorder(g); + + g.setColor(upperColor); + g.fillRect(1, 1, 58, 33); + + g.setColor(lowerColor); + g.fillRect(1, 34, 58, 33); + } + } + + class ColorField extends JPanel { + + private Dimension size = new Dimension(60, 38); + + ColorField(Color c) { + setBorder(new LineBorder(Color.GRAY, 1)); + setBackground(c); + } + + public Dimension getPreferredSize() { + return size; + } + } + + class SliderAction implements ChangeListener { + + public void stateChanged(ChangeEvent e) { + if (!keyInput) { + if (ComparatorUtils.equals(e.getSource(), satSlider)) { + satField.setText("" + satSlider.getValue()); + } else { + briField.setText("" + briSlider.getValue()); + } + } + + if (valueIsAdjusting) { + return; + } + + showColor(satSlider.getValue(), briSlider.getValue()); + } + } + + class SatInputListener implements DocumentListener { + public void changedUpdate(DocumentEvent e) { + } + + public void insertUpdate(DocumentEvent e) { + update(e); + } + + public void removeUpdate(DocumentEvent e) { + update(e); + } + + private void update(DocumentEvent e) { + Document doc = e.getDocument(); + + try { + String text = doc.getText(0, doc.getLength()); + + try { + int val = Integer.parseInt(text); + + keyInput = true; + satSlider.setValue(val); + keyInput = false; + } catch (NumberFormatException ignore) { + } + } catch (BadLocationException ignore) { + } + } + } + + class BriInputListener implements DocumentListener { + public void changedUpdate(DocumentEvent e) { + } + + public void insertUpdate(DocumentEvent e) { + update(e); + } + + public void removeUpdate(DocumentEvent e) { + update(e); + } + + private void update(DocumentEvent e) { + Document doc = e.getDocument(); + + try { + String text = doc.getText(0, doc.getLength()); + + try { + int val = Integer.parseInt(text); + + keyInput = true; + briSlider.setValue(val); + keyInput = false; + } catch (NumberFormatException ignore) { + } + } catch (BadLocationException ignore) { + } + } + } + + class ArrowKeyAction extends KeyAdapter implements ActionListener { + + private JTextField theField; + private javax.swing.Timer keyTimer; + private int step, min, max; + + ArrowKeyAction(JTextField field, int min, int max) { + theField = field; + this.min = min; + this.max = max; + keyTimer = new javax.swing.Timer(20, this); + } + + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == DECREASE) { // up => decrease + step = 1; + if (e.getModifiers() == KeyEvent.SHIFT_MASK) { + step = STEP_GAP; + } + + changeVal(); + keyTimer.setInitialDelay(3 * VALUE); + keyTimer.start(); + } else if (e.getKeyCode() == INCREASE) { // up => increase + step = -1; + if (e.getModifiers() == KeyEvent.SHIFT_MASK) { + step = -STEP_GAP; + } + + changeVal(); + keyTimer.setInitialDelay(3 * VALUE); + keyTimer.start(); + } + } + + public void keyReleased(KeyEvent e) { + keyTimer.stop(); + } + + public void actionPerformed(ActionEvent e) { + changeVal(); + } + + private void changeVal() { + int val = Integer.parseInt(theField.getText()) + step; + + if (val > max) { + val = max; + } else if (val < min) { + val = min; + } + + theField.setText("" + val); + } + } + + class OKAction implements ActionListener { + + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + } + + class CancelAction implements ActionListener { + + public void actionPerformed(ActionEvent e) { + outColor = null; + setVisible(false); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBar.java b/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBar.java new file mode 100644 index 0000000000..fee92dedaa --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBar.java @@ -0,0 +1,50 @@ +package com.fr.design.gui.iscrollbar; + +import javax.swing.*; +import java.awt.*; + +/** + * UIScrollBar是没有下上的按钮的,宽为8像素 + * + * @author zhou + * @since 2012-5-9下午4:32:59 + */ +public class UIScrollBar extends JScrollBar { + + /** + * + */ + private static final long serialVersionUID = 1L; + private int temp = 10; + + public UIScrollBar(){ + } + + public UIScrollBar(int orientation) { + super(orientation); + setUI(new UIScrollBarUI()); + } + + @Override + public Dimension getPreferredSize() { + return getOrientation() == UIScrollBar.VERTICAL ? + new Dimension(10, super.getPreferredSize().height) + : new Dimension(super.getPreferredSize().width, 10); + } + + @Override + /** + * 取得宽度 + */ + public int getWidth() { + return getOrientation() == UIScrollBar.VERTICAL ? temp : super.getWidth(); + } + + @Override + /** + * 取得高度 + */ + public int getHeight() { + return getOrientation() == UIScrollBar.HORIZONTAL ? temp : super.getHeight(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBarUI.java b/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBarUI.java new file mode 100644 index 0000000000..d039e81628 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollBarUI.java @@ -0,0 +1,1333 @@ +package com.fr.design.gui.iscrollbar; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoundedRangeModel; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ScrollBarUI; +import javax.swing.plaf.UIResource; + +import com.fr.design.constants.UIConstants; +import sun.swing.DefaultLookup; + +/** + * Like BasicScrollBarUI,but without two buttons + * + * @author zhou + * @since 2012-5-18下午12:51:55 + */ +public class UIScrollBarUI extends ScrollBarUI implements LayoutManager, SwingConstants { + protected Dimension minimumThumbSize; + protected Dimension maximumThumbSize; + + protected Color thumbHighlightColor; + protected Color thumbLightShadowColor; + protected Color thumbDarkShadowColor; + protected Color thumbColor; + protected Color trackColor; + protected Color trackHighlightColor; + + protected JScrollBar scrollbar; + // protected UIButton incrButton; + // protected UIButton decrButton; + protected boolean isDragging; + protected boolean isPressing; + protected TrackListener trackListener; + protected ModelListener modelListener; + + protected Rectangle thumbRect; + protected Rectangle trackRect; + + protected int trackHighlight; + + protected static final int NO_HIGHLIGHT = 0; + protected static final int DECREASE_HIGHLIGHT = 1; + protected static final int INCREASE_HIGHLIGHT = 2; + + protected ScrollListener scrollListener; + protected PropertyChangeListener propertyChangeListener; + protected Timer scrollTimer; + + private final static int SCROLL_SPEED_THROTTLE = 60; // delay in milli seconds + + /** + * True indicates a middle click will absolutely position the scrollbar. + */ + private boolean supportsAbsolutePositioning; + + /** + * Hint as to what width (when vertical) or height (when horizontal) should + * be. + */ + private int scrollBarWidth; + + private Handler handler; + + private boolean thumbActive; + + /** + * Determine whether scrollbar layout should use cached value or adjusted + * value returned by scrollbar's getValue. + */ + private boolean useCachedValue = false; + /** + * The scrollbar value is cached to save real value if the view is adjusted. + */ + private int scrollBarValue; + + /** + * Distance between the increment button and the track. This may be a + * negative number. If negative, then an overlap between the button and + * track will occur, which is useful for shaped buttons. + *

+ * TODO This should be made protected in a feature release + */ + private int incrGap; + + /** + * Distance between the decrement button and the track. This may be a + * negative number. If negative, then an overlap between the button and + * track will occur, which is useful for shaped buttons. + *

+ * TODO This should be made protected in a feature release + */ + private int decrGap; + + /** + * @param c + * @return + */ + public static ComponentUI createUI(JComponent c) { + return new UIScrollBarUI(); + } + + protected void configureScrollBarColors() { + LookAndFeel.installColors(scrollbar, "ScrollBar.background", "ScrollBar.foreground"); + thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight"); + thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow"); + thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow"); + thumbColor = UIManager.getColor("ScrollBar.thumb"); + trackColor = UIManager.getColor("ScrollBar.track"); + trackHighlightColor = UIManager.getColor("ScrollBar.trackHighlight"); + } + + /** + * 设置UI + * + * @param c + */ + public void installUI(JComponent c) { + scrollbar = (JScrollBar) c; + thumbRect = new Rectangle(0, 0, 0, 0); + trackRect = new Rectangle(0, 0, 0, 0); + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + + /** + * 重新设置UI + * + * @param c + */ + public void uninstallUI(JComponent c) { + scrollbar = (JScrollBar) c; + uninstallListeners(); + uninstallDefaults(); + uninstallComponents(); + uninstallKeyboardActions(); + thumbRect = null; + scrollbar = null; + } + + protected void installDefaults() { + scrollBarWidth = UIManager.getInt("ScrollBar.width"); + if (scrollBarWidth <= 0) { + scrollBarWidth = 16; + } +// minimumThumbSize = (Dimension)UIManager.get("ScrollBar.minimumThumbSize"); + //滚动条的滑块的高度最小为30像素 + minimumThumbSize = new Dimension(10, 30); + maximumThumbSize = (Dimension) UIManager.get("ScrollBar.maximumThumbSize"); + + Boolean absB = (Boolean) UIManager.get("ScrollBar.allowsAbsolutePositioning"); + supportsAbsolutePositioning = (absB != null) ? absB.booleanValue() : false; + + trackHighlight = NO_HIGHLIGHT; + if (scrollbar.getLayout() == null || (scrollbar.getLayout() instanceof UIResource)) { + scrollbar.setLayout(this); + } + configureScrollBarColors(); + LookAndFeel.installBorder(scrollbar, "ScrollBar.border"); + LookAndFeel.installProperty(scrollbar, "opaque", Boolean.TRUE); + + scrollBarValue = scrollbar.getValue(); + + incrGap = UIManager.getInt("ScrollBar.incrementButtonGap"); + decrGap = UIManager.getInt("ScrollBar.decrementButtonGap"); + + // TODO this can be removed when incrGap/decrGap become protected + // handle scaling for sizeVarients for special case components. The + // key "JComponent.sizeVariant" scales for large/small/mini + // components are based on Apples LAF + String scaleKey = (String) scrollbar.getClientProperty("JComponent.sizeVariant"); + if (scaleKey != null) { + if ("large".equals(scaleKey)) { + scrollBarWidth *= 1.15; + incrGap *= 1.15; + decrGap *= 1.15; + } else if ("small".equals(scaleKey)) { + scrollBarWidth *= 0.857; + incrGap *= 0.857; + decrGap *= 0.714; + } else if ("mini".equals(scaleKey)) { + scrollBarWidth *= 0.714; + incrGap *= 0.714; + decrGap *= 0.714; + } + } + } + + protected void installComponents() { + scrollbar.setEnabled(scrollbar.isEnabled()); + } + + protected void uninstallComponents() { + } + + protected void installListeners() { + trackListener = createTrackListener(); + modelListener = createModelListener(); + propertyChangeListener = createPropertyChangeListener(); + + scrollbar.addMouseListener(trackListener); + scrollbar.addMouseMotionListener(trackListener); + scrollbar.getModel().addChangeListener(modelListener); + scrollbar.addPropertyChangeListener(propertyChangeListener); + scrollbar.addFocusListener(getHandler()); + + scrollListener = createScrollListener(); + scrollTimer = new Timer(SCROLL_SPEED_THROTTLE, scrollListener); + scrollTimer.setInitialDelay(300); // default InitialDelay? + } + + protected void installKeyboardActions() { + + InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); + SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, inputMap); + inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap); + } + + protected void uninstallKeyboardActions() { + SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, null); + SwingUtilities.replaceUIActionMap(scrollbar, null); + } + + private InputMap getInputMap(int condition) { + if (condition == JComponent.WHEN_FOCUSED) { + InputMap keyMap = (InputMap) DefaultLookup.get(scrollbar, this, "ScrollBar.focusInputMap"); + InputMap rtlKeyMap; + + if (scrollbar.getComponentOrientation().isLeftToRight() || ((rtlKeyMap = (InputMap) DefaultLookup.get(scrollbar, this, "ScrollBar.focusInputMap.RightToLeft")) == null)) { + return keyMap; + } else { + rtlKeyMap.setParent(keyMap); + return rtlKeyMap; + } + } else if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { + InputMap keyMap = (InputMap) DefaultLookup.get(scrollbar, this, "ScrollBar.ancestorInputMap"); + InputMap rtlKeyMap; + + if (scrollbar.getComponentOrientation().isLeftToRight() + || ((rtlKeyMap = (InputMap) DefaultLookup.get(scrollbar, this, "ScrollBar.ancestorInputMap.RightToLeft")) == null)) { + return keyMap; + } else { + rtlKeyMap.setParent(keyMap); + return rtlKeyMap; + } + } + return null; + } + + protected void uninstallListeners() { + scrollTimer.stop(); + scrollTimer = null; + + scrollbar.getModel().removeChangeListener(modelListener); + scrollbar.removeMouseListener(trackListener); + scrollbar.removeMouseMotionListener(trackListener); + scrollbar.removePropertyChangeListener(propertyChangeListener); + scrollbar.removeFocusListener(getHandler()); + handler = null; + } + + protected void uninstallDefaults() { + LookAndFeel.uninstallBorder(scrollbar); + if (scrollbar.getLayout() == this) { + scrollbar.setLayout(null); + } + } + + private Handler getHandler() { + if (handler == null) { + handler = new Handler(); + } + return handler; + } + + protected TrackListener createTrackListener() { + return new TrackListener(); + } + + protected ModelListener createModelListener() { + return new ModelListener(); + } + + protected ScrollListener createScrollListener() { + return new ScrollListener(); + } + + protected PropertyChangeListener createPropertyChangeListener() { + return getHandler(); + } + + private void updateThumbState(int x, int y) { + Rectangle rect = getThumbBounds(); + + setThumbRollover(rect.contains(x, y)); + } + + /** + * Sets whether or not the mouse is currently over the thumb. + * + * @param active True indicates the thumb is currently active. + * @since 1.5 + */ + protected void setThumbRollover(boolean active) { + if (thumbActive != active) { + thumbActive = active; + scrollbar.repaint(getThumbBounds()); + } + } + + /** + * Returns true if the mouse is currently over the thumb. + * + * @return true if the thumb is currently active + * @since 1.5 + */ + public boolean isThumbRollover() { + return thumbActive; + } + + /** + * 只画Thumb + */ + public void paint(Graphics g, JComponent c) { + Rectangle thumbBounds = getThumbBounds(); + if (thumbBounds.intersects(g.getClipBounds())) { + paintThumb(g, c, thumbBounds); + } + } + + /** + * A vertical scrollbar's preferred width is the maximum of preferred widths + * of the (non null) increment/decrement buttons, and the + * minimum width of the thumb. The preferred height is the sum of the + * preferred heights of the same parts. The basis for the preferred size of + * a horizontal scrollbar is similar. + *

+ * The preferredSize is only computed once, subsequent calls to + * this method just return a cached size. + * + * @param c the JScrollBar that's delegating this method to + * us + * @return the preferred size of a Basic JScrollBar + * @see #getMaximumSize + * @see #getMinimumSize + */ + public Dimension getPreferredSize(JComponent c) { + return (scrollbar.getOrientation() == JScrollBar.VERTICAL) ? new Dimension(scrollBarWidth, 48) : new Dimension(48, scrollBarWidth); + } + + /** + * @param c The JScrollBar that's delegating this method to us. + * @return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + * @see #getMinimumSize + * @see #getPreferredSize + */ + public Dimension getMaximumSize(JComponent c) { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + protected void paintDecreaseHighlight(Graphics g) { + Insets insets = scrollbar.getInsets(); + Rectangle thumbR = getThumbBounds(); + g.setColor(trackHighlightColor); + + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + // paint the distance between the start of the track and top of the + // thumb + int x = insets.left; + int y = trackRect.y; + int w = scrollbar.getWidth() - (insets.left + insets.right); + int h = thumbR.y - y; + g.fillRect(x, y, w, h); + } else { + // if left-to-right, fill the area between the start of the track + // and + // the left edge of the thumb. If right-to-left, fill the area + // between + // the end of the thumb and end of the track. + int x, w; + if (scrollbar.getComponentOrientation().isLeftToRight()) { + x = trackRect.x; + w = thumbR.x - x; + } else { + x = thumbR.x + thumbR.width; + w = trackRect.x + trackRect.width - x; + } + int y = insets.top; + int h = scrollbar.getHeight() - (insets.top + insets.bottom); + g.fillRect(x, y, w, h); + } + } + + protected void paintIncreaseHighlight(Graphics g) { + Insets insets = scrollbar.getInsets(); + Rectangle thumbR = getThumbBounds(); + g.setColor(trackHighlightColor); + + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + // fill the area between the bottom of the thumb and the end of the + // track. + int x = insets.left; + int y = thumbR.y + thumbR.height; + int w = scrollbar.getWidth() - (insets.left + insets.right); + int h = trackRect.y + trackRect.height - y; + g.fillRect(x, y, w, h); + } else { + // if left-to-right, fill the area between the right of the thumb + // and the + // end of the track. If right-to-left, then fill the area to the + // left of + // the thumb and the start of the track. + int x, w; + if (scrollbar.getComponentOrientation().isLeftToRight()) { + x = thumbR.x + thumbR.width; + w = trackRect.x + trackRect.width - x; + } else { + x = trackRect.x; + w = thumbR.x - x; + } + int y = insets.top; + int h = scrollbar.getHeight() - (insets.top + insets.bottom); + g.fillRect(x, y, w, h); + } + } + + protected void paintThumb(Graphics g, JComponent cc, Rectangle thumbBounds) { + int width = thumbBounds.width; + int height = thumbBounds.height; + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2.translate(thumbBounds.x, thumbBounds.y); + Color color = isDragging ? UIConstants.LINE_COLOR : UIConstants.BARNOMAL; + color = isPressing ? UIConstants.LINE_COLOR : UIConstants.BARNOMAL; + g2.setColor(color); + g2.fillRoundRect(1, 1, width - 2, height - 2, UIConstants.LARGEARC, UIConstants.LARGEARC); + + } + + + /** + * Return the smallest acceptable size for the thumb. If the scrollbar + * becomes so small that this size isn't available, the thumb will be + * hidden. + *

+ * Warning : the value returned by this method should not be be + * modified, it's a shared static constant. + * + * @return The smallest acceptable size for the thumb. + * @see #getMaximumThumbSize + */ + protected Dimension getMinimumThumbSize() { + return minimumThumbSize; + } + + /** + * Return the largest acceptable size for the thumb. To create a fixed size + * thumb one make this method and getMinimumThumbSize return + * the same value. + *

+ * Warning : the value returned by this method should not be be + * modified, it's a shared static constant. + * + * @return The largest acceptable size for the thumb. + * @see #getMinimumThumbSize + */ + protected Dimension getMaximumThumbSize() { + return maximumThumbSize; + } + + /* + * LayoutManager Implementation + */ + + + /** + * @param name + * @param child + */ + public void addLayoutComponent(String name, Component child) { + } + + /** + * @param child + */ + public void removeLayoutComponent(Component child) { + } + + /** + * 得到最好的布局大小 + * + * @param scrollbarContainer + * @return + */ + public Dimension preferredLayoutSize(Container scrollbarContainer) { + return getPreferredSize((JComponent) scrollbarContainer); + } + + /** + * 最小的布局大小 + * + * @param scrollbarContainer + * @return + */ + public Dimension minimumLayoutSize(Container scrollbarContainer) { + return getMinimumSize((JComponent) scrollbarContainer); + } + + private int getValue(JScrollBar sb) { + return (useCachedValue) ? scrollBarValue : sb.getValue(); + } + + + + + + /* + * Width and left edge of the buttons and thumb. + */ + + /* + * Nominal locations of the buttons, assuming their preferred size will + * fit. + */ + + /* + * The thumb must fit within the height left over after we subtract the + * preferredSize of the buttons and the insets and the gaps + */ + + /* + * Compute the height and origin of the thumb. The case where the thumb + * is at the bottom edge is handled specially to avoid numerical + * problems in computing thumbY. Enforce the thumbs min/max dimensions. + * If the thumb doesn't fit in the track (trackH) we'll hide it later. + */ + + /* + * If the buttons don't fit, allocate half of the available space to + * each and move the lower one (incrButton) down. + */ + + /* + * Update the trackRect field. + */ + + /* + * If the thumb isn't going to fit, zero it's bounds. Otherwise make + * sure it fits between the buttons. Note that setting the thumbs bounds + * will cause a repaint. + */ + + protected void layoutVScrollbar(JScrollBar sb) { + Dimension sbSize = sb.getSize(); + Insets sbInsets = sb.getInsets(); + int itemW = sbSize.width - (sbInsets.left + sbInsets.right); + int itemX = sbInsets.left; + boolean squareButtons = DefaultLookup.getBoolean(scrollbar, this, "ScrollBar.squareButtons", false); + int decrButtonH = squareButtons ? itemW : 0; + int decrButtonY = sbInsets.top; + int incrButtonH = squareButtons ? itemW : 0; + int incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH); + int sbInsetsH = sbInsets.top + sbInsets.bottom; + int sbButtonsH = decrButtonH + incrButtonH; + int gaps = decrGap + incrGap; + float trackH = sbSize.height - (sbInsetsH + sbButtonsH) - gaps; + float min = sb.getMinimum(); + float extent = sb.getVisibleAmount(); + float range = sb.getMaximum() - min; + float value = getValue(sb); + int thumbH = (range <= 0) ? getMaximumThumbSize().height : (int) (trackH * (extent / range)); + thumbH = Math.max(thumbH, getMinimumThumbSize().height); + thumbH = Math.min(thumbH, getMaximumThumbSize().height); + int thumbY = incrButtonY - incrGap - thumbH; + if (value < (sb.getMaximum() - sb.getVisibleAmount())) { + float thumbRange = trackH - thumbH; + thumbY = (int) (0.5f + (thumbRange * ((value - min) / (range - extent)))); + thumbY += decrButtonY + decrButtonH + decrGap; + } + int sbAvailButtonH = (sbSize.height - sbInsetsH); + if (sbAvailButtonH < sbButtonsH) { + incrButtonH = decrButtonH = sbAvailButtonH / 2; + incrButtonY = sbSize.height - (sbInsets.bottom + incrButtonH); + } + int itrackY = decrButtonY + decrButtonH + decrGap; + int itrackH = incrButtonY - incrGap - itrackY; + trackRect.setBounds(itemX, itrackY, itemW, itrackH); + if (thumbH >= (int) trackH) { + setThumbBounds(0, 0, 0, 0); + } else { + if ((thumbY + thumbH) > incrButtonY - incrGap) { + thumbY = incrButtonY - incrGap - thumbH; + } + if (thumbY < (decrButtonY + decrButtonH + decrGap)) { + thumbY = decrButtonY + decrButtonH + decrGap + 1; + } + setThumbBounds(itemX, thumbY, itemW, thumbH); + } + } + + + + /* + * Height and top edge of the buttons and thumb. + */ + + /* + * Nominal locations of the buttons, assuming their preferred size will + * fit. + */ + + /* + * The thumb must fit within the width left over after we subtract the + * preferredSize of the buttons and the insets and the gaps + */ + + /* + * Compute the width and origin of the thumb. Enforce the thumbs min/max + * dimensions. The case where the thumb is at the right edge is handled + * specially to avoid numerical problems in computing thumbX. If the + * thumb doesn't fit in the track (trackH) we'll hide it later. + */ + /* + * If the buttons don't fit, allocate half of the available space to + * each and move the right one over. + */ + + /* + * Update the trackRect field. + */ + /* + * Make sure the thumb fits between the buttons. Note that setting the + * thumbs bounds causes a repaint. + */ + protected void layoutHScrollbar(JScrollBar sb) { + Dimension sbSize = sb.getSize(); + Insets sbInsets = sb.getInsets(); + int itemH = sbSize.height - (sbInsets.top + sbInsets.bottom); + int itemY = sbInsets.top; + boolean ltr = sb.getComponentOrientation().isLeftToRight(); + boolean squareButtons = DefaultLookup.getBoolean(scrollbar, this, "ScrollBar.squareButtons", false); + int leftButtonW = squareButtons ? itemH : 0; + int rightButtonW = squareButtons ? itemH : 0; + if (!ltr) { + int temp = leftButtonW; + leftButtonW = rightButtonW; + rightButtonW = temp; + } + int leftButtonX = sbInsets.left; + int rightButtonX = sbSize.width - (sbInsets.right + rightButtonW); + int leftGap = ltr ? decrGap : incrGap; + int rightGap = ltr ? incrGap : decrGap; + int sbInsetsW = sbInsets.left + sbInsets.right; + int sbButtonsW = leftButtonW + rightButtonW; + float trackW = sbSize.width - (sbInsetsW + sbButtonsW) - (leftGap + rightGap); + float min = sb.getMinimum(); + float max = sb.getMaximum(); + float extent = sb.getVisibleAmount(); + float range = max - min; + float value = getValue(sb); + int thumbW = (range <= 0) ? getMaximumThumbSize().width : (int) (trackW * (extent / range)); + thumbW = Math.max(thumbW, getMinimumThumbSize().width); + thumbW = Math.min(thumbW, getMaximumThumbSize().width); + int thumbX = ltr ? rightButtonX - rightGap - thumbW : leftButtonX + leftButtonW + leftGap; + if (value < (max - sb.getVisibleAmount())) { + float thumbRange = trackW - thumbW; + if (ltr) { + thumbX = (int) (0.5f + (thumbRange * ((value - min) / (range - extent)))); + } else { + thumbX = (int) (0.5f + (thumbRange * ((max - extent - value) / (range - extent)))); + } + thumbX += leftButtonX + leftButtonW + leftGap; + } + int sbAvailButtonW = (sbSize.width - sbInsetsW); + if (sbAvailButtonW < sbButtonsW) { + rightButtonW = leftButtonW = sbAvailButtonW / 2; + rightButtonX = sbSize.width - (sbInsets.right + rightButtonW + rightGap); + } + int itrackX = leftButtonX + leftButtonW + leftGap; + int itrackW = rightButtonX - rightGap - itrackX; + trackRect.setBounds(itrackX, itemY, itrackW, itemH); + set(thumbW, thumbX, trackW, rightButtonX, rightGap, leftButtonX, leftButtonW, leftGap, itemY, itemH); + } + + private void set(int thumbW, int thumbX, float trackW, int rightButtonX, int rightGap, int leftButtonX, int leftButtonW, int leftGap, int itemY, int itemH) { + if (thumbW >= (int) trackW) { + setThumbBounds(0, 0, 0, 0); + } else { + if (thumbX + thumbW > rightButtonX - rightGap) { + thumbX = rightButtonX - rightGap - thumbW; + } + if (thumbX < leftButtonX + leftButtonW + leftGap) { + thumbX = leftButtonX + leftButtonW + leftGap + 1; + } + setThumbBounds(thumbX, itemY, thumbW, itemH); + } + } + + /** + * @param scrollbarContainer + */ + public void layoutContainer(Container scrollbarContainer) { + /* + * If the user is dragging the value, we'll assume that the scrollbars + * layout is OK modulo the thumb which is being handled by the dragging + * code. + */ + if (isDragging) { + return; + } + + JScrollBar scrollbar = (JScrollBar) scrollbarContainer; + switch (scrollbar.getOrientation()) { + case JScrollBar.VERTICAL: + layoutVScrollbar(scrollbar); + break; + + case JScrollBar.HORIZONTAL: + layoutHScrollbar(scrollbar); + break; + } + } + + /** + * Set the bounds of the thumb and force a repaint that includes the old + * thumbBounds and the new one. + * + * @see #getThumbBounds + */ + protected void setThumbBounds(int x, int y, int width, int height) { + /* + * If the thumbs bounds haven't changed, we're done. + */ + boolean isX = thumbRect.x == x; + boolean isWidth = thumbRect.width == width; + boolean isY = thumbRect.y == y; + boolean isHeight = thumbRect.height == height; + boolean istrue1 = isX && isWidth; + boolean istrue2 = isY && isHeight; + if (istrue1 && istrue2) { + return; + } + + /* + * Update thumbRect, and repaint the union of x,y,w,h and the old + * thumbRect. + */ + int minX = Math.min(x, thumbRect.x); + int minY = Math.min(y, thumbRect.y); + int maxX = Math.max(x + width, thumbRect.x + thumbRect.width); + int maxY = Math.max(y + height, thumbRect.y + thumbRect.height); + + thumbRect.setBounds(x, y, width, height); + scrollbar.repaint(minX, minY, maxX - minX, maxY - minY); + + // Once there is API to determine the mouse location this will need + // to be changed. + setThumbRollover(false); + } + + /** + * Return the current size/location of the thumb. + *

+ * Warning : the value returned by this method should not be be + * modified, it's a reference to the actual rectangle, not a copy. + * + * @return The current size/location of the thumb. + * @see #setThumbBounds + */ + protected Rectangle getThumbBounds() { + return thumbRect; + } + + /** + * Returns the current bounds of the track, i.e. the space in between the + * increment and decrement buttons, less the insets. The value returned by + * this method is updated each time the scrollbar is laid out (validated). + *

+ * Warning : the value returned by this method should not be be + * modified, it's a reference to the actual rectangle, not a copy. + * + * @return the current bounds of the scrollbar track + * @see #layoutContainer + */ + protected Rectangle getTrackBounds() { + return trackRect; + } + + /* + * Method for scrolling by a block increment. Added for mouse wheel + * scrolling support, RFE 4202656. + */ + static void scrollByBlock(JScrollBar scrollbar, int direction) { + // This method is called from BasicScrollPaneUI to implement wheel + // scrolling, and also from scrollByBlock(). + int oldValue = scrollbar.getValue(); + int blockIncrement = scrollbar.getBlockIncrement(direction); + int delta = blockIncrement * ((direction > 0) ? +1 : -1); + int newValue = oldValue + delta; + + // Check for overflow. + if (delta > 0 && newValue < oldValue) { + newValue = scrollbar.getMaximum(); + } else if (delta < 0 && newValue > oldValue) { + newValue = scrollbar.getMinimum(); + } + + scrollbar.setValue(newValue); + } + + protected void scrollByBlock(int direction) { + scrollByBlock(scrollbar, direction); + trackHighlight = direction > 0 ? INCREASE_HIGHLIGHT : DECREASE_HIGHLIGHT; + Rectangle dirtyRect = getTrackBounds(); + scrollbar.repaint(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height); + } + + /* + * Method for scrolling by a unit increment. Added for mouse wheel scrolling + * support, RFE 4202656. + * + * If limitByBlock is set to true, the scrollbar will scroll at least 1 unit + * increment, but will not scroll farther than the block increment. See + * BasicScrollPaneUI.Handler.mouseWheelMoved(). + */ + static void scrollByUnits(JScrollBar scrollbar, int direction, int units, boolean limitToBlock) { + // This method is called from BasicScrollPaneUI to implement wheel + // scrolling, as well as from scrollByUnit(). + int delta; + int limit = -1; + if (limitToBlock) { + if (direction < 0) { + limit = scrollbar.getValue() - scrollbar.getBlockIncrement(direction); + } else { + limit = scrollbar.getValue() + scrollbar.getBlockIncrement(direction); + } + } + for (int i = 0; i < units; i++) { + if (direction > 0) { + delta = scrollbar.getUnitIncrement(direction); + } else { + delta = -scrollbar.getUnitIncrement(direction); + } + int oldValue = scrollbar.getValue(); + int newValue = oldValue + delta; + // Check for overflow. + if (delta > 0 && newValue < oldValue) { + newValue = scrollbar.getMaximum(); + } else if (delta < 0 && newValue > oldValue) { + newValue = scrollbar.getMinimum(); + } + if (oldValue == newValue) { + break; + } + if (limitToBlock && i > 0) { + assert limit != -1; + boolean islow = direction < 0 && newValue < limit; + boolean isHigh = direction > 0 && newValue > limit; + if (islow && isHigh) { + break; + } + } + scrollbar.setValue(newValue); + } + } + + protected void scrollByUnit(int direction) { + scrollByUnits(scrollbar, direction, 1, false); + } + + /** + * Indicates whether the user can absolutely position the thumb with a mouse + * gesture (usually the middle mouse button). + * + * @return true if a mouse gesture can absolutely position the thumb + * @since 1.5 + */ + public boolean isSupportsAbsolutePositioning() { + return supportsAbsolutePositioning; + } + + /** + * A listener to listen for model changes. + */ + protected class ModelListener implements ChangeListener { + public void stateChanged(ChangeEvent e) { + if (!useCachedValue) { + scrollBarValue = scrollbar.getValue(); + } + layoutContainer(scrollbar); + useCachedValue = false; + } + } + + /** + * Track mouse drags. + */ + protected class TrackListener extends MouseAdapter implements MouseMotionListener { + protected transient int offset; + protected transient int currentMouseX, currentMouseY; + private transient int direction = +1; + + + public void mouseReleased(MouseEvent e) { + isPressing = false; + if (isDragging) { + updateThumbState(e.getX(), e.getY()); + } + boolean isMiddle = !isSupportsAbsolutePositioning() && SwingUtilities.isMiddleMouseButton(e); + if (SwingUtilities.isRightMouseButton(e) || isMiddle) { + return; + } + if (!scrollbar.isEnabled()) { + return; + } + Rectangle r = getTrackBounds(); + scrollbar.repaint(r.x, r.y, r.width, r.height); + + trackHighlight = NO_HIGHLIGHT; + isDragging = false; + offset = 0; + scrollTimer.stop(); + useCachedValue = true; + scrollbar.setValueIsAdjusting(false); + scrollbar.repaint(); + + } + + /** + * If the mouse is pressed above the "thumb" component then reduce the + * scrollbars value by one page ("page up"), otherwise increase it by + * one page. If there is no thumb then page up if the mouse is in the + * upper half of the track. + */ + public void mousePressed(MouseEvent e) { + boolean isMiddle = !isSupportsAbsolutePositioning() && SwingUtilities.isMiddleMouseButton(e); + if (SwingUtilities.isRightMouseButton(e) || isMiddle) { + return; + } + + if (!scrollbar.isEnabled()) { + return; + } + + isPressing = true; + if (!scrollbar.hasFocus() && scrollbar.isRequestFocusEnabled()) { + scrollbar.requestFocus(); + } + useCachedValue = true; + scrollbar.setValueIsAdjusting(true); + currentMouseX = e.getX(); + currentMouseY = e.getY(); + // Clicked in the Thumb area? + if (getThumbBounds().contains(currentMouseX, currentMouseY)) { + switch (scrollbar.getOrientation()) { + case JScrollBar.VERTICAL: + offset = currentMouseY - getThumbBounds().y; + break; + case JScrollBar.HORIZONTAL: + offset = currentMouseX - getThumbBounds().x; + break; + } + isDragging = true; + scrollbar.repaint(); + return; + } else if (isSupportsAbsolutePositioning() && SwingUtilities.isMiddleMouseButton(e)) { + switch (scrollbar.getOrientation()) { + case JScrollBar.VERTICAL: + offset = getThumbBounds().height / 2; + break; + case JScrollBar.HORIZONTAL: + offset = getThumbBounds().width / 2; + break; + } + isDragging = true; + setValueFrom(e); + scrollbar.repaint(); + return; + } + isDragging = false; + sCrollBar(); + } + + private void sCrollBar() { + Dimension sbSize = scrollbar.getSize(); + direction = +1; + switch (scrollbar.getOrientation()) { + case JScrollBar.VERTICAL: + if (getThumbBounds().isEmpty()) { + int scrollbarCenter = sbSize.height / 2; + direction = (currentMouseY < scrollbarCenter) ? -1 : +1; + } else { + int thumbY = getThumbBounds().y; + direction = (currentMouseY < thumbY) ? -1 : +1; + } + break; + case JScrollBar.HORIZONTAL: + if (getThumbBounds().isEmpty()) { + int scrollbarCenter = sbSize.width / 2; + direction = (currentMouseX < scrollbarCenter) ? -1 : +1; + } else { + int thumbX = getThumbBounds().x; + direction = (currentMouseX < thumbX) ? -1 : +1; + } + if (!scrollbar.getComponentOrientation().isLeftToRight()) { + direction = -direction; + } + break; + } + scrollByBlock(direction); + scrollTimer.stop(); + scrollListener.setDirection(direction); + scrollListener.setScrollByBlock(true); + startScrollTimerIfNecessary(); + scrollbar.repaint(); + } + + + public void mouseDragged(MouseEvent e) { + if (getThumbBounds().contains(e.getPoint())) { + isDragging = true; + } + boolean isMiddle = !isSupportsAbsolutePositioning() && SwingUtilities.isMiddleMouseButton(e); + if (SwingUtilities.isRightMouseButton(e) || isMiddle) { + return; + } + if (!scrollbar.isEnabled() || getThumbBounds().isEmpty()) { + return; + } + if (isDragging) { + setValueFrom(e); + } else { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + updateThumbState(currentMouseX, currentMouseY); + startScrollTimerIfNecessary(); + } + + scrollbar.repaint(); + } + + private void setValueFrom(MouseEvent e) { + boolean active = isThumbRollover(); + BoundedRangeModel model = scrollbar.getModel(); + Rectangle thumbR = getThumbBounds(); + int thumbMin, thumbMax, thumbPos; + + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + thumbMin = trackRect.y; + thumbMax = trackRect.y + trackRect.height - thumbR.height; + thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getY() - offset))); + setThumbBounds(thumbR.x, thumbPos, thumbR.width, thumbR.height); + } else { + thumbMin = trackRect.x; + thumbMax = trackRect.x + trackRect.width - thumbR.width; + thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e.getX() - offset))); + setThumbBounds(thumbPos, thumbR.y, thumbR.width, thumbR.height); + } + + /* + * Set the scrollbars value. If the thumb has reached the end of the + * scrollbar, then just set the value to its maximum. Otherwise + * compute the value as accurately as possible. + */ + if (thumbPos == thumbMax) { + if (scrollbar.getOrientation() == JScrollBar.VERTICAL || scrollbar.getComponentOrientation().isLeftToRight()) { + scrollbar.setValue(model.getMaximum() - model.getExtent()); + } else { + scrollbar.setValue(model.getMinimum()); + } + } else { + float valueMax = model.getMaximum() - model.getExtent(); + float valueRange = valueMax - model.getMinimum(); + float thumbValue = thumbPos - thumbMin; + float thumbRange = thumbMax - thumbMin; + int value; + if (scrollbar.getOrientation() == JScrollBar.VERTICAL || scrollbar.getComponentOrientation().isLeftToRight()) { + value = (int) (0.5 + ((thumbValue / thumbRange) * valueRange)); + } else { + value = (int) (0.5 + (((thumbMax - thumbPos) / thumbRange) * valueRange)); + } + + useCachedValue = true; + scrollBarValue = value + model.getMinimum(); + scrollbar.setValue(adjustValueIfNecessary(scrollBarValue)); + } + setThumbRollover(active); + } + + private int adjustValueIfNecessary(int value) { + if (scrollbar.getParent() instanceof JScrollPane) { + JScrollPane scrollpane = (JScrollPane) scrollbar.getParent(); + JViewport viewport = scrollpane.getViewport(); + Component view = viewport.getView(); + if (view instanceof JList) { + JList list = (JList) view; + if (DefaultLookup.getBoolean(list, list.getUI(), "List.lockToPositionOnScroll", false)) { + int adjustedValue = value; + int mode = list.getLayoutOrientation(); + int orientation = scrollbar.getOrientation(); + if (orientation == JScrollBar.VERTICAL && mode == JList.VERTICAL) { + int index = list.locationToIndex(new Point(0, value)); + Rectangle rect = list.getCellBounds(index, index); + if (rect != null) { + adjustedValue = rect.y; + } + } + if (orientation == JScrollBar.HORIZONTAL && (mode == JList.VERTICAL_WRAP || mode == JList.HORIZONTAL_WRAP)) { + if (scrollpane.getComponentOrientation().isLeftToRight()) { + int index = list.locationToIndex(new Point(value, 0)); + Rectangle rect = list.getCellBounds(index, index); + if (rect != null) { + adjustedValue = rect.x; + } + } else { + Point loc = new Point(value, 0); + int extent = viewport.getExtentSize().width; + loc.x += extent - 1; + int index = list.locationToIndex(loc); + Rectangle rect = list.getCellBounds(index, index); + if (rect != null) { + adjustedValue = rect.x + rect.width - extent; + } + } + } + value = adjustedValue; + + } + } + } + return value; + } + + private void startScrollTimerIfNecessary() { + if (scrollTimer.isRunning()) { + return; + } + + Rectangle tb = getThumbBounds(); + + switch (scrollbar.getOrientation()) { + case JScrollBar.VERTICAL: + if (direction > 0) { + if (tb.y + tb.height < trackListener.currentMouseY) { + scrollTimer.start(); + } + } else if (tb.y > trackListener.currentMouseY) { + scrollTimer.start(); + } + break; + case JScrollBar.HORIZONTAL: + boolean isAfterThumb = direction > 0 && isMouseAfterThumb(); + boolean isBeforeThumb = direction < 0 && isMouseBeforeThumb(); + if (isAfterThumb || isBeforeThumb) { + scrollTimer.start(); + } + break; + } + } + + } + + /** + * Listener for scrolling events initiated in the ScrollPane. + */ + protected class ScrollListener implements ActionListener { + int direction = +1; + boolean useBlockIncrement; + + public ScrollListener() { + direction = +1; + useBlockIncrement = false; + } + + public ScrollListener(int dir, boolean block) { + direction = dir; + useBlockIncrement = block; + } + + public void setDirection(int direction) { + this.direction = direction; + } + + public void setScrollByBlock(boolean block) { + this.useBlockIncrement = block; + } + + public void actionPerformed(ActionEvent e) { + if (useBlockIncrement) { + scrollByBlock(direction); + // Stop scrolling if the thumb catches up with the mouse + if (scrollbar.getOrientation() == JScrollBar.VERTICAL) { + if (direction > 0) { + if (getThumbBounds().y + getThumbBounds().height >= trackListener.currentMouseY) { + ((Timer) e.getSource()).stop(); + } + } else if (getThumbBounds().y <= trackListener.currentMouseY) { + ((Timer) e.getSource()).stop(); + } + } else { + boolean isAfterThumb = direction > 0 && !isMouseAfterThumb(); + boolean isBeforeThumb = direction < 0 && !isMouseBeforeThumb(); + if (isAfterThumb || isBeforeThumb) { + ((Timer) e.getSource()).stop(); + } + } + } else { + scrollByUnit(direction); + } + if (direction > 0 && scrollbar.getValue() + scrollbar.getVisibleAmount() >= scrollbar.getMaximum()) { + ((Timer) e.getSource()).stop(); + } else if (direction < 0 && scrollbar.getValue() <= scrollbar.getMinimum()) { + ((Timer) e.getSource()).stop(); + } + } + } + + private boolean isMouseLeftOfThumb() { + return trackListener.currentMouseX < getThumbBounds().x; + } + + private boolean isMouseRightOfThumb() { + Rectangle tb = getThumbBounds(); + return trackListener.currentMouseX > tb.x + tb.width; + } + + private boolean isMouseBeforeThumb() { + return scrollbar.getComponentOrientation().isLeftToRight() ? isMouseLeftOfThumb() : isMouseRightOfThumb(); + } + + private boolean isMouseAfterThumb() { + return scrollbar.getComponentOrientation().isLeftToRight() ? isMouseRightOfThumb() : isMouseLeftOfThumb(); + } + + private void updateButtonDirections() { + } + + /** + * PropertyChangeHandler + */ + public class PropertyChangeHandler implements PropertyChangeListener { + // NOTE: This class exists only for backward compatability. All + // its functionality has been moved into Handler. If you need to add + // new functionality add it to the Handler, but make sure this + // class calls into the Handler. + + /** + * @param e + */ + public void propertyChange(PropertyChangeEvent e) { + getHandler().propertyChange(e); + } + } + + // + // EventHandler + // + private class Handler implements FocusListener, PropertyChangeListener { + // + // FocusListener + // + public void focusGained(FocusEvent e) { + scrollbar.repaint(); + } + + public void focusLost(FocusEvent e) { + scrollbar.repaint(); + } + + // + // PropertyChangeAdapter + // + + /** + * @param e + */ + public void propertyChange(PropertyChangeEvent e) { + String propertyName = e.getPropertyName(); + + if ("model" == propertyName) { + BoundedRangeModel oldModel = (BoundedRangeModel) e.getOldValue(); + BoundedRangeModel newModel = (BoundedRangeModel) e.getNewValue(); + oldModel.removeChangeListener(modelListener); + newModel.addChangeListener(modelListener); + scrollbar.repaint(); + scrollbar.revalidate(); + } else if ("orientation" == propertyName) { + updateButtonDirections(); + } else if ("componentOrientation" == propertyName) { + updateButtonDirections(); + InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED); + SwingUtilities.replaceUIInputMap(scrollbar, JComponent.WHEN_FOCUSED, inputMap); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollButton.java b/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollButton.java new file mode 100644 index 0000000000..adfd759012 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/iscrollbar/UIScrollButton.java @@ -0,0 +1,236 @@ +package com.fr.design.gui.iscrollbar; + +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicArrowButton; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-17 + * Time: 上午10:00 + */ +public class UIScrollButton extends BasicArrowButton { + + // cache for already drawn icons - speeds up drawing by a factor + // of 2.2 if there are several scroll buttons or one scroll button + // is painted several times + static HashMap cache = new HashMap(); + + private boolean isRollover; + + private UIBasicScrollBarUI scrollbarUI; + + protected static Dimension size = new Dimension(17, 17); + + + /** + * Create a new ScrollButton. + * + * @see javax.swing.plaf.metal.MetalScrollButton#MetalScrollButton(int, int, boolean) + */ + public UIScrollButton(int direction, UIBasicScrollBarUI scrollbarUI) { + super(direction); + + this.scrollbarUI = scrollbarUI; + setBorder(null); + setRolloverEnabled(true); + setMargin(new Insets(0, 0, 0, 0)); + setSize(size); + } + + /** + * Paints the button + * + * @see java.awt.Component#paint(Graphics) + */ + public void paint(Graphics g) { + isRollover = false; + Color c = null; + + if (!scrollbarUI.isThumbVisible()) { + c = ThemeUtils.SCROLL_BUTTON_DISABLED_COLOR; + } else if (getModel().isPressed()) { + c = ThemeUtils.SCROLL_BUTTON_PRESSED_COLOR; + } else if (getModel().isRollover() && ThemeUtils.SCROLL_ROLLOVER) { + c = ThemeUtils.SCROLL_BUTTON_ROLLOVER_COLOR; + isRollover = true; + } else { + c = ThemeUtils.SCROLL_BUTTON_COLOR; + } + + g.setColor(c); + + drawXpButton(g, getSize(), c); + + // arrows depend on scrollbar's style + if (!scrollbarUI.isThumbVisible()) { + g.setColor(ThemeUtils.SCROLL_ARROW_DISABLED_COLOR); + } else { + g.setColor(ThemeUtils.SCROLL_ARROW_COLOR); + } + drawXpArrow(g, getSize()); + } + + private void drawXpButton(Graphics g, Dimension size, Color c) { + boolean enabled = scrollbarUI.isThumbVisible(); + boolean pressed = getModel().isPressed(); + boolean rollover = getModel().isRollover() && ThemeUtils.SCROLL_ROLLOVER; + ScrollButtonKey key = new ScrollButtonKey( + (direction == NORTH || direction == SOUTH), + c, pressed, enabled, rollover); + Object value = cache.get(key); + if (value != null) { + // image was cached - paint image and return + g.drawImage((Image) value, 0, 0, this); + return; + } + Image img = new BufferedImage(17, 17, BufferedImage.TYPE_INT_ARGB); + Graphics imgGraphics = img.getGraphics(); + switch (direction) { + case EAST: + case WEST: + case NORTH: + case SOUTH: + Color a = ThemeUtils.SCROLL_BORDER_COLOR; + Graphics2D g2 = (Graphics2D) imgGraphics; + GradientPaint scrollBarBg = null; + if (!scrollbarUI.isThumbVisible()) { + scrollBarBg = new GradientPaint(1, 1, new Color(236, 236, 236), 1, 16, c); + } else if (getModel().isPressed()) { + scrollBarBg = new GradientPaint(1, 1, new Color(0xd2d2d2), 1, 16, new Color(0xd2d2d2)); + } else if (getModel().isRollover() && ThemeUtils.SCROLL_ROLLOVER) { + scrollBarBg = new GradientPaint(1, 1, new Color(0xd2d2d2), 1, 16, new Color(0xd2d2d2)); + } else { + scrollBarBg = new GradientPaint(1, 1, new Color(0xffffff), 1, 16, new Color(0xffffff)); + } +// GradientPaint scrollBarHight = new GradientPaint(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.5f), 0, 7, new Color(1.0f, 1.0f, 1.0f, 0.2f)); + g2.setPaint(scrollBarBg); + g2.fillRoundRect(1, 1, 16, 16, 0, 0); +// g2.setPaint(scrollBarHight); +// g2.fillRoundRect(1, 1, 16, 7, 3, 3); +// g2.setColor(a); +// g2.drawRoundRect(1, 1, 15, 15, 3, 3); +// g2.setColor(new Color(240, 240, 240)); +// g2.drawRoundRect(2, 2, 13, 13, 3, 3); + break; + } + // dispose of image graphics + imgGraphics.dispose(); + // draw the image + g.drawImage(img, 0, 0, this); + // add the image to the cache + cache.put(key, img); + } + + + private void drawXpArrow(Graphics g, Dimension size) { + switch (direction) { + case SwingConstants.NORTH: + g.drawLine(8, 5, 8, 5); + g.drawLine(7, 6, 9, 6); + g.drawLine(6, 7, 10, 7); + g.drawLine(5, 8, 7, 8); + g.drawLine(9, 8, 11, 8); + g.drawLine(4, 9, 6, 9); + g.drawLine(10, 9, 12, 9); + g.drawLine(5, 10, 5, 10); + g.drawLine(11, 10, 11, 10); + break; + case SwingConstants.SOUTH: + g.drawLine(5, 6, 5, 6); + g.drawLine(11, 6, 11, 6); + g.drawLine(4, 7, 6, 7); + g.drawLine(10, 7, 12, 7); + g.drawLine(5, 8, 7, 8); + g.drawLine(9, 8, 11, 8); + g.drawLine(6, 9, 10, 9); + g.drawLine(7, 10, 9, 10); + g.drawLine(8, 11, 8, 11); + break; + case SwingConstants.EAST: + g.drawLine(6, 5, 6, 5); + g.drawLine(6, 11, 6, 11); + g.drawLine(7, 4, 7, 6); + g.drawLine(7, 10, 7, 12); + g.drawLine(8, 5, 8, 7); + g.drawLine(8, 9, 8, 11); + g.drawLine(9, 6, 9, 10); + g.drawLine(10, 7, 10, 9); + g.drawLine(11, 8, 11, 8); + break; + case SwingConstants.WEST: + g.drawLine(4, 8, 4, 8); + g.drawLine(5, 7, 5, 9); + g.drawLine(6, 6, 6, 10); + g.drawLine(7, 5, 7, 7); + g.drawLine(7, 9, 7, 11); + g.drawLine(8, 4, 8, 6); + g.drawLine(8, 10, 8, 12); + g.drawLine(9, 5, 9, 5); + g.drawLine(9, 11, 9, 11); + break; + } + } + + /** + * Returns the preferred size of the component wich is the size of the skin + * + * @see java.awt.Component#getPreferredSize() + */ + public Dimension getPreferredSize() { + return size; + } + + /* + * ScrollButtonKey is used as key in the cache HashMap. + * Overrides equals() and hashCode(). + */ + static class ScrollButtonKey { + + private boolean vertical; + private Color c; + private boolean pressed; + private boolean enabled; + private boolean rollover; + + ScrollButtonKey(boolean vertical, Color c, + boolean pressed, boolean enabled, boolean rollover) { + this.vertical = vertical; + this.c = c; + this.pressed = pressed; + this.enabled = enabled; + this.rollover = rollover; + } + + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (!(o instanceof ScrollButtonKey)) { + return false; + } + + ScrollButtonKey other = (ScrollButtonKey) o; + return ComparatorUtils.equals(vertical, other.vertical) && + ComparatorUtils.equals(pressed, other.pressed) && + ComparatorUtils.equals(enabled, other.enabled) && + ComparatorUtils.equals(rollover, other.rollover) && + ComparatorUtils.equals(c, other.c); + } + + public int hashCode() { + return c.hashCode() * + (pressed ? 1 : 2) * + (enabled ? 4 : 8) * + (rollover ? 16 : 32) * + (vertical ? 64 : 128); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/islider/UISlider.java b/designer_base/src/com/fr/design/gui/islider/UISlider.java new file mode 100644 index 0000000000..583fe9b9b0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/islider/UISlider.java @@ -0,0 +1,37 @@ +package com.fr.design.gui.islider; + +import javax.swing.*; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-3-28 + * Time: 下午1:30 + */ +public class UISlider extends JSlider { + + public UISlider(){ + super(); + } + + public UISlider(int orientation){ + super(orientation); + } + + public UISlider(int min, int max){ + super(min,max); + } + + public UISlider(int min, int max, int value){ + super(min,max,value); + } + + public UISlider(int orientation, int min, int max, int value){ + super(orientation,min,max,value); + } + + public UISlider(BoundedRangeModel brm) { + super(brm); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ispinner/UIBasicSpinner.java b/designer_base/src/com/fr/design/gui/ispinner/UIBasicSpinner.java new file mode 100644 index 0000000000..34f809fb83 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ispinner/UIBasicSpinner.java @@ -0,0 +1,86 @@ +package com.fr.design.gui.ispinner; + +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : Richer + * Version: 6.5.6 + * Date: 13-3-27 + * Time: 下午2:17 + */ +public class UIBasicSpinner extends JSpinner implements UIObserver { + + private UIObserverListener uiObserverListener; + + /** + * + * @param model + */ + public UIBasicSpinner(SpinnerModel model) { + super(model); + iniListener(); + } + + /** + * + */ + public UIBasicSpinner() { + super(); + iniListener(); + } + + + private void iniListener() { + if (shouldResponseChangeListener()) { + ((DefaultEditor) this.getEditor()).getTextField().getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + attributeChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + attributeChanged(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + attributeChanged(); + } + }); + } + + } + + + private void attributeChanged() { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + + } + + @Override + /** + * + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + @Override + /** + * + */ + public boolean shouldResponseChangeListener() { + return true; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ispinner/UISpinner.java b/designer_base/src/com/fr/design/gui/ispinner/UISpinner.java new file mode 100644 index 0000000000..2352b16a41 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ispinner/UISpinner.java @@ -0,0 +1,350 @@ +package com.fr.design.gui.ispinner; + +import java.awt.*; +import java.awt.event.*; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.JTextComponent; + +import com.fr.design.constants.UIConstants; +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.itextfield.UINumberField; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.gui.itextfield.UITextFieldUI; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class UISpinner extends JPanel implements UIObserver, GlobalNameObserver { + + protected double value; + private static final int SIZE = 20; + private static final int LEN = 13; + private UINumberField textField; + private UIButton preButton; + private UIButton nextButton; + private double minValue; + private double maxValue; + private double dierta; + private String spinnerName = ""; + private UIObserverListener uiObserverListener; + private GlobalNameListener globalNameListener = null; + + + public UISpinner(double minValue, double maxValue, double dierta) { + this.minValue = minValue; + this.maxValue = maxValue; + this.dierta = dierta; + initComponents(); + iniListener(); + } + + public UISpinner(double minValue, double maxValue, double dierta, double defaultValue) { + this(minValue, maxValue, dierta); + textField.setValue(defaultValue); + } + + private void iniListener() { + if (shouldResponseChangeListener()) { + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (uiObserverListener == null) { + return; + } + uiObserverListener.doChange(); + } + }); + } + } + + /** + * 给组件分别加上FocusListener + * @param focusListener 监听事件 + */ + public void addUISpinnerFocusListenner(FocusListener focusListener) { + this.addFocusListener(focusListener); + this.textField.addFocusListener(focusListener); + this.preButton.addFocusListener(focusListener); + this.nextButton.addFocusListener(focusListener); + + } + + public double getValue() { + return value; + } + + public void setGlobalName(String name) { + spinnerName = name; + } + + public UINumberField getTextField() { + return textField; + } + + public void setValue(double value) { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(spinnerName); + } + value = value < minValue ? minValue : value; + value = value > maxValue ? maxValue : value; + if (value == this.value) { + return; + } + this.value = value; + + textField.getDocument().removeDocumentListener(docListener); + textField.setValue(value); + textField.getDocument().addDocumentListener(docListener); + fireStateChanged(); + } + + public void setTextFieldValue(double value) { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(spinnerName); + } + value = value < minValue ? minValue : value; + value = value > maxValue ? maxValue : value; + + if (value == this.value) { + return; + } + this.value = value; + fireStateChanged(); + } + + + public void setEnabled(boolean flag) { + super.setEnabled(flag); + this.textField.setEnabled(flag); + this.preButton.setEnabled(flag); + this.nextButton.setEnabled(flag); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = SIZE; + return dim; + } + + /** + *增加 a ChangeListener to the listener list. + * @param l 监听事件 + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + *移除 a ChangeListener from the listener list. + * @param l 监听事件 + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + // august: Process the listeners last to first + protected void fireStateChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + + private void initComponents() { + textField = initNumberField(); + textField.setMaxValue(maxValue); + textField.setMinValue(minValue); + setValue(value); + textField.setUI(new SpinnerTextFieldUI(textField)); + preButton = new UIButton(UIConstants.ARROW_UP_ICON){ + public boolean shouldResponseChangeListener() { + return false; + } + }; + preButton.setRoundBorder(true, Constants.LEFT); + nextButton = new UIButton(UIConstants.ARROW_DOWN_ICON) { + public boolean shouldResponseChangeListener() { + return false; + } + }; + nextButton.setRoundBorder(true, Constants.LEFT); + setLayout(new BorderLayout()); + add(textField, BorderLayout.CENTER); + JPanel arrowPane = new JPanel(); + arrowPane.setPreferredSize(new Dimension(LEN, SIZE)); + arrowPane.setLayout(new GridLayout(2, 1)); + preButton.setBounds(0, 1, 13, 10); + nextButton.setBounds(0, 10, 13, 10); + arrowPane.add(preButton); + arrowPane.add(nextButton); + add(arrowPane, BorderLayout.EAST); + componentInitListeners(); + } + + private void componentInitListeners(){ + preButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setValue(value + dierta); + } + }); + nextButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setValue(value - dierta); + } + }); + addMouseWheelListener(new MouseWheelListener() { + + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + if (isEnabled() && e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { + setValue(value - e.getWheelRotation()); + } + } + }); + textField.getDocument().addDocumentListener(docListener); + textField.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + textField.setValue(value); + } + }); + } + + protected UINumberField initNumberField() { + return new UINumberField(2) { + public boolean shouldResponseChangeListener() { + return false; + } + }; + } + + private DocumentListener docListener = new DocumentListener() { + @Override + public void removeUpdate(DocumentEvent e) { + setTextFieldValue(textField.getValue()); + } + + @Override + public void insertUpdate(DocumentEvent e) { + setTextFieldValue(textField.getValue()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + setTextFieldValue(textField.getValue()); + } + }; + + /** + * 给组件登记一个观察者监听事件 + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * 给组件登记一个全局名字观察者监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseNameListener() { + return true; + } + + private class SpinnerTextFieldUI extends UITextFieldUI { + + public SpinnerTextFieldUI(UITextField textField) { + super(textField); + } + + @Override + public void paintBorder(Graphics2D g2d, int width, int height, + boolean isRound, int rectDirection) { + // do nothing + } + + protected void paintBackground(Graphics g) { + JTextComponent editor = getComponent(); + int width = editor.getWidth(); + int height = editor.getHeight(); + Shape oldClip = g.getClip(); + Shape roundShape = new RoundRectangle2D.Double(0, 0, width, height, UIConstants.ARC, UIConstants.ARC); + Graphics2D g2d = (Graphics2D) g; + g2d.clearRect(0, 0, width, height); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.clip(roundShape); + g2d.setColor(Color.WHITE); + g2d.fillRoundRect(1, 1, width - 2, height - 2, UIConstants.ARC, UIConstants.ARC); + if (isRollOver && isEnabled()) { + Shape shape = new RoundRectangle2D.Double(1, 1, width - 3, height - 3, UIConstants.ARC, UIConstants.ARC); + GUIPaintUtils.paintBorderShadow(g2d, 3, shape, UIConstants.HOVER_BLUE, Color.white); + } else { + g2d.setColor(UIConstants.LINE_COLOR); + g2d.drawRoundRect(1, 1, width - 2, height - 2, UIConstants.ARC, UIConstants.ARC); + g2d.clearRect(width - 2, 0, 2, height); + g2d.setClip(oldClip); + g2d.drawLine(width - 2, 1, width, 1); + g2d.drawLine(width - 2, height - 1, width, height - 1); + } + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + } + + } + + /** + * 程序入口 测试 + * @param args 参数 + */ + public static void main(String... args) { + LayoutManager layoutManager = null; + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(layoutManager); + + UISpinner bb = new UISpinner(0, 9, 1); + bb.setValue(4); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ispinner/UISpinnerButtonUI.java b/designer_base/src/com/fr/design/gui/ispinner/UISpinnerButtonUI.java new file mode 100644 index 0000000000..684614df37 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ispinner/UISpinnerButtonUI.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ispinner; + +import com.fr.design.gui.ibutton.UIBasicButtonUI; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-5 + * Time: 下午4:05 + */ +public class UISpinnerButtonUI extends UIBasicButtonUI { + private int orientation; + + protected static Dimension xpSize = new Dimension(15, 8); + + /** + * 创建UI + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + throw new IllegalStateException("Must not be used this way."); + } + + /** + * Creates a new Spinner Button. Use either SwingConstants.SOUTH or SwingConstants.NORTH + * for a SpinnerButton of Type up or a down. + * + * @param type + */ + UISpinnerButtonUI(int type) { + orientation = type; + } + + public void paint(Graphics g, JComponent c) { + AbstractButton button = (AbstractButton) c; + + if (!button.isEnabled()) { + g.setColor(ThemeUtils.SPINNER_BUTT_DISABLED_COLOR); + } else if (button.getModel().isPressed()) { + g.setColor(ThemeUtils.SPINNER_BUTT_PRESSED_COLOR); + } else if (button.getModel().isRollover()) { + g.setColor(ThemeUtils.SPINNER_BUTT_ROLLOVER_COLOR); + } else { + g.setColor(ThemeUtils.SPINNER_BUTT_COLOR); + } + + drawXpButton(g, button); + + + if (!button.isEnabled()) { + g.setColor(ThemeUtils.SPINNER_ARROW_DISABLED_COLOR); + } else { + g.setColor(ThemeUtils.SPINNER_ARROW_COLOR); + } + + drawXpArrow(g, button); + + } + + private void drawXpButton(Graphics g, AbstractButton b) { + // g.setColor(Color.RED); + // g.fillRect(0, 0, b.getWidth(), b.getHeight()); + // if(true) return; + Color borderColor = ThemeUtils.BORDER_COLOR; + Color innerColor = ThemeUtils.WHITE_BORDER_COLOR; + int h = b.getSize().height; + int w = b.getSize().width; + + boolean isEnabled = b.isEnabled(); + boolean isRollover = b.getModel().isRollover(); + boolean isPressed = b.getModel().isPressed(); + Color pressedLightColor = ThemeUtils.PRESSED_LIGHT_COLOR; + Color pressedDarkColor = ThemeUtils.PRESSED_DARK_COLOR; + Color rolloverLightColor = ThemeUtils.ROLLOVER_LIGHT_COLOR; + Color rolloverDarkColor = ThemeUtils.ROLLOVER_DARK_COLOR; + Color normalLightColor = ThemeUtils.NORMAL_LIGHT_COLOR; + Color normalDarkColor = ThemeUtils.NORMAL_DARK_COLOR; + + Graphics2D g2 = (Graphics2D) g; + GradientPaint spinnerBg = new GradientPaint(0, 0, normalLightColor, 0, h, normalDarkColor); + GradientPaint HighLight = new GradientPaint(2, 2, new Color(1.0f, 1.0f, 1.0f, 0.6f), 0, h / 2, new Color(1.0f, 1.0f, 1.0f, 0.2f)); + GradientPaint spinnerCover = new GradientPaint(0, 0, rolloverLightColor, 0, h, rolloverDarkColor); + GradientPaint spinnerPressed = new GradientPaint(0, 0, pressedLightColor, 0, h, pressedDarkColor); + g2.setPaint(spinnerBg); + g2.fillRoundRect(2, 2, w - 4, h - 4, 3, 3); + g2.setPaint(HighLight); + g2.fillRect(2, 2, w - 4, (h - 4) / 2); + g2.setColor(borderColor); + g2.drawRoundRect(0, 0, w - 1, h - 1, 3, 3); + g2.setColor(innerColor); + g2.drawRoundRect(1, 1, w - 3, h - 3, 3, 3); + + if (isRollover) { + g2.setPaint(spinnerCover); + g2.fillRoundRect(2, 2, w - 4, h - 4, 3, 3); + } else if (isPressed) { + g2.setPaint(spinnerPressed); + g2.fillRoundRect(2, 2, w - 4, h - 4, 3, 3); + } else if (!isEnabled) { + g2.setColor(ThemeUtils.SPINNER_BUTT_DISABLED_COLOR); + g2.fillRoundRect(2, 2, w - 4, h - 4, 3, 3); + } + } + + + private void drawXpArrow(Graphics g, AbstractButton b) { + int y = (b.getSize().height - 6) / 2; + + switch (orientation) { + case SwingConstants.NORTH: + y--; + g.drawLine(7, y + 2, 7, y + 2); + g.drawLine(6, y + 3, 8, y + 3); + g.drawLine(5, y + 4, 9, y + 4); + g.drawLine(4, y + 5, 6, y + 5); + g.drawLine(8, y + 5, 10, y + 5); + break; + case SwingConstants.SOUTH: + g.drawLine(4, y + 2, 6, y + 2); + g.drawLine(8, y + 2, 10, y + 2); + g.drawLine(5, y + 3, 9, y + 3); + g.drawLine(6, y + 4, 8, y + 4); + g.drawLine(7, y + 5, 7, y + 5); + break; + } + } + + /** + * @see javax.swing.plaf.basic.BasicButtonUI#getPreferredSize(javax.swing.JComponent) + */ + public Dimension getPreferredSize(JComponent c) { + return xpSize; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ispinner/UISpinnerUI.java b/designer_base/src/com/fr/design/gui/ispinner/UISpinnerUI.java new file mode 100644 index 0000000000..3a333bbf1e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ispinner/UISpinnerUI.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.ispinner; + + +import com.fr.design.gui.ibutton.SpecialUIButton; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSpinnerUI; +import javax.swing.text.InternationalFormatter; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.text.*; +import java.util.Calendar; +import java.util.Map; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-5 + * Time: 下午4:03 + */ +public class UISpinnerUI extends BasicSpinnerUI { + private static final ArrowButtonHandler NEXT_BUTTON_HANDLER = + new ArrowButtonHandler("increment", true); + private static final ArrowButtonHandler PREVIOUS_BUTTON_HANDLER = + new ArrowButtonHandler("decrement", false); + + /** + * 创建UI + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UISpinnerUI(); + } + + protected Component createPreviousButton() { + JButton b = new SpecialUIButton(new UISpinnerButtonUI(SwingConstants.SOUTH)); + + b.putClientProperty("isSpinnerButton", Boolean.TRUE); + b.setFocusable(false); + b.addActionListener(PREVIOUS_BUTTON_HANDLER); + b.addMouseListener(PREVIOUS_BUTTON_HANDLER); + + return b; + } + + protected Component createNextButton() { + JButton b = new SpecialUIButton(new UISpinnerButtonUI(SwingConstants.NORTH)); + + b.putClientProperty("isSpinnerButton", Boolean.TRUE); + b.setFocusable(false); + b.addActionListener(NEXT_BUTTON_HANDLER); + b.addMouseListener(NEXT_BUTTON_HANDLER); + + return b; + } + + /** + * Copy and paste from BasicSpinnerUI - sigh ! + *

+ *

+ * A handler for spinner arrow button mouse and action events. When + * a left mouse pressed event occurs we look up the (enabled) spinner + * that's the source of the event and start the autorepeat timer. The + * timer fires action events until any button is released at which + * point the timer is stopped and the reference to the spinner cleared. + * The timer doesn't start until after a 300ms delay, so often the + * source of the initial (and final) action event is just the button + * logic for mouse released - which means that we're relying on the fact + * that our mouse listener runs after the buttons mouse listener. + *

+ * Note that one instance of this handler is shared by all slider previous + * arrow buttons and likewise for all of the next buttons, + * so it doesn't have any state that persists beyond the limits + * of a single button pressed/released gesture. + */ + private static class ArrowButtonHandler extends AbstractAction implements MouseListener { + final javax.swing.Timer autoRepeatTimer; + final boolean isNext; + JSpinner spinner = null; + + ArrowButtonHandler(String name, boolean isNext) { + super(name); + this.isNext = isNext; + autoRepeatTimer = new javax.swing.Timer(20, this); + autoRepeatTimer.setInitialDelay(300); + } + + private JSpinner eventToSpinner(AWTEvent e) { + Object src = e.getSource(); + + while ((src instanceof Component) && !(src instanceof JSpinner)) { + src = ((Component) src).getParent(); + } + return (src instanceof JSpinner) ? (JSpinner) src : null; + } + + public void actionPerformed(ActionEvent e) { + JSpinner spinner = this.spinner; + + if (!(e.getSource() instanceof javax.swing.Timer)) { + // Most likely resulting from being in ActionMap. + spinner = eventToSpinner(e); + } + + if (spinner != null) { + try { + int calendarField = getCalendarField(spinner); + spinner.commitEdit(); + + if (calendarField != -1) { + ((SpinnerDateModel) spinner.getModel()).setCalendarField(calendarField); + } + + Object value = isNext ? spinner.getNextValue() : + spinner.getPreviousValue(); + if (value != null) { + spinner.setValue(value); + select(spinner); + } + } catch (IllegalArgumentException iae) { + UIManager.getLookAndFeel().provideErrorFeedback(spinner); + } catch (ParseException pe) { + UIManager.getLookAndFeel().provideErrorFeedback(spinner); + } + } + } + + /** + * If the spinner's editor is a DateEditor, this selects the field + * associated with the value that is being incremented. + */ + private void select(JSpinner spinner) { + JComponent editor = spinner.getEditor(); + + if (editor instanceof JSpinner.DateEditor) { + JSpinner.DateEditor dateEditor = (JSpinner.DateEditor) editor; + JFormattedTextField ftf = dateEditor.getTextField(); + Format format = dateEditor.getFormat(); + Object value; + + if (format != null && (value = spinner.getValue()) != null) { + SpinnerDateModel model = dateEditor.getModel(); + DateFormat.Field field = DateFormat.Field.ofCalendarField(model.getCalendarField()); + + if (field != null) { + try { + AttributedCharacterIterator iterator = format.formatToCharacterIterator(value); + if (!select(ftf, iterator, field) && field == DateFormat.Field.HOUR0) { + select(ftf, iterator, DateFormat.Field.HOUR1); + } + } catch (IllegalArgumentException iae) { + } + } + } + } + } + + /** + * Selects the passed in field, returning true if it is found, + * false otherwise. + */ + private boolean select(JFormattedTextField ftf, + AttributedCharacterIterator iterator, DateFormat.Field field) { + int max = ftf.getDocument().getLength(); + + iterator.first(); + do { + Map attrs = iterator.getAttributes(); + + if (attrs != null && attrs.containsKey(field)) { + int start = iterator.getRunStart(field); + int end = iterator.getRunLimit(field); + + if (start != -1 && end != -1 && start <= max && end <= max) { + ftf.select(start, end); + } + return true; + } + } while (iterator.next() != CharacterIterator.DONE); + return false; + } + + /** + * Returns the calendarField under the start of the selection, or + * -1 if there is no valid calendar field under the selection (or + * the spinner isn't editing dates. + */ + private int getCalendarField(JSpinner spinner) { + JComponent editor = spinner.getEditor(); + + if (editor instanceof JSpinner.DateEditor) { + JSpinner.DateEditor dateEditor = (JSpinner.DateEditor) editor; + JFormattedTextField ftf = dateEditor.getTextField(); + int start = ftf.getSelectionStart(); + JFormattedTextField.AbstractFormatter formatter = ftf.getFormatter(); + + if (formatter instanceof InternationalFormatter) { + Format.Field[] fields = ((InternationalFormatter) formatter).getFields(start); + + for (int counter = 0; counter < fields.length; counter++) { + if (fields[counter] instanceof DateFormat.Field) { + int calendarField; + + if (fields[counter] == DateFormat.Field.HOUR1) { + calendarField = Calendar.HOUR; + } else { + calendarField = ((DateFormat.Field) fields[counter]).getCalendarField(); + } + if (calendarField != -1) { + return calendarField; + } + } + } + } + } + + return -1; + } + + public void mousePressed(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e) && e.getComponent().isEnabled()) { + spinner = eventToSpinner(e); + autoRepeatTimer.start(); + + focusSpinnerIfNecessary(); + } + } + + public void mouseReleased(MouseEvent e) { + autoRepeatTimer.stop(); + spinner = null; + } + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + /** + * Requests focus on a child of the spinner if the spinner doesn't + * have focus. + */ + private void focusSpinnerIfNecessary() { + Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + if (spinner.isRequestFocusEnabled() && (fo == null || !SwingUtilities.isDescendingFrom(fo, spinner))) { + Container root = spinner; + + if (!root.isFocusCycleRoot()) { + root = root.getFocusCycleRootAncestor(); + } + if (root != null) { + FocusTraversalPolicy ftp = root.getFocusTraversalPolicy(); + Component child = ftp.getComponentAfter(root, spinner); + + if (child != null && SwingUtilities.isDescendingFrom(child, spinner)) { + child.requestFocus(); + } + } + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/ispinner/UpperCaseSpinner.java b/designer_base/src/com/fr/design/gui/ispinner/UpperCaseSpinner.java new file mode 100644 index 0000000000..1fb5b45b9b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/ispinner/UpperCaseSpinner.java @@ -0,0 +1,132 @@ +package com.fr.design.gui.ispinner; + +import java.text.ParseException; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.JFormattedTextField; +import javax.swing.JSpinner; +import javax.swing.SpinnerDateModel; +import javax.swing.SpinnerListModel; +import javax.swing.SpinnerModel; +import javax.swing.SpinnerNumberModel; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.DocumentFilter; + +import com.fr.stable.StableUtils; + +//_denny: 实在是没有办法处理让Spinner,小写转大写。这个UpperCaseSpinner在其他地方最好不要用 +public class UpperCaseSpinner extends UIBasicSpinner { + public UpperCaseSpinner(SpinnerModel model) { + super(model); + } + + protected JComponent createEditor(SpinnerModel model) { + if (model instanceof SpinnerDateModel) { + return new DateEditor(this); + } else if (model instanceof SpinnerListModel) { + return new UpperCaseEditor(this); + } else if (model instanceof SpinnerNumberModel) { + return new NumberEditor(this); + } else { + return new DefaultEditor(this); + } + } + + private class UpperCaseEditor extends DefaultEditor { + public UpperCaseEditor(JSpinner spinner) { + super(spinner); + if (!(spinner.getModel() instanceof SpinnerListModel)) { + throw new IllegalArgumentException( + "model not a SpinnerListModel"); + } + getTextField().setEditable(true); + getTextField().setFormatterFactory( + new DefaultFormatterFactory(new ListFormatter())); + } + + public SpinnerListModel getModel() { + return (SpinnerListModel) (getSpinner().getModel()); + } + + private class ListFormatter extends + JFormattedTextField.AbstractFormatter { + private DocumentFilter filter; + + public String valueToString(Object value) throws ParseException { + if (value == null) { + return ""; + } + return value.toString(); + } + + public Object stringToValue(String string) + throws ParseException { + //add将行数转换成ABC + try { + int num = Integer.parseInt(string); + if (num > 0) { + string = StableUtils.convertIntToABC(num); + } + } catch (Exception e) { + //do nothing string is string again + } + return string; + } + + protected DocumentFilter getDocumentFilter() { + if (filter == null) { + filter = new Filter(); + } + return filter; + } + + private class Filter extends DocumentFilter { + public void replace(FilterBypass fb, int offset, + int length, String string, AttributeSet attrs) + throws BadLocationException { + string = string.toUpperCase(); + if (string != null + && (offset + length) == fb.getDocument() + .getLength()) { + List list = getModel().getList(); + Object next = null; + for (int counter = 0; counter < list.size(); counter++) { + Object value = list.get(counter); + String str = value.toString(); + + if (str != null + && str.startsWith(fb.getDocument() + .getText(0, offset) + + string)) { + next = value; + break; + } + } + + String value = (next != null) ? next.toString() + : null; + + if (value != null) { + fb.remove(0, offset + length); + fb.insertString(0, value, null); + getFormattedTextField().select( + offset + string.length(), + value.length()); + return; + } + } + super.replace(fb, offset, length, string, attrs); + } + + public void insertString(FilterBypass fb, int offset, + String string, AttributeSet attr) + throws BadLocationException { + replace(fb, offset, 0, string, attr); + } + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneDivider.java b/designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneDivider.java new file mode 100644 index 0000000000..e4da4eedb1 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneDivider.java @@ -0,0 +1,275 @@ +package com.fr.design.gui.isplitpanedivider; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-12 + * Time: 下午4:50 + */ +public class UISplitPaneDivider extends BasicSplitPaneDivider { + + private static final int BOUND5 = 5; + + private int inset = 2; + private Color controlColor = MetalLookAndFeel.getControl(); + private Color primaryControlColor = MetalLookAndFeel.getPrimaryControl(); + + public UISplitPaneDivider(BasicSplitPaneUI ui) { + super(ui); + setLayout(new MetalDividerLayout()); + } + + public void paint(Graphics g) { + g.setColor(controlColor); + + Rectangle clip = g.getClipBounds(); + Insets insets = getInsets(); + g.fillRect(clip.x, clip.y, clip.width, clip.height); + Dimension size = getSize(); + size.width -= inset * 2; + size.height -= inset * 2; + int drawX = inset; + int drawY = inset; + + if (insets != null) { + size.width -= (insets.left + insets.right); + size.height -= (insets.top + insets.bottom); + drawX += insets.left; + drawY += insets.top; + } + + super.paint(g); + } + + /** + * Creates and return an instance of JButton that can be used to + * collapse the left component in the metal split pane. + */ + protected JButton createLeftOneTouchButton() { + JButton b = new JButton() { + public void setBorder(Border b) { + } + + public void paint(Graphics g) { + JSplitPane splitPane = getSplitPaneFromSuper(); + + // changed this in 1.3 + if (splitPane != null) { + int oneTouchSize = getOneTouchSizeFromSuper(); + int orientation = getOrientationFromSuper(); + + // Fill the background first ... + g.setColor(ThemeUtils.BACK_COLOR); + g.fillRect(0, 0, this.getWidth(), this.getHeight()); + + // use scrollArrowColor as button color + g.setColor(ThemeUtils.SCROLL_ARROW_COLOR); + + if (orientation == JSplitPane.VERTICAL_SPLIT) { + g.drawLine(2, 1, 3, 1); + g.drawLine(1, 2, 4, 2); + g.drawLine(0, 3, 5, 3); + } else { + // HORIZONTAL_SPLIT + g.drawLine(1, 2, 1, 3); + g.drawLine(2, 1, 2, 4); + g.drawLine(3, 0, 3, 5); + } + } + } + + // Don't want the button to participate in focus traversable. + public boolean isFocusTraversable() { + return false; + } + }; + b.setRequestFocusEnabled(false); + b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + b.setFocusPainted(false); + b.setBorderPainted(false); + return b; + } + + /** + * Creates and return an instance of JButton that can be used to + * collapse the right component in the metal split pane. + */ + protected JButton createRightOneTouchButton() { + JButton b = new JButton() { + public void setBorder(Border border) { + } + + public void paint(Graphics g) { + JSplitPane splitPane = getSplitPaneFromSuper(); + + // changed this in 1.3 + if (splitPane != null) { + int oneTouchSize = getOneTouchSizeFromSuper(); + int orientation = getOrientationFromSuper(); + + // Fill the background first ... + g.setColor(ThemeUtils.BACK_COLOR); + g.fillRect(0, 0, this.getWidth(), this.getHeight()); + + // use scrollArrowColor as button color + g.setColor(ThemeUtils.SCROLL_ARROW_COLOR); + + if (orientation == JSplitPane.VERTICAL_SPLIT) { + g.drawLine(2, 3, 3, 3); + g.drawLine(1, 2, 4, 2); + g.drawLine(0, 1, 5, 1); + } else { + // HORIZONTAL_SPLIT + g.drawLine(3, 2, 3, 3); + g.drawLine(2, 1, 2, 4); + g.drawLine(1, 0, 1, 5); + } + } + } + + // Don't want the button to participate in focus traversable. + public boolean isFocusTraversable() { + return false; + } + }; + + b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + b.setFocusPainted(false); + b.setBorderPainted(false); + b.setRequestFocusEnabled(false); + return b; + } + + /** + * Used to layout a TinySplitPaneDivider. Layout for the divider + * involves appropriately moving the left/right buttons around. + *

+ * This inner class is marked "public" due to a compiler bug. + * This class should be treated as a "protected" inner class. + * Instantiate it only within subclasses of TinySplitPaneDivider. + */ + public class MetalDividerLayout implements LayoutManager { + /** + * 布局 + * + * @param c 容器 + */ + public void layoutContainer(Container c) { + JButton leftButton = getLeftButtonFromSuper(); + JButton rightButton = getRightButtonFromSuper(); + JSplitPane splitPane = getSplitPaneFromSuper(); + int orientation = getOrientationFromSuper(); + int oneTouchSize = getOneTouchSizeFromSuper(); + int oneTouchOffset = getOneTouchOffsetFromSuper(); + Insets insets = getInsets(); + + // This layout differs from the one used in BasicSplitPaneDivider. + // It does not center justify the oneTouchExpadable buttons. + // This was necessary in order to meet the spec of the Metal + // splitpane divider. + if (leftButton != null && rightButton != null && c == UISplitPaneDivider.this) { + if (splitPane.isOneTouchExpandable()) { + if (orientation == JSplitPane.VERTICAL_SPLIT) { + int extraY = (insets != null) ? insets.top : 0; + int blockSize = getDividerSize(); + + if (insets != null) { + blockSize -= (insets.top + insets.bottom); + } + blockSize = Math.min(blockSize, oneTouchSize); + leftButton.setBounds(oneTouchOffset, extraY, blockSize * 2, blockSize); + rightButton.setBounds(oneTouchOffset + oneTouchSize * 2, extraY, blockSize * 2, blockSize); + } else { + int blockSize = getDividerSize(); + int extraX = (insets != null) ? insets.left : 0; + + if (insets != null) { + blockSize -= (insets.left + insets.right); + } + blockSize = Math.min(blockSize, oneTouchSize); + leftButton.setBounds(extraX, oneTouchOffset, blockSize, blockSize * 2); + rightButton.setBounds(extraX, oneTouchOffset + oneTouchSize * 2, blockSize, blockSize * 2); + } + } else { + leftButton.setBounds(-BOUND5, -BOUND5, 1, 1); + rightButton.setBounds(-BOUND5, -BOUND5, 1, 1); + } + } + } + + /** + * 最小布局 + * + * @param c 容器 + * @return 最小 + */ + public Dimension minimumLayoutSize(Container c) { + return new Dimension(0, 0); + } + + /** + *合适的布局大小 + * @param c 容器 + * @return 大小 + */ + public Dimension preferredLayoutSize(Container c) { + return new Dimension(0, 0); + } + + /** + * 去掉布局组件 + * @param c 组件 + */ + public void removeLayoutComponent(Component c) { + } + + /** + * 增加布局组件 + * @param string 名字 + * @param c 组件 + */ + public void addLayoutComponent(String string, Component c) { + } + } + + /* + * The following methods only exist in order to be able to access protected + * members in the superclass, because these are otherwise not available + * in any inner class. + */ + + int getOneTouchSizeFromSuper() { + return super.ONE_TOUCH_SIZE; + } + + int getOneTouchOffsetFromSuper() { + return super.ONE_TOUCH_OFFSET; + } + + int getOrientationFromSuper() { + return super.orientation; + } + + JSplitPane getSplitPaneFromSuper() { + return super.splitPane; + } + + JButton getLeftButtonFromSuper() { + return super.leftButton; + } + + JButton getRightButtonFromSuper() { + return super.rightButton; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneUI.java b/designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneUI.java new file mode 100644 index 0000000000..554413d405 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/isplitpanedivider/UISplitPaneUI.java @@ -0,0 +1,33 @@ +package com.fr.design.gui.isplitpanedivider; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.metal.MetalSplitPaneUI; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-12 + * Time: 下午4:59 + */ +public class UISplitPaneUI extends MetalSplitPaneUI { + + /** + * 创建UI + * @param x 组件 + * @return 返回组件UI + */ + public static ComponentUI createUI(JComponent x) { + return new UISplitPaneUI(); + } + + /** + * 创建Divider + * @return 返回默认的divider + */ + public BasicSplitPaneDivider createDefaultDivider() { + return new UISplitPaneDivider(this); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/AbstractPropertyTable.java b/designer_base/src/com/fr/design/gui/itable/AbstractPropertyTable.java new file mode 100644 index 0000000000..f16be99639 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/AbstractPropertyTable.java @@ -0,0 +1,248 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.itable; + +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableModel; + +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; + +/** + * @author richer + * @since 6.5.3 + */ +public abstract class AbstractPropertyTable extends JTable { + + // 属性分组 + protected ArrayList groups; + protected TableModel default_table_model; + // 属性表被选中的行加一个浅蓝色的背景 + public static final Color PROPERTY_SELECTION_BACKGROUND = new Color(153, 204, 255); + // 属性表的行高 + public static final int PROPERTY_TABLE_ROW_HEIGHT = 22; + + public AbstractPropertyTable() { + this.setRowHeight(PROPERTY_TABLE_ROW_HEIGHT); + JTableHeader header = getTableHeader(); + header.setReorderingAllowed(false); + header.setPreferredSize(new Dimension(0, PROPERTY_TABLE_ROW_HEIGHT)); + header.setDefaultRenderer(new HeaderRenderer()); + this.setGridColor(new Color(212, 208, 200)); + this.setSelectionBackground(PROPERTY_SELECTION_BACKGROUND); + this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + this.setColumnSelectionAllowed(false); + this.setRowSelectionAllowed(true); + this.setFillsViewportHeight(true); + this.initPopup(); + default_table_model = new DefaultTableModel(); + this.setModel(default_table_model); + this.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + } + + public abstract void initPropertyGroups(Object source); + + public void fireValueChanged(Object old_value, boolean success, Object newValue) { + if (success && !ComparatorUtils.equals(old_value, newValue)) { + firePropertyEdit(); + } + } + + public abstract void firePropertyEdit(); + + @Override + public TableCellRenderer getCellRenderer(int row, int column) { + if (groups != null) { + Point pIndex = getGroupIndex(row); + PropertyGroup group = groups.get(pIndex.x); + if (pIndex.y == 0) { + if (column == 0) { + return group.getFirstRenderer(); + } else { + return group.getSecondRenderer(); + } + } else { + if (column == 0) { + return super.getCellRenderer(row, column); + } else { + TableCellRenderer renderer = group.getModel().getRenderer(pIndex.y - 1); + if (renderer instanceof Component) { + ((Component) renderer).setEnabled(isCellEditable(row, column)); + } + return renderer; + } + } + } else { + return super.getCellRenderer(row, column); + } + } + + public String getToolTipText(MouseEvent event) { + return null; + } + + @Override + public TableCellEditor getCellEditor(int row, int column) { + if (groups != null) { + Point pIndex = getGroupIndex(row); + PropertyGroup group = groups.get(pIndex.x); + if (pIndex.y == 0) { + return super.getCellEditor(row, column); + } else { + if (column == 0) { + return super.getCellEditor(row, column); + } else { + return group.getModel().getEditor(pIndex.y - 1); + } + } + } else { + return super.getCellEditor(row, column); + } + } + + private Point getGroupIndex(int row) { + int count = 0; + for (int i = 0; i < groups.size(); i++) { + PropertyGroup group = groups.get(i); + int groupRowCount = 1; + if (!group.isCollapsed()) { + groupRowCount += group.getModel().getRowCount(); + } + if (count + groupRowCount > row) { + return new Point(i, row - count); + } + count += groupRowCount; + } + return null; + } + + private void initPopup() { + + this.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + if (!e.isPopupTrigger() && groups != null) { + int row = AbstractPropertyTable.super.rowAtPoint(e.getPoint()); + if (row != -1) { + Point pIndex = getGroupIndex(row); + if (pIndex.y == 0 && e.getClickCount() > 1) { + toggleCollapse(pIndex.x); + } + } + } + } + + @Override + public void mousePressed(MouseEvent e) { + if (!e.isPopupTrigger() && groups != null) { + int row = AbstractPropertyTable.super.rowAtPoint(e.getPoint()); + if (row != -1) { + Point pIndex = getGroupIndex(row); + if (pIndex.y == 0 && e.getClickCount() == 1 && e.getX() < 10) { + toggleCollapse(pIndex.x); + } + } + } + } + }); + } + + private void toggleCollapse(int groupIndex) { + PropertyGroup group = groups.get(groupIndex); + group.setCollapsed(!group.isCollapsed()); + Container parent = AbstractPropertyTable.this.getParent(); + if (parent != null) { + parent.doLayout(); + } + repaint(); + } + + public class BeanTableModel extends AbstractTableModel { + + @Override + public int getRowCount() { + int row = 0; + for (PropertyGroup group : groups) { + row++; + if (!group.isCollapsed()) { + row += group.getModel().getRowCount(); + } + } + return row; + } + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public Object getValueAt(int row, int column) { + Point pIndex = getGroupIndex(row); + PropertyGroup group = groups.get(pIndex.x); + if (pIndex.y == 0) { + if (column == 0) { + return (group.isCollapsed() ? "+" : "-") + group.getName(); + } else { + return null; + } + } else { + Object value = group.getModel().getValue(pIndex.y - 1, column); + if (column == 0) { + value = " " + value; + } + return value; + } + } + + @Override + public String getColumnName(int column) { + if (column == 0) { + return Inter.getLocText("Form-Widget_Property"); + } else { + return Inter.getLocText("Form-Widget_Property_Value"); + } + } + + @Override + public void setValueAt(Object aValue, int row, int column) { + Point pIndex = getGroupIndex(row); + PropertyGroup group = groups.get(pIndex.x); + if (pIndex.y != 0) { + Object old_value = getValueAt(row, column); + boolean success = group.getModel().setValue(aValue, pIndex.y - 1, column); + fireValueChanged(old_value, success, aValue); + } else { + group.setCollapsed((Boolean) aValue); + } + } + + @Override + public boolean isCellEditable(int row, int column) { + Point pIndex = getGroupIndex(row); + PropertyGroup group = groups.get(pIndex.x); + if (pIndex.y == 0) { + if (column == 0) { + return false; + } else { + return false; + } + } else { + return column == 1 && group.getModel().isEditable(pIndex.y - 1); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/GroupRenderer.java b/designer_base/src/com/fr/design/gui/itable/GroupRenderer.java new file mode 100644 index 0000000000..87561eb648 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/GroupRenderer.java @@ -0,0 +1,50 @@ +package com.fr.design.gui.itable; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JTable; +import javax.swing.table.DefaultTableCellRenderer; + +import com.fr.base.BaseUtils; +import com.fr.stable.StringUtils; + +public class GroupRenderer extends DefaultTableCellRenderer { + + private static final Icon PLUS_ICON = new ImageIcon(BaseUtils.readImage("com/fr/design/images/form/designer/properties/plus.png")); + private static final Icon MINUS_ICON = new ImageIcon(BaseUtils.readImage("com/fr/design/images/form/designer/properties/minus.png")); + + public GroupRenderer() { + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + super.getTableCellRendererComponent(table, value, isSelected, false, row, column); + String text = getText(); + if (StringUtils.isNotBlank(text)) { + if (text.length() > 0 && text.charAt(0) == '+') { + setIcon(PLUS_ICON); + setText(text.substring(1)); + } else if (text.length() > 0 && text.charAt(0) == '-') { + setIcon(MINUS_ICON); + setText(text.substring(1)); + } else { + setIcon(null); + setText(text); + } + } else { + setIcon(null); + setText(text); + } + if (isSelected) { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } else { + setBackground(table.getGridColor()); + setForeground(Color.black); + } + return this; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/HeaderRenderer.java b/designer_base/src/com/fr/design/gui/itable/HeaderRenderer.java new file mode 100644 index 0000000000..87e742c1a6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/HeaderRenderer.java @@ -0,0 +1,60 @@ +package com.fr.design.gui.itable; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + +import javax.swing.JTable; +import javax.swing.border.Border; + +public class HeaderRenderer extends GroupRenderer { + + private static final Color GRID__COLOR = new Color(127, 157, 185); + private static final Color CONTROL_COLOR = new Color(229, 229, 229); + private HeaderBorder border = new HeaderBorder(); + + public HeaderRenderer() { + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + super.getTableCellRendererComponent(table, value, isSelected, false, row, column); + border.setGridColor(GRID__COLOR); + setBackground(CONTROL_COLOR); + setText(" " + value); + setBorder(border); + return this; + } + + private class HeaderBorder implements Border { + + private Color grid_color; + + public HeaderBorder() { + } + + public void setGridColor(Color c) { + grid_color = c; + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Color old = g.getColor(); + g.setColor(grid_color); + g.drawLine(x + width - 1, y, x + width - 1, y + height); + g.drawLine(x, y + height - 1, x + width, y + height - 1); + g.setColor(old); + } + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(0, 0, 1, 1); + } + + @Override + public boolean isBorderOpaque() { + return true; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/PropertyGroup.java b/designer_base/src/com/fr/design/gui/itable/PropertyGroup.java new file mode 100644 index 0000000000..f66288e391 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/PropertyGroup.java @@ -0,0 +1,58 @@ +package com.fr.design.gui.itable; + +import javax.swing.table.TableCellRenderer; + +import com.fr.design.beans.GroupModel; + +public class PropertyGroup { + + private GroupModel model; + private String name; + private boolean collapsed; + private GroupRenderer renderer1; + private GroupRenderer renderer2; + + public PropertyGroup(GroupModel model) { + this(model.getGroupName(), model, false); + renderer1 = new GroupRenderer(); + renderer2 = new GroupRenderer(); + } + + public PropertyGroup(String name, GroupModel model, boolean collapsed) { + this.name = name; + this.model = model; + this.collapsed = collapsed; + } + + public GroupModel getModel() { + return model; + } + + public void setModel(GroupModel model) { + this.model = model; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isCollapsed() { + return collapsed; + } + + public void setCollapsed(boolean collapsed) { + this.collapsed = collapsed; + } + + public TableCellRenderer getFirstRenderer() { + return renderer1; + } + + public TableCellRenderer getSecondRenderer() { + return renderer2; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/SortableJTable.java b/designer_base/src/com/fr/design/gui/itable/SortableJTable.java new file mode 100644 index 0000000000..03fd1691b4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/SortableJTable.java @@ -0,0 +1,10 @@ +package com.fr.design.gui.itable; + +import javax.swing.JTable; + +public class SortableJTable extends JTable{ + public SortableJTable(TableSorter tableModel){ + super(tableModel); + tableModel.setTableHeader(getTableHeader()); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/TableSorter.java b/designer_base/src/com/fr/design/gui/itable/TableSorter.java new file mode 100644 index 0000000000..0ea84af03d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/TableSorter.java @@ -0,0 +1,498 @@ +package com.fr.design.gui.itable; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.Icon; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JTable; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; + +/** + * TableSorter is a decorator for TableModels; adding sorting + * functionality to a supplied TableModel. TableSorter does + * not store or copy the data in its TableModel; instead it maintains + * a map from the row indexes of the view to the row indexes of the + * model. As requests are made of the sorter (like getValueAt(row, col)) + * they are passed to the underlying model after the row numbers + * have been translated via the internal mapping array. This way, + * the TableSorter appears to hold another copy of the table + * with the rows in a different order. + *

+ * TableSorter registers itself as a listener to the underlying model, + * just as the JTable itself would. Events recieved from the model + * are examined, sometimes manipulated (typically widened), and then + * passed on to the TableSorter's listeners (typically the JTable). + * If a change to the model has invalidated the order of TableSorter's + * rows, a note of this is made and the sorter will resort the + * rows the next time a value is requested. + *

+ * When the tableHeader property is set, either by using the + * setTableHeader() method or the two argument constructor, the + * table header may be used as a complete UI for TableSorter. + * The default renderer of the tableHeader is decorated with a renderer + * that indicates the sorting status of each column. In addition, + * a mouse listener is installed with the following behavior: + *

    + *
  • + * Mouse-click: Clears the sorting status of all other columns + * and advances the sorting status of that column through three + * values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to + * NOT_SORTED again). + *
  • + * SHIFT-mouse-click: Clears the sorting status of all other columns + * and cycles the sorting status of the column through the same + * three values, in the opposite order: {NOT_SORTED, DESCENDING, ASCENDING}. + *
  • + * CONTROL-mouse-click and CONTROL-SHIFT-mouse-click: as above except + * that the changes to the column do not cancel the statuses of columns + * that are already sorting - giving a way to initiate a compound + * sort. + *
+ *

+ * This is a long overdue rewrite of a class of the same name that + * first appeared in the swing table demos in 1997. + * + * @author Philip Milne + * @author Brendon McLean + * @author Dan van Enckevort + * @author Parwinder Sekhon + * @version 2.0 02/27/04 + */ + +public class TableSorter extends AbstractTableModel { + protected TableModel tableModel; + + public static final int DESCENDING = -1; + public static final int NOT_SORTED = 0; + public static final int ASCENDING = 1; + + private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED); + + public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() { + public int compare(Object o1, Object o2) { + return ((Comparable) o1).compareTo(o2); + } + }; + public static final Comparator LEXICAL_COMPARATOR = new Comparator() { + public int compare(Object o1, Object o2) { + return o1.toString().compareTo(o2.toString()); + } + }; + + private Row[] viewToModel; + private int[] modelToView; + + private JTableHeader tableHeader; + private MouseListener mouseListener; + private TableModelListener tableModelListener; + private Map columnComparators = new HashMap(); + private List sortingColumns = new ArrayList(); + + public TableSorter() { + this.mouseListener = new MouseHandler(); + this.tableModelListener = new TableModelHandler(); + } + + public TableSorter(TableModel tableModel) { + this(); + setTableModel(tableModel); + } + + public TableSorter(TableModel tableModel, JTableHeader tableHeader) { + this(); + setTableHeader(tableHeader); + setTableModel(tableModel); + } + + private void clearSortingState() { + viewToModel = null; + modelToView = null; + } + + public TableModel getTableModel() { + return tableModel; + } + + public void setTableModel(TableModel tableModel) { + if (this.tableModel != null) { + this.tableModel.removeTableModelListener(tableModelListener); + } + + this.tableModel = tableModel; + if (this.tableModel != null) { + this.tableModel.addTableModelListener(tableModelListener); + } + + clearSortingState(); + fireTableStructureChanged(); + } + + public JTableHeader getTableHeader() { + return tableHeader; + } + + public void setTableHeader(JTableHeader tableHeader) { + if (this.tableHeader != null) { + this.tableHeader.removeMouseListener(mouseListener); + TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer(); + if (defaultRenderer instanceof SortableHeaderRenderer) { + this.tableHeader.setDefaultRenderer(((SortableHeaderRenderer) defaultRenderer).tableCellRenderer); + } + } + this.tableHeader = tableHeader; + if (this.tableHeader != null) { + this.tableHeader.addMouseListener(mouseListener); + this.tableHeader.setDefaultRenderer( + new SortableHeaderRenderer(this.tableHeader.getDefaultRenderer())); + } + } + + public boolean isSorting() { + return sortingColumns.size() != 0; + } + + private Directive getDirective(int column) { + for (int i = 0; i < sortingColumns.size(); i++) { + Directive directive = (Directive)sortingColumns.get(i); + if (directive.column == column) { + return directive; + } + } + return EMPTY_DIRECTIVE; + } + + public int getSortingStatus(int column) { + return getDirective(column).direction; + } + + private void sortingStatusChanged() { + clearSortingState(); + fireTableDataChanged(); + if (tableHeader != null) { + tableHeader.repaint(); + } + } + + public void setSortingStatus(int column, int status) { + Directive directive = getDirective(column); + if (directive != EMPTY_DIRECTIVE) { + sortingColumns.remove(directive); + } + if (status != NOT_SORTED) { + sortingColumns.add(new Directive(column, status)); + } + sortingStatusChanged(); + } + + protected Icon getHeaderRendererIcon(int column, int size) { + Directive directive = getDirective(column); + if (directive == EMPTY_DIRECTIVE) { + return null; + } + return new Arrow(directive.direction == DESCENDING, size, sortingColumns.indexOf(directive)); + } + + private void cancelSorting() { + sortingColumns.clear(); + sortingStatusChanged(); + } + + public void setColumnComparator(Class type, Comparator comparator) { + if (comparator == null) { + columnComparators.remove(type); + } else { + columnComparators.put(type, comparator); + } + } + + protected Comparator getComparator(int column) { + Class columnType = tableModel.getColumnClass(column); + Comparator comparator = (Comparator) columnComparators.get(columnType); + if (comparator != null) { + return comparator; + } + if (Comparable.class.isAssignableFrom(columnType)) { + return COMPARABLE_COMAPRATOR; + } + return LEXICAL_COMPARATOR; + } + + private Row[] getViewToModel() { + if (viewToModel == null) { + int tableModelRowCount = tableModel.getRowCount(); + viewToModel = new Row[tableModelRowCount]; + for (int row = 0; row < tableModelRowCount; row++) { + viewToModel[row] = new Row(row); + } + + if (isSorting()) { + Arrays.sort(viewToModel); + } + } + return viewToModel; + } + + public int modelIndex(int viewIndex) { + return getViewToModel()[viewIndex].modelIndex; + } + + private int[] getModelToView() { + if (modelToView == null) { + int n = getViewToModel().length; + modelToView = new int[n]; + for (int i = 0; i < n; i++) { + modelToView[modelIndex(i)] = i; + } + } + return modelToView; + } + + // TableModel interface methods + + public int getRowCount() { + return (tableModel == null) ? 0 : tableModel.getRowCount(); + } + + public int getColumnCount() { + return (tableModel == null) ? 0 : tableModel.getColumnCount(); + } + + public String getColumnName(int column) { + return tableModel.getColumnName(column); + } + + public Class getColumnClass(int column) { + return tableModel.getColumnClass(column); + } + + public boolean isCellEditable(int row, int column) { + return tableModel.isCellEditable(modelIndex(row), column); + } + + public Object getValueAt(int row, int column) { + return tableModel.getValueAt(modelIndex(row), column); + } + + public void setValueAt(Object aValue, int row, int column) { + tableModel.setValueAt(aValue, modelIndex(row), column); + } + + // Helper classes + + private class Row implements Comparable { + private int modelIndex; + + public Row(int index) { + this.modelIndex = index; + } + + public int compareTo(Object o) { + int row1 = modelIndex; + int row2 = ((Row) o).modelIndex; + + for (Iterator it = sortingColumns.iterator(); it.hasNext();) { + Directive directive = (Directive) it.next(); + int column = directive.column; + Object o1 = tableModel.getValueAt(row1, column); + Object o2 = tableModel.getValueAt(row2, column); + + int comparison = 0; + // Define null less than everything, except null. + if (o1 == null && o2 == null) { + comparison = 0; + } else if (o1 == null) { + comparison = -1; + } else if (o2 == null) { + comparison = 1; + } else { + comparison = getComparator(column).compare(o1, o2); + } + if (comparison != 0) { + return directive.direction == DESCENDING ? -comparison : comparison; + } + } + return 0; + } + } + + private class TableModelHandler implements TableModelListener { + public void tableChanged(TableModelEvent e) { + // If we're not sorting by anything, just pass the event along. + if (!isSorting()) { + clearSortingState(); + fireTableChanged(e); + return; + } + + // If the table structure has changed, cancel the sorting; the + // sorting columns may have been either moved or deleted from + // the model. + if (e.getFirstRow() == TableModelEvent.HEADER_ROW) { + cancelSorting(); + fireTableChanged(e); + return; + } + + // We can map a cell event through to the view without widening + // when the following conditions apply: + // + // a) all the changes are on one row (e.getFirstRow() == e.getLastRow()) and, + // b) all the changes are in one column (column != TableModelEvent.ALL_COLUMNS) and, + // c) we are not sorting on that column (getSortingStatus(column) == NOT_SORTED) and, + // d) a reverse lookup will not trigger a sort (modelToView != null) + // + // Note: INSERT and DELETE events fail this test as they have column == ALL_COLUMNS. + // + // The last check, for (modelToView != null) is to see if modelToView + // is already allocated. If we don't do this check; sorting can become + // a performance bottleneck for applications where cells + // change rapidly in different parts of the table. If cells + // change alternately in the sorting column and then outside of + // it this class can end up re-sorting on alternate cell updates - + // which can be a performance problem for large tables. The last + // clause avoids this problem. + int column = e.getColumn(); + if (e.getFirstRow() == e.getLastRow() + && column != TableModelEvent.ALL_COLUMNS + && getSortingStatus(column) == NOT_SORTED + && modelToView != null) { + int viewIndex = getModelToView()[e.getFirstRow()]; + fireTableChanged(new TableModelEvent(TableSorter.this, + viewIndex, viewIndex, + column, e.getType())); + return; + } + + // Something has happened to the data that may have invalidated the row order. + clearSortingState(); + fireTableDataChanged(); + return; + } + } + + private class MouseHandler extends MouseAdapter { + public void mouseClicked(MouseEvent e) { + JTableHeader h = (JTableHeader) e.getSource(); + TableColumnModel columnModel = h.getColumnModel(); + int viewColumn = columnModel.getColumnIndexAtX(e.getX()); + int column = columnModel.getColumn(viewColumn).getModelIndex(); + if (column != -1) { + int status = getSortingStatus(column); + if (!e.isControlDown()) { + cancelSorting(); + } + // Cycle the sorting states through {NOT_SORTED, ASCENDING, DESCENDING} or + // {NOT_SORTED, DESCENDING, ASCENDING} depending on whether shift is pressed. + status = status + (e.isShiftDown() ? -1 : 1); + status = (status + 4) % 3 - 1; // signed mod, returning {-1, 0, 1} + setSortingStatus(column, status); + } + } + } + + private static class Arrow implements Icon { + private boolean descending; + private int size; + private int priority; + + public Arrow(boolean descending, int size, int priority) { + this.descending = descending; + this.size = size; + this.priority = priority; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Color color = c == null ? Color.GRAY : c.getBackground(); + // In a compound sort, make each succesive triangle 20% + // smaller than the previous one. + int dx = (int)(size/2*Math.pow(0.8, priority)); + int dy = descending ? dx : -dx; + // Align icon (roughly) with font baseline. + y = y + 5*size/6 + (descending ? -dy : 0); + int shift = descending ? 1 : -1; + g.translate(x, y); + + // Right diagonal. + g.setColor(color.darker()); + g.drawLine(dx / 2, dy, 0, 0); + g.drawLine(dx / 2, dy + shift, 0, shift); + + // Left diagonal. + g.setColor(color.brighter()); + g.drawLine(dx / 2, dy, dx, 0); + g.drawLine(dx / 2, dy + shift, dx, shift); + + // Horizontal line. + if (descending) { + g.setColor(color.darker().darker()); + } else { + g.setColor(color.brighter().brighter()); + } + g.drawLine(dx, 0, 0, 0); + + g.setColor(color); + g.translate(-x, -y); + } + + public int getIconWidth() { + return size; + } + + public int getIconHeight() { + return size; + } + } + + private class SortableHeaderRenderer implements TableCellRenderer { + private TableCellRenderer tableCellRenderer; + + public SortableHeaderRenderer(TableCellRenderer tableCellRenderer) { + this.tableCellRenderer = tableCellRenderer; + } + + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + Component c = tableCellRenderer.getTableCellRendererComponent(table, + value, isSelected, hasFocus, row, column); + if (c instanceof UILabel) { + UILabel l = (UILabel) c; + l.setHorizontalTextPosition(UILabel.LEFT); + int modelColumn = table.convertColumnIndexToModel(column); + l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize())); + } + return c; + } + } + + private static class Directive { + private int column; + private int direction; + + public Directive(int column, int direction) { + this.column = column; + this.direction = direction; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UIBasicTableUI.java b/designer_base/src/com/fr/design/gui/itable/UIBasicTableUI.java new file mode 100644 index 0000000000..ab9b54b19d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UIBasicTableUI.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.itable; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTableUI; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-4-24 + * Time: 上午10:03 + */ +public class UIBasicTableUI extends BasicTableUI { + + JTable table; + + public UIBasicTableUI() { + super(); + } + + public UIBasicTableUI(JComponent table) { + super(); + this.table = (JTable) table; + this.table.setRowHeight(20); + } + + /** + * 创建UI界面 + * @param table 表 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent table) { + return new UIBasicTableUI(table); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UIComponentTable.java b/designer_base/src/com/fr/design/gui/itable/UIComponentTable.java new file mode 100644 index 0000000000..0480bb5807 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UIComponentTable.java @@ -0,0 +1,35 @@ +package com.fr.design.gui.itable; + +import javax.swing.JComponent; +import com.fr.design.gui.ilable.UILabel; + +/** + * 保持 编辑控件 存在 不toString + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-1-6 下午03:37:18 + */ +public class UIComponentTable extends UITable { + + public UIComponentTable(int columnSize) { + this.setModel(new UITableComponentModel(columnSize)); + initComponents(); + } + + /** + * @param value 该行列的值(字符串) + * @param row + * @param column + * @return 列表中默认显示的东西,如果有很多内容,可以装载一个JPanel里再嵌进来 + */ + protected JComponent getRenderCompoment(Object value, int row, int column) { + UILabel text = new UILabel(); + if (value != null) { + text.setText(value.toString()); + } + if(value instanceof JComponent) { + return (JComponent)value; + } + return text; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UIDefaultTableCellEditor.java b/designer_base/src/com/fr/design/gui/itable/UIDefaultTableCellEditor.java new file mode 100644 index 0000000000..dd0628ee3c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UIDefaultTableCellEditor.java @@ -0,0 +1 @@ +package com.fr.design.gui.itable; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.io.Serializable; import java.util.EventObject; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.JTree; import com.fr.design.gui.itextfield.UITextField; /** * The default editor for table and tree cells. *

* Warning: * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing. As of 1.4, support for long term storage * of all JavaBeansTM * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. * * @author Alan Chung * @author Philip Milne * @version 1.52 11/17/05 */ public class UIDefaultTableCellEditor extends UITableEditor { // // Instance Variables // /** * The Swing component being edited. */ protected JComponent editorComponent; /** * The delegate class which handles all methods sent from the * CellEditor. */ protected EditorDelegate delegate; /** * An integer specifying the number of clicks needed to start editing. * Even if clickCountToStart is defined as zero, it * will not initiate until a click occurs. */ protected int clickCountToStart = 1; // // Constructors // /** * Constructs a DefaultCellEditor that uses a text field. * * @param textField a JTextField object */ public UIDefaultTableCellEditor(final UITextField textField) { editorComponent = textField; // textField.setBorderPainted(false); this.clickCountToStart = 1; delegate = new EditorDelegate() { public void setValue(Object value) { textField.setText((value != null) ? value.toString() : ""); } public Object getCellEditorValue() { return textField.getText(); } }; textField.addActionListener(delegate); } /** * Constructs a DefaultCellEditor object that uses a check box. * * @param checkBox a JCheckBox object */ public UIDefaultTableCellEditor(final JCheckBox checkBox) { editorComponent = checkBox; delegate = new EditorDelegate() { public void setValue(Object value) { boolean selected = false; if (value instanceof Boolean) { selected = ((Boolean) value).booleanValue(); } else if (value instanceof String) { selected = value.equals("true"); } checkBox.setSelected(selected); } public Object getCellEditorValue() { return Boolean.valueOf(checkBox.isSelected()); } }; checkBox.addActionListener(delegate); checkBox.setRequestFocusEnabled(false); } /** * Constructs a DefaultCellEditor object that uses a * combo box. * * @param comboBox a JComboBox object */ public UIDefaultTableCellEditor(final JComboBox comboBox) { editorComponent = comboBox; comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE); delegate = new EditorDelegate() { public void setValue(Object value) { comboBox.setSelectedItem(value); } public Object getCellEditorValue() { return comboBox.getSelectedItem(); } public boolean shouldSelectCell(EventObject anEvent) { if (anEvent instanceof MouseEvent) { MouseEvent e = (MouseEvent) anEvent; return e.getID() != MouseEvent.MOUSE_DRAGGED; } return true; } public boolean stopCellEditing() { if (comboBox.isEditable()) { // Commit edited value. comboBox.actionPerformed(new ActionEvent( UIDefaultTableCellEditor.this, 0, "")); } return super.stopCellEditing(); } }; comboBox.addActionListener(delegate); } /** * Returns a reference to the editor component. * * @return the editor Component */ public Component getComponent() { return editorComponent; } // // Modifying // /** * Specifies the number of clicks needed to start editing. * * @param count an int specifying the number of clicks needed to start editing * @see #getClickCountToStart */ public void setClickCountToStart(int count) { clickCountToStart = count; } /** * Returns the number of clicks needed to start editing. * * @return the number of clicks needed to start editing */ public int getClickCountToStart() { return clickCountToStart; } // // Override the implementations of the superclass, forwarding all methods // from the CellEditor interface to our delegate. // /** * Forwards the message from the CellEditor to * the delegate. * * @see EditorDelegate#getCellEditorValue */ public Object getCellEditorValue() { return delegate.getCellEditorValue(); } /** * Forwards the message from the CellEditor to * the delegate. * * @see EditorDelegate#isCellEditable(EventObject) */ public boolean isCellEditable(EventObject anEvent) { return delegate.isCellEditable(anEvent); } /** * Forwards the message from the CellEditor to * the delegate. * * @see EditorDelegate#shouldSelectCell(EventObject) */ public boolean shouldSelectCell(EventObject anEvent) { return delegate.shouldSelectCell(anEvent); } /** * Forwards the message from the CellEditor to * the delegate. * * @see EditorDelegate#stopCellEditing */ public boolean stopCellEditing() { return delegate.stopCellEditing(); } /** * Forwards the message from the CellEditor to * the delegate. * * @see EditorDelegate#cancelCellEditing */ public void cancelCellEditing() { delegate.cancelCellEditing(); } // // Implementing the TreeCellEditor Interface // /** * Implements the TreeCellEditor interface. */ public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) { String stringValue = tree.convertValueToText(value, isSelected, expanded, leaf, row, false); delegate.setValue(stringValue); return editorComponent; } // // Implementing the CellEditor Interface // /** * Implements the TableCellEditor interface. */ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { delegate.setValue(value); return editorComponent; } // // Protected EditorDelegate class // /** * The protected EditorDelegate class. */ protected class EditorDelegate implements ActionListener, ItemListener, Serializable { /** * The value of this cell. */ protected Object value; /** * Returns the value of this cell. * * @return the value of this cell */ public Object getCellEditorValue() { return value; } /** * Sets the value of this cell. * * @param value the new value of this cell */ public void setValue(Object value) { this.value = value; } /** * Returns true if anEvent is not a * MouseEvent. Otherwise, it returns true * if the necessary number of clicks have occurred, and * returns false otherwise. * * @param anEvent the event * @return true if cell is ready for editing, false otherwise * @see #setClickCountToStart * @see #shouldSelectCell */ public boolean isCellEditable(EventObject anEvent) { if (anEvent instanceof MouseEvent) { return ((MouseEvent) anEvent).getClickCount() >= clickCountToStart; } return true; } /** * Returns true to indicate that the editing cell may * be selected. * * @param anEvent the event * @return true * @see #isCellEditable */ public boolean shouldSelectCell(EventObject anEvent) { return true; } /** * Returns true to indicate that editing has begun. * * @param anEvent the event */ public boolean startCellEditing(EventObject anEvent) { return true; } /** * Stops editing and * returns true to indicate that editing has stopped. * This method calls fireEditingStopped. * * @return true */ public boolean stopCellEditing() { fireEditingStopped(); return true; } /** * Cancels editing. This method calls fireEditingCanceled. */ public void cancelCellEditing() { fireEditingCanceled(); } /** * When an action is performed, editing is ended. * * @param e the action event * @see #stopCellEditing */ public void actionPerformed(ActionEvent e) { UIDefaultTableCellEditor.this.stopCellEditing(); } /** * When an item's state changes, editing is ended. * * @param e the action event * @see #stopCellEditing */ public void itemStateChanged(ItemEvent e) { UIDefaultTableCellEditor.this.stopCellEditing(); } } } // End of class JCellEditor \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UISelectTable.java b/designer_base/src/com/fr/design/gui/itable/UISelectTable.java new file mode 100644 index 0000000000..6c80cb79ee --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UISelectTable.java @@ -0,0 +1,108 @@ +package com.fr.design.gui.itable; + +import java.awt.BorderLayout; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.fr.design.event.ChangeEvent; +import com.fr.design.event.ChangeListener; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UISelectTable extends UITable implements MouseListener { + + protected int selectedRowIndex = -1; + private List selectionListeners = new ArrayList(); + + public UISelectTable(int columnSize) { + super(columnSize); + addMouseListener(this); + } + + /** + * 给表添加选择事件 + * + * @param listener 选择表数据时触发的事件 + */ + public void addSelectionChangeListener(ChangeListener listener) { + selectionListeners.add(listener); + } + + private void fireSelectionChangeListener(ChangeEvent e) { + for (int i = selectionListeners.size(); i > 0; i--) { + selectionListeners.get(i - 1).fireChanged(e); + } + } + + @Override + public boolean isCellEditable(int row, int column) { + return column != 0 && super.isCellEditable(row, column); + } + + /** + * 鼠标点击事件,以触发表的选择事件 + * + * @param e 鼠标事件对象 + */ + @Override + public final void mouseClicked(MouseEvent e) { + selectedRowIndex = rowAtPoint(e.getPoint()); + Object selectItem = getModel().getValueAt(selectedRowIndex, columnAtPoint(e.getPoint())); + fireSelectionChangeListener(new ChangeEvent(selectItem)); + } + + /** + * Invoked when a mouse button has been pressed on a component. + */ + @Override + public void mousePressed(MouseEvent e) { + } + + /** + * Invoked when a mouse button has been released on a component. + */ + @Override + public void mouseReleased(MouseEvent e) { + } + + /** + * Invoked when the mouse enters a component. + */ + @Override + public void mouseEntered(MouseEvent e) { + } + + /** + * Invoked when the mouse exits a component. + */ + @Override + public void mouseExited(MouseEvent e) { + } + + + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + List data = new ArrayList(); + String[] a = {"1", "11"}; + String[] b = {"2", "22"}; + String[] c = {"3", "33"}; + String[] d = {"4", "44"}; + data.add(a); + data.add(b); + data.add(c); + data.add(d); + UISelectTable pane = new UISelectTable(1); + pane.populateBean(data); + content.add(pane, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UITable.java b/designer_base/src/com/fr/design/gui/itable/UITable.java new file mode 100644 index 0000000000..ccfcd9b806 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UITable.java @@ -0,0 +1,388 @@ +package com.fr.design.gui.itable; + +import java.awt.*; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.TableUI; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; + +import com.fr.design.constants.UIConstants; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.utils.gui.GUICoreUtils; + +public class UITable extends JTable implements UIObserver { + + + private static final int OFF_LEFT = 10; + private static final int DEFAULT_ROW_HEIGHT =20; + private UIObserverListener uiObserverListener; + UITableEditor editor ; + private boolean shouldResponseAwt; + private boolean isEditingStopped; + + + /** + * 在没有任何数据的时候,使用此构造函数,然后通过populate更新数据 + * + * @param columnSize 列表的列数 + */ + public UITable(int columnSize) { + + super(new UITableDataModel(columnSize)); + initComponents(); + iniListener(); + shouldResponseAwt = false; + // kunsnat: 屏蔽: 对于下拉框, 无法等待选择结果之后在stop.. +// Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + } + + public UITable (int columnSize, boolean needAWTEventListener) { + this(columnSize); + shouldResponseAwt = needAWTEventListener; + isEditingStopped = true; + if (needAWTEventListener) { + Toolkit.getDefaultToolkit().addAWTEventListener(awt, AWTEvent.MOUSE_EVENT_MASK); + this.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + isEditingStopped = false; + } + }); + } + } + + /** + * values不允许为空! + * + * @param values 一个列表,里面装有字符串数组,每个数组代表一行内容 + */ + public UITable(List values) { + super(new UITableDataModel(values)); + initComponents(); + iniListener(); + } + + public UITable() { + + } + + public void populateBean(List values) { + getTableDataModel().populateBean(values); + } + + + + private AWTEventListener awt = new AWTEventListener() { + public void eventDispatched(AWTEvent event) { + if(!UITable.this.isShowing()){ + return; + } + doSomeInAll(event); + } + }; + + private void doSomeInAll(AWTEvent event) { + Rectangle bounds = new Rectangle(getLocationOnScreen().x, getLocationOnScreen().y, getWidth(), getHeight()); + if (event instanceof MouseEvent) { + MouseEvent mv = (MouseEvent) event; + if (mv.getClickCount() > 0) { + Point point = new Point((int) (mv.getLocationOnScreen().getX()) - 2 * OFF_LEFT, (int) mv.getLocationOnScreen().getY()); + // 判断鼠标点击是否在边界内 + if (!bounds.contains(point) && shouldResponseAwt) { + if (!isEditingStopped) { + this.editor.stopCellEditing(); + isEditingStopped = true; + } + } + } + } + } + + public List updateBean() { + return getTableDataModel().updateBean(); + } + + /** + * 在table底部增加一空行 + */ + public void addBlankLine() { + getTableDataModel().addBlankLine(); + } + + /** + * 在table底部增加一行内容 + * @param line 该行的内容 + */ + public void addLine(Object[] line) { + getTableDataModel().addLine(line); + } + + /** + * @param rowIndex + * @return 某一行的内容 + */ + public Object[] getLine(int rowIndex) { + return getTableDataModel().getLine(rowIndex); + } + + /** + * 删除某行内容 + * + * @param rowIndex 行号 + */ + public void removeLine(int rowIndex) { + getTableDataModel().removeLine(rowIndex); + } + + /** + * 对某一行拖动时进行排序 + * + * @param rowIndex 行号 + * @param positive 鼠标移动的距离 + */ + public void dragSort(int rowIndex, boolean positive) { + ((UITableDataModel) dataModel).dragSort(rowIndex, positive); + } + + + /** + *格子是否可编辑,可置顶某一列column不可编辑 + * @param row 行号 + * @param column 列号 + * @return 是否可编辑 + */ + public boolean isCellEditable(int row, int column) { + return true; + } + + /** + * 清空数据 + */ + public void clear() { + getTableDataModel().clear(); + } + + private UITableDataModel getTableDataModel() { + return (UITableDataModel) dataModel; + } + + /** + * @param value 该行列的值(字符串) + * @param row + * @param column + * @return 列表中默认显示的东西,如果有很多内容,可以装载一个JPanel里再嵌进来 + */ + protected JComponent getRenderCompoment(Object value, int row, int column) { + UILabel text = new UILabel(); + if (value != null) { + text.setText(value.toString()); + } + return text; + } + + protected void initComponents() { + setShowGrid(false); + setRowHeight(getRowHeight4Table()); + setDragEnabled(false); + editor = createTableEditor(); + editor.addCellEditorListener(new CellEditorListener() { + @Override + public void editingStopped(ChangeEvent e) { + tableCellEditingStopped(e); + } + + @Override + public void editingCanceled(ChangeEvent e) { + tableCellEditingCanceled(e); + } + + }); + + setBackground(UIConstants.NORMAL_BACKGROUND); + setDefaultEditor(UITable.class, editor); + setDefaultRenderer(UITable.class, new UITableRender()); + setUI(getUI()); + + TableColumn deleteTableColumn = new TableColumn(getTableDataModel().getColumnCount()); + deleteTableColumn.setCellEditor(null); + deleteTableColumn.setCellRenderer(null); + deleteTableColumn.setMaxWidth(20); + getColumnModel().addColumn(deleteTableColumn); + } + + /** + * 鼠标悬浮再某一行时触发的事件 + * @param index 行号 + */ + public void dealWithRollOver(int index){ + + } + + private void iniListener(){ + if(shouldResponseChangeListener()){ + this.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if(uiObserverListener == null){ + return ; + } + uiObserverListener.doChange(); + } + }); + } + } + + protected int getRowHeight4Table() { + return DEFAULT_ROW_HEIGHT; + } + + + /** + *停止编辑事件 + * @param e 事件 + */ + public void tableCellEditingStopped(ChangeEvent e) { + + } + + /** + *取消编辑事件 + * @param e 事件 + */ + public void tableCellEditingCanceled(ChangeEvent e) { + + } + + /** + * 编辑器 + * @return 编辑器 + */ + public UITableEditor createTableEditor() { + return new UIDefaultTableCellEditor(new UITextField()); + } + + @Override + /** + * + */ + public TableUI getUI() { + return new UITableUI(); + } + + @Override + /** + * + */ + public TableCellEditor getDefaultEditor(Class columnClass) { + columnClass = UITable.class; + return super.getDefaultEditor(columnClass); + } + + @Override + /** + * + */ + public TableCellRenderer getDefaultRenderer(Class columnClass) { + columnClass = UITable.class; + return super.getDefaultRenderer(columnClass); + } + + /** + * 给组件登记一个观察者监听事件 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + public boolean shouldResponseChangeListener() { + return true; + } + + protected class UITableRender implements TableCellRenderer { + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column) { + JComponent comp = getRenderCompoment(value, row, column); + comp.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); + return comp; + } + } + + protected void fireTargetChanged() { + repaint(); + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener) listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + /** + * 增加监听 + * @param l 监听 + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + *移除监听 + * @param l 监听 + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + /** + *测试主函数 + * @param args 参数 + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + List data = new ArrayList(); + String[] a = {"1", "11"}; + String[] b = {"2", "22"}; + String[] c = {"3", "33"}; + String[] d = {"4", "44"}; + data.add(a); + data.add(b); + data.add(c); + data.add(d); + UITable pane = new UITable(2); + pane.populateBean(data); + content.add(pane, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UITableComponentModel.java b/designer_base/src/com/fr/design/gui/itable/UITableComponentModel.java new file mode 100644 index 0000000000..bd0580e4f4 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UITableComponentModel.java @@ -0,0 +1,23 @@ +package com.fr.design.gui.itable; + + +/** + * 预想的 只比UITableDataModel 差别一件事: setValue 不做toString 保持编辑component存在. + * + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2013-1-6 下午03:32:22 + */ +public class UITableComponentModel extends UITableDataModel { + + public UITableComponentModel(int columnSize) { + super(columnSize); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if(rowIndex >= values.size() || columnIndex >= columnSize || aValue == null) { + return; + } + values.get(rowIndex)[columnIndex] = aValue; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UITableDataModel.java b/designer_base/src/com/fr/design/gui/itable/UITableDataModel.java new file mode 100644 index 0000000000..2018f75eb3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UITableDataModel.java @@ -0,0 +1,146 @@ +package com.fr.design.gui.itable; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; + +public class UITableDataModel implements TableModel { + protected List values; + protected int columnSize; + + public UITableDataModel(int columnSize) { + this.columnSize = columnSize; + this.values = new ArrayList(); + } + + public UITableDataModel(List values) { + if (values == null) { + return; + } + this.values = values; + this.columnSize = values.get(0).length; + } + + public void populateBean(List values) { + if (values == null) { + return; + } + this.values.clear(); + this.values = values; + } + + public void clear() { + values.clear(); + } + + public List updateBean() { + return values; + } + + public void dragSort(int rowIndex, boolean positive) { + if (values == null || rowIndex == -1) { + return; + } + + if (positive && rowIndex < values.size() - 1) { + Object[] tmp = values.get(rowIndex); + values.set(rowIndex, values.get(rowIndex + 1)); + values.set(rowIndex + 1, tmp); + tmp = null; + } else if (!positive && rowIndex > 1) { + Object[] tmp = values.get(rowIndex); + values.set(rowIndex, values.get(rowIndex - 1)); + values.set(rowIndex - 1, tmp); + tmp = null; + } + } + + public Object[] getLine(int rowIndex) { + if (rowIndex >= values.size() || rowIndex < 0) { + return null; + } + return values.get(rowIndex); + } + + public void removeLine(int rowIndex) { + if (rowIndex >= values.size() || rowIndex < 0) { + return; + } + values.remove(rowIndex); + } + + public void addLine(Object[] line) { + if (line.length != columnSize) { + return; + } + values.add(line); + } + + public void addBlankLine() { + Object[] newLine = new Object[columnSize]; + values.add(newLine); + } + + @Override + public int getRowCount() { + return values.size(); + } + + @Override + public int getColumnCount() { + return columnSize; + } + + @Override + public String getColumnName(int columnIndex) { + return null; + } + + @Override + public Class getColumnClass(int columnIndex) { + return null; + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return true; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + if (rowIndex >= values.size() || columnIndex >= columnSize) { + return null; + } + Object[] rowValue = values.get(rowIndex); + if (columnIndex > -1 && columnIndex < rowValue.length) { + return values.get(rowIndex)[columnIndex]; + } + return null; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + if (rowIndex >= values.size() || columnIndex >= columnSize) { + return; + } + if (aValue == null) { + values.get(rowIndex)[columnIndex] = null; + return; + } + values.get(rowIndex)[columnIndex] = aValue.toString(); + } + + @Override + public void addTableModelListener(TableModelListener l) { + // TODO Auto-generated method stub + + } + + @Override + public void removeTableModelListener(TableModelListener l) { + // TODO Auto-generated method stub + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UITableEditor.java b/designer_base/src/com/fr/design/gui/itable/UITableEditor.java new file mode 100644 index 0000000000..2d7dcde3ec --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UITableEditor.java @@ -0,0 +1 @@ +package com.fr.design.gui.itable; import javax.swing.AbstractCellEditor; import javax.swing.table.TableCellEditor; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 6.5.6 * Date: 12-12-13 * Time: 下午10:20 */ public abstract class UITableEditor extends AbstractCellEditor implements TableCellEditor { private Object value; public void setValue(Object value) { this.value = value; } /** * Returns the value contained in the editor. * * @return the value contained in the editor */ @Override public Object getCellEditorValue() { return value; } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UITableNoOptionUI.java b/designer_base/src/com/fr/design/gui/itable/UITableNoOptionUI.java new file mode 100644 index 0000000000..7eaf9e9a3e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UITableNoOptionUI.java @@ -0,0 +1,25 @@ +package com.fr.design.gui.itable; + +import java.awt.event.MouseEvent; + +import javax.swing.event.MouseInputListener; + +/** + * 删除按钮 无提示框 + * @author kunsnat E-mail:kunsnat@gmail.com + * @version 创建时间:2012-11-14 下午12:57:53 + */ +public class UITableNoOptionUI extends UITableUI { + + protected MouseInputListener createMouseInputListener() { + return new MyMouseListener() { + public void mousePressed(MouseEvent e) { + if (e.getX() >= table.getWidth() - 20) { + ((UITable)table).removeLine(table.rowAtPoint(e.getPoint())); + ((UITable)table).fireTargetChanged(); + ((UITable)table).getParent().doLayout(); + } + } + }; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itable/UITableUI.java b/designer_base/src/com/fr/design/gui/itable/UITableUI.java new file mode 100644 index 0000000000..a770ce413e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itable/UITableUI.java @@ -0,0 +1,225 @@ +package com.fr.design.gui.itable; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.Stroke; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; + +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.basic.BasicTableUI; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableModel; + +import com.fr.base.BaseUtils; +import com.fr.design.constants.UIConstants; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.Inter; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class UITableUI extends BasicTableUI { + private static BufferedImage closeIcon = BaseUtils.readImageWithCache("com/fr/design/images/toolbarbtn/close.png"); + protected boolean isReleased = true; + protected int rollOverRowIndex = -1; + protected int dragStartRowIndex = -1; + protected int dragStartY = -1; + protected int dragEndY = -1; + private int startColumn; + private int startRow; + private boolean draggingRow = false; + private static final int WIDTH_GAP = 20; + private int startDragPoint; + + private int dyOffset; + + + public UITableUI() { + super(); + } + + public UITableUI(JComponent table) { + super(); + this.table = (JTable) table; + this.table.setRowHeight(20); + } + + @Override + public void paint(Graphics g, JComponent c) { + Graphics2D g2d = (Graphics2D) g; + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + //鼠标悬停时,画一层蓝色背景色 + paintRolloverBackground(g2d); + super.paint(g, c); + //画虚线,不重写原来的paintGrid因为paintGrid为private +// paintDotLine(g2d); + //画X号 + paintDeleteButton(g2d); + //画拖拽 + paintDragTab(g2d); + + + g2d.setStroke(oldStroke); + g2d.setColor(oldColor); + } + + protected void paintDragTab(Graphics2D g) { + if (draggingRow) { + g.setColor(table.getParent().getBackground()); + Rectangle cellRect = table.getCellRect(table.getSelectedRow(), 0, false); + g.copyArea(cellRect.x, cellRect.y, table.getWidth(), table.getRowHeight(), cellRect.x, dyOffset); + if (dyOffset < 0) { + g.fillRect(cellRect.x, cellRect.y + (table.getRowHeight() + dyOffset), table.getWidth(), (dyOffset * -1)); + } else { + g.fillRect(cellRect.x, cellRect.y, table.getWidth(), dyOffset); + } + } + } + + protected boolean isDeletable(){ + return true; + } + + private void paintDeleteButton(Graphics2D g2d) { + if (!isReleased || rollOverRowIndex == -1) { + return; + } + if(!isDeletable()){ + return; + } + g2d.drawImage(closeIcon, table.getWidth() - 20, rollOverRowIndex * table.getRowHeight() + 1, closeIcon.getWidth(), closeIcon.getHeight(), table); + } + + private void paintRolloverBackground(Graphics2D g2d) { + if (rollOverRowIndex != -1) { + g2d.setColor(UIConstants.FLESH_BLUE); + GUIPaintUtils.fillPaint(g2d, 1, rollOverRowIndex * table.getRowHeight(), table.getWidth() - 2, table.getRowHeight(), true, Constants.NULL, UIConstants.FLESH_BLUE, UIConstants.LARGEARC); + } + } + + protected MouseInputListener createMouseInputListener() { + return new MyMouseListener(); + } + + protected class MyMouseListener extends BasicTableUI.MouseInputHandler { + + public void mouseMoved(MouseEvent e) { + super.mouseMoved(e); + int tmp = table.rowAtPoint(e.getPoint()); + if (rollOverRowIndex != tmp && isReleased) { + rollOverRowIndex = tmp; + ((UITable)table).dealWithRollOver(rollOverRowIndex); + table.repaint(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + if (e.getX() >= table.getWidth() - WIDTH_GAP) { + if (table.isEditing()) { + table.getCellEditor(startRow, startColumn).stopCellEditing(); + } + + if(!isDeletable()){ + return; + } + if (!table.isEditing()) { + int val = JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("Utils-Are_you_sure_to_remove_the_selected_item") + "?", + Inter.getLocText("Remove"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (val == JOptionPane.OK_OPTION) { + ((UITable) table).removeLine(table.rowAtPoint(e.getPoint())); + ((UITable) table).fireTargetChanged(); + ((UITable) table).getParent().doLayout(); + return; + } + } + } + startColumn = table.columnAtPoint(e.getPoint()); + startRow = table.rowAtPoint(e.getPoint()); + startDragPoint = (int) e.getPoint().getY(); + } + + @Override + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + draggingRow = false; + isReleased = true; + table.repaint(); + } + + @Override + public void mouseDragged(MouseEvent e) { + int fromRow = table.getSelectedRow(); + TableCellEditor tableCellEditor = table.getCellEditor(startRow, startColumn); + tableCellEditor.stopCellEditing(); + + if (fromRow >= 0) { + draggingRow = true; + int rowHeight = table.getRowHeight(); + int middleOfSelectedRow = (rowHeight * fromRow) + (rowHeight / 2); + int toRow = -1; + int yMousePoint = (int) e.getPoint().getY(); + + if (yMousePoint < (middleOfSelectedRow - rowHeight)) { + toRow = fromRow - 1; + } else if (yMousePoint > (middleOfSelectedRow + rowHeight)) { + toRow = fromRow + 1; + } + + if (toRow >= 0 && toRow < table.getRowCount()) { + TableModel model = table.getModel(); + + for (int i = 0; i < model.getColumnCount(); i++) { + Object fromValue = model.getValueAt(fromRow, i); + Object toValue = model.getValueAt(toRow, i); + + model.setValueAt(toValue, fromRow, i); + model.setValueAt(fromValue, toRow, i); + } + table.setRowSelectionInterval(toRow, toRow); + startDragPoint = yMousePoint; + rollOverRowIndex = toRow; + } + dyOffset = (startDragPoint - yMousePoint) * -1; + table.repaint(); + } + } + + + } + + protected void startDragTab(MouseEvent e) { + rollOverRowIndex = -1; + dragStartY = e.getY(); + dragStartRowIndex = table.rowAtPoint(e.getPoint()); + } + + protected void resetDragTab() { + dragStartY = -1; + dragEndY = -1; + isReleased = true; + } + + /** + * 初始化UI + * + * @param c 组件 + */ + public void installUI(JComponent c) { + table = (JTable) c; + rendererPane = new CellRendererPane(); + table.add(rendererPane); + installDefaults(); + installListeners(); + installKeyboardActions(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/ActionStyle.java b/designer_base/src/com/fr/design/gui/itableeditorpane/ActionStyle.java new file mode 100644 index 0000000000..c1c2a1044f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/ActionStyle.java @@ -0,0 +1,16 @@ +package com.fr.design.gui.itableeditorpane; + +public interface ActionStyle { + + public int ADDSTYLE = 1; + + public int DELETESTYLE = 2; + + public int MOVEUPSTYLE = 3; + + public int MOVEDOWNSTYLE = 4; + + public int ADDJSFILE = 6; + + public int ADDCSSFILE = 7; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/ParameterTableModel.java b/designer_base/src/com/fr/design/gui/itableeditorpane/ParameterTableModel.java new file mode 100644 index 0000000000..2c8122c633 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/ParameterTableModel.java @@ -0,0 +1,258 @@ +package com.fr.design.gui.itableeditorpane; + +import com.fr.base.Parameter; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.editor.ValueEditorPane; +import com.fr.design.editor.ValueEditorPaneFactory; +import com.fr.general.Inter; +import com.fr.stable.ParameterProvider; +import com.fr.stable.StringUtils; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellEditor; +import java.awt.*; +import java.awt.event.ActionEvent; + +/** + * 参数列表 下拉参数模式. +* @author kunsnat E-mail:kunsnat@gmail.com +* @version 创建时间:2013-1-11 上午10:07:49 + */ +public class ParameterTableModel extends UITableModelAdapter { + + public static final int NO_CHART_USE = 0; + public static final int CHART_NORMAL_USE = 1; + public static final int CHART_MAP_USE = 2; + public static final int CHART_PIE_USE = 3; + public static final int CHART__XY_USE = 4; + public static final int CHART_BUBBLE_USE = 5; + public static final int CHART_STOCK_USE = 6; + public static final int CHART_NO_USE = 7; + public static final int CHART_GIS_USE = 8; + public static final int CHART_GANTT_USE = 9; + public static final int CHART_METER_USE = 10; + public static final int FORM_NORMAL_USE = -1; + public static final int FORM_ELEMENTCASE_USE = 11; + public static final int FORM_CHART_USE = 12; + + private static final long serialVersionUID = 1L; + protected Component component = null; //指定确认对话框的父窗口,bug40340 + public ParameterTableModel() { + this(NO_CHART_USE); + } + + public ParameterTableModel(int paraUseType) { + super(new String[] { Inter.getLocText("Parameter"), Inter.getLocText("Value") }); + this.setColumnClass(new Class[] { ParameterEditor.class, ParameterValueEditor.class }); + this.setDefaultEditor(ParameterValueEditor.class, new ParameterValueEditor(paraUseType)); + this.setDefaultEditor(ParameterEditor.class, new ParameterEditor()); + this.setDefaultRenderer(ParameterValueEditor.class, new ParameterValueRenderer(paraUseType)); + } + + public ParameterTableModel(int paraUseType, Component component) { + super(new String[] { Inter.getLocText("Parameter"), Inter.getLocText("Value") }); + this.setColumnClass(new Class[] { ParameterEditor.class, ParameterValueEditor.class }); + this.setDefaultEditor(ParameterValueEditor.class, new ParameterValueEditor(paraUseType)); + this.setDefaultEditor(ParameterEditor.class, new ParameterEditor()); + this.setDefaultRenderer(ParameterValueEditor.class, new ParameterValueRenderer(paraUseType)); + this.component = component; + } + + + /** + * 单元格是否可编辑 + * @param row 行 + * @param col 列 + * @return 是否可以编辑 + */ + public boolean isCellEditable(int row, int col) { + if(col == 1) { + return this.getList().get(row) != null && StringUtils.isNotEmpty(this.getList().get(row).getName()); + } + return true; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + ParameterProvider para = this.getList().get(rowIndex); + switch (columnIndex) { + case 0: + return para.getName(); + case 1: + return para.getValue(); + } + return null; + } + + /** + * 生成工具栏上的一系列动作按钮 + * @return 返回table上的action数组. + */ + @Override + public UITableEditAction[] createAction() { + return new UITableEditAction[] { new AddParameterAction(), new DeleteAction(), new MoveUpAction(), new MoveDownAction() }; + } + + + /** + * 生成上移下移按钮 + * @return UItableEdit数组. + */ + public UITableEditAction[] createDBTableAction() { + return new UITableEditAction[] { new MoveUpAction(), new MoveDownAction() }; + } + + private class AddParameterAction extends AddTableRowAction { + + public AddParameterAction() { + + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + addParameter(); + } + } + + private void addParameter() { + Parameter para = new Parameter(); + addRow(para); + fireTableDataChanged(); + table.getSelectionModel().setSelectionInterval(table.getRowCount() - 1, table.getRowCount() - 1); + } + + protected class AddChartParameterAction extends AddTableRowAction { + public AddChartParameterAction() { + super(); + } + + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + addParameter(); + // kunsnat: 屏蔽以下部分弹出框 直接添加行针对bug 10061 +// final ChartHotParameterEditPane pane = new ChartHotParameterEditPane(); +// pane.populate(para); +// BasicDialog dialog = pane.showSmallWindow(SwingUtilities.getWindowAncestor(DesignerContext.getDesignerFrame()),new DialogActionAdapter() { +// +// @Override +// public void doOk() { +// addRow(pane.update()); +// fireTableDataChanged(); +// } +// }); +// dialog.setVisible(true); + } + } + + public class ParameterEditor extends AbstractCellEditor implements TableCellEditor { + + private UITextField textField; + + public ParameterEditor() { + textField = new UITextField(); + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1){ + return; + } + ParameterProvider para = getList().get(table.getSelectedRow()); + String value = StringUtils.trimToNull(textField.getText()); + para.setName(value); + fireTableDataChanged(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + textField.setText((String) value); + return textField; + } + + @Override + public Object getCellEditorValue() { + return textField.getText(); + } + } + + private class ParameterValueEditor extends AbstractCellEditor implements TableCellEditor { + private static final long serialVersionUID = 1L; + private ValueEditorPane editor; + + public ParameterValueEditor(int paraUseType) { + + editor = ValueEditorPaneFactory.createVallueEditorPaneWithUseType(paraUseType); + + this.addCellEditorListener(new CellEditorListener() { + + @Override + public void editingCanceled(ChangeEvent e) { + + } + + @Override + public void editingStopped(ChangeEvent e) { + if (table.getSelectedRow() == -1) { + return; + } + ParameterProvider para = getList().get(table.getSelectedRow()); + para.setValue(getCellEditorValue()); + fireTableDataChanged(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + editor.populate(value == null ? "" : value); + return editor; + } + + @Override + public Object getCellEditorValue() { + return editor.update(); + } + + } + + private class ParameterValueRenderer extends DefaultTableCellRenderer { + private static final long serialVersionUID = 1L; + private ValueEditorPane editor; + private UILabel disableLable; + + public ParameterValueRenderer(int paraUseType) { + disableLable = new UILabel(Inter.getLocText("Set-Parameter-Name")); + disableLable.setForeground(Color.pink); + disableLable.setHorizontalAlignment(SwingConstants.CENTER); + + editor = ValueEditorPaneFactory.createVallueEditorPaneWithUseType(paraUseType); + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + if (table.isCellEditable(row, column)) { + if (value == null) { + editor.populate(""); + } else { + editor.populate(value); + } + return editor; + } else { + return disableLable; + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/UIArrayTableModel.java b/designer_base/src/com/fr/design/gui/itableeditorpane/UIArrayTableModel.java new file mode 100644 index 0000000000..8d5de0281b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/UIArrayTableModel.java @@ -0,0 +1,74 @@ +package com.fr.design.gui.itableeditorpane; + + +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; + +public class UIArrayTableModel extends UITableModelAdapter implements ActionStyle { + /** + * + */ + private static final long serialVersionUID = 1L; + private int[] array; + + public UIArrayTableModel(String[] s, int[] array) { + super(s); + this.array = array; + } + + public Object getValueAt(int row, int column) { + Object[] os = this.getList().get(row); + if(os != null && column < os.length) { + return os[column]; + } + return null; + } + + public void setValueAt(Object value, int row, int column) { + Object[] os = this.getList().get(row); + os[column] = value; + fireTableCellUpdated(row, column); + } + + public boolean isCellEditable(int row, int col) { + return true; + } + + @Override + public UITableEditAction[] createAction() { + List list = new ArrayList(); + UITableEditAction[] tableEditAction = new UITableEditAction[array.length]; + for (int i : array) { + switch (i) { + case UIArrayTableModel.ADDSTYLE: + list.add(new AddRow()); + break; + case UIArrayTableModel.ADDJSFILE: + break; + case UIArrayTableModel.ADDCSSFILE: + break; + case UIArrayTableModel.DELETESTYLE: + list.add(new DeleteAction()); + break; + case UIArrayTableModel.MOVEUPSTYLE: + list.add(new MoveUpAction()); + break; + case UIArrayTableModel.MOVEDOWNSTYLE: + list.add(new MoveDownAction()); + break; + + } + } + return list.toArray(tableEditAction); + } + + public class AddRow extends AddTableRowAction { + @Override + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + addRow(new Object[getColumnCount()]); + fireTableDataChanged(); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditAction.java b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditAction.java new file mode 100644 index 0000000000..61a50fa4d0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditAction.java @@ -0,0 +1,8 @@ +package com.fr.design.gui.itableeditorpane; + +import com.fr.design.actions.UpdateAction; + +public abstract class UITableEditAction extends UpdateAction { + + public abstract void checkEnabled(); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorLoader.java b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorLoader.java new file mode 100644 index 0000000000..b477f9517b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorLoader.java @@ -0,0 +1,12 @@ +package com.fr.design.gui.itableeditorpane; + + + +public interface UITableEditorLoader { + + // august:生成工具栏上的一系列动作按钮 + UITableEditAction[] createAction(); + + void stopCellEditing(); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorPane.java b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorPane.java new file mode 100644 index 0000000000..a0c09a8486 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableEditorPane.java @@ -0,0 +1,148 @@ +package com.fr.design.gui.itableeditorpane; + +import com.fr.design.constants.UIConstants; +import com.fr.design.border.UIRoundedBorder; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; + +import javax.swing.*; +import javax.swing.event.TableModelListener; +import java.awt.*; +import java.util.List; + +/** + * 表格编辑面板,一般是两列.键-值 用泛型实现,用的时候请定义T.model里面的T要一样 + * + * @editor zhou + * @since 2012-3-28下午3:06:30 + */ +public class UITableEditorPane extends BasicPane { + /** + * + */ + private static final long serialVersionUID = 6855793816972735815L; + private JTable editTable; + // 放置action 的按钮. + private UITableModelAdapter tableModel; + private String leftLabelName; + private JPanel buttonPane; + + public UITableEditorPane(UITableModelAdapter model) { + this.tableModel = model; + this.initComponent(model.createAction()); + } + + public UITableEditorPane(UITableModelAdapter model, String s) { + leftLabelName = s; + this.tableModel = model; + this.initComponent(model.createAction()); + } + + private void initComponent(UITableEditAction[] action) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + JPanel pane = new JPanel(new BorderLayout(4, 4)); + this.add(pane, BorderLayout.CENTER); + + UILabel l = new UILabel(leftLabelName); + editTable = tableModel.createTable(); + + UIScrollPane scrollPane = new UIScrollPane(editTable); + scrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); + pane.add(scrollPane, BorderLayout.CENTER); + initbuttonPane(action); + JPanel controlPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + controlPane.add(buttonPane, BorderLayout.EAST); + controlPane.add(l, BorderLayout.WEST); + pane.add(controlPane, BorderLayout.NORTH); + + } + + public UITableModelAdapter getTableModel(){ + return tableModel; + } + + private void initbuttonPane(UITableEditAction[] action){ + buttonPane = new JPanel(); + + if (action != null) { + buttonPane.setLayout(new GridLayout(1, action.length, 3, 3)); + for (int i = 0; i < action.length; i++) { + final UIButton newButton = new UIButton(action[i]); + newButton.set4ToolbarButton(); + newButton.setMargin(new Insets(0, 0, 0, 0)); + newButton.setText(""); + newButton.setName(action[i].getName()); + newButton.setToolTipText(action[i].getName()); + newButton.setBorder(null); + newButton.setMargin(null); + newButton.setOpaque(false); + buttonPane.add(newButton); + } + } + } + + /** + * 增加事件监听 + * @param l 加的东东 + */ + public void addTableListener(TableModelListener l) { + tableModel.addTableModelListener(l); + } + + /** + * 移除事件监听 + * @param l 去的东东 + */ + public void removeTableListener(TableModelListener l) { + tableModel.removeTableModelListener(l); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("TableData_Dynamic_Parameter_Setting"); + } + + public void populate(T[] objs) { + tableModel.clear(); + if(objs==null){ + return; + } + for (T obj : objs) { + tableModel.addRow(obj); + } + this.tableModel.fireTableDataChanged(); + if (objs.length > 0) { + this.editTable.getSelectionModel().setSelectionInterval(0, 0); + } + } + + // TODO:august这个最好还是返回数组 + public List update() { + tableModel.stopCellEditing(); + return tableModel.getList(); + } + + public int getSelectedRow() { + return this.editTable.getSelectedRow(); + } + + public int getSelectedColumn() { + return this.editTable.getSelectedColumn(); + } + + public JPanel getbuttonPane(){ + return buttonPane; + } + + /** + * 停止编辑 + */ + public void stopEditing() { + tableModel.stopCellEditing(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java new file mode 100644 index 0000000000..38f4cf81c9 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itableeditorpane/UITableModelAdapter.java @@ -0,0 +1,330 @@ +package com.fr.design.gui.itableeditorpane; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.swing.JOptionPane; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.design.mainframe.DesignerContext; +import com.fr.general.Inter; + +/** + * 用来处理TableEditorPane的model + * @editor zhou + * @since 2012-3-28下午3:07:44 + */ +public abstract class UITableModelAdapter extends AbstractTableModel implements UITableEditorLoader { + + /** + * + */ + private static final long serialVersionUID = 3633792011995186187L; + protected JTable table; + + private Class[] classes; + private String[] columnNames; + + // list里放的是一行数据 + private List list = new ArrayList(); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + protected UITableModelAdapter(String[] columnNames) { + this.columnNames = columnNames; + table = new JTable(this); + table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); +// TableRowSorter rowSorter = new TableRowSorter(this); +// table.setRowSorter(rowSorter); + } + + /** + * 创建表 + * @return 表 + */ + public JTable createTable() { + return table; + } + + public String getColumnName(int col) { + return columnNames[col]; + } + + public T getSelectedValue() { + if (table.getSelectedRow() >= 0) { + return list.get(table.getSelectedRow()); + } + return null; + } + + public void setColumnClass(Class[] classes) { + this.classes = classes; + } + + public void setDefaultEditor(Class columnClass, TableCellEditor editor) { + table.setDefaultEditor(columnClass, editor); + } + + public void setDefaultRenderer(Class columnClass, TableCellRenderer renderer) { + table.setDefaultRenderer(columnClass, renderer); + } + + + public void setList(List list) { + this.list = list; + } + + public List getList() { + return this.list; + } + + /** + * 增加行 + * @param obj 行 + */ + public void addRow(T obj) { + this.list.add(obj); + } + + public void setSelectedValue(T value) { + int selectedIndex = table.getSelectedRow(); + if (selectedIndex >= 0) { + setRowAt(value, selectedIndex); + } + } + + public void setRowAt(T value, int rowIndwx) { + this.list.set(rowIndwx, value); + } + + /** + * 去掉行 + * @param rowIndex 行号 + */ + public void removeRow(int rowIndex) { + if (this.list != null) { + this.list.remove(rowIndex); + + this.fireTableDataChanged(); + } + } + + /** + * 去除所有 + */ + public void clear() { + this.list.clear(); + } + + /** + * 通知所有linstener,Table每一行的值可能改变,并检查 + */ + @Override + public void fireTableDataChanged() { + super.fireTableDataChanged(); + table.getParent().validate(); + table.repaint(); + for (UITableEditAction action : this.createAction()) { + action.checkEnabled(); + } + } + + @Override + public Class getColumnClass(int columnIndex) { + if (classes != null) { + return classes[columnIndex]; + } + return super.getColumnClass(columnIndex); + } + + @Override + public int getRowCount() { + return this.list.size(); + } + + @Override + public int getColumnCount() { + return columnNames == null ? 0 : columnNames.length; + } + + @Override + public abstract Object getValueAt(int rowIndex, int columnIndex); + + /** + * 停止编辑 + */ + @Override + public void stopCellEditing() { + if (table.getCellEditor() != null) { + try { + table.getCellEditor().stopCellEditing(); + } catch (Exception ee) { + FRContext.getLogger().error(ee.getMessage(), ee); + } + } + } + + /** + * 单元格是否可编辑 + * @param row 行 + * @param col 列 + * @return 是则返回true + */ + @Override + public abstract boolean isCellEditable(int row, int col); + + protected abstract class AddTableRowAction extends UITableEditAction { + public AddTableRowAction() { + this.setName(Inter.getLocText("Insert")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/add.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + stopCellEditing(); + } + + public void checkEnabled() { + } + + } + + protected abstract class EditAction extends UITableEditAction { + + public EditAction() { + this.setName(Inter.getLocText("Edit")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/edit.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + final int selectedRow = table.getSelectedRow(); + if (selectedRow > table.getRowCount() - 1 || selectedRow < 0) { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("no-alternatives")); + return; + } + stopCellEditing(); + + } + + } + + protected class DeleteAction extends UITableEditAction { + + private Component component = null; + public DeleteAction() { + this.setName(Inter.getLocText("Delete")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + } + + public DeleteAction(Component component){ + this.setName(Inter.getLocText("Delete")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png")); + this.component = component; + } + + @Override + public void actionPerformed(ActionEvent e) { + int[] selectedRow = table.getSelectedRows(); + if (ismultiSelected()) { + JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),Inter.getLocText(new String[]{"The_current_list_is_empty", "Or-you", "Privilege-Selected_None_Of_Any_Items"})); + return; + } + if (table.getCellEditor() != null) { + try { + table.getCellEditor().stopCellEditing(); + } catch (Exception ee) { + FRContext.getLogger().error(ee.getMessage(), ee); + } + } + if (getRowCount() < 1 || selectedRow.length < 0) { + return; + } + + if(component == null){ + component = DesignerContext.getDesignerFrame(); + } + int val = JOptionPane.showConfirmDialog(component, + Inter.getLocText("Utils-Are_you_sure_to_remove_the_selected_item") + "?", Inter.getLocText("Remove"), + JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (val != JOptionPane.OK_OPTION) { + return; + } + for (int i = 0; i < selectedRow.length; i++) { + if (selectedRow[i] - i < 0) { + continue; + } + removeRow(selectedRow[i] - i); + } + fireTableDataChanged(); + int selection = selectedRow[0] > table.getRowCount() ? table.getRowCount() - 1 + : (selectedRow[0] > 1 ? selectedRow[0] - 1 : 0); + table.getSelectionModel().setSelectionInterval(selection, selection); + } + + private boolean ismultiSelected(){ + int[] selectedRow = table.getSelectedRows(); + return (selectedRow.length == 1 && (selectedRow[0] > table.getRowCount() - 1 || selectedRow[0] < 0)) || selectedRow.length == 0; + } + @Override + public void checkEnabled() { + setEnabled(!ismultiSelected()); + } + } + + protected class MoveUpAction extends UITableEditAction { + public MoveUpAction() { + this.setName(Inter.getLocText("Utils-Move_Up")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/up.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + int selectedRow = table.getSelectedRow(); + stopCellEditing(); + if (getList().size() < 2 || selectedRow == 0) { + return; + } + Collections.swap(getList(), selectedRow, selectedRow - 1); + fireTableDataChanged(); + table.getSelectionModel().setSelectionInterval(selectedRow - 1, selectedRow - 1); + } + + @Override + public void checkEnabled() { + } + } + + protected class MoveDownAction extends UITableEditAction { + + public MoveDownAction() { + this.setName(Inter.getLocText("Utils-Move_Down")); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/down.png")); + } + + @Override + public void actionPerformed(ActionEvent e) { + int selectedRow = table.getSelectedRow(); + stopCellEditing(); + if (getList().size() < 2 || selectedRow == getRowCount() - 1) { + return; + } + Collections.swap(getList(), selectedRow, selectedRow + 1); + fireTableDataChanged(); + table.getSelectionModel().setSelectionInterval(selectedRow + 1, selectedRow + 1); + } + + @Override + public void checkEnabled() { + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itabpane/TitleChangeListener.java b/designer_base/src/com/fr/design/gui/itabpane/TitleChangeListener.java new file mode 100644 index 0000000000..1d96024b56 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itabpane/TitleChangeListener.java @@ -0,0 +1,6 @@ +package com.fr.design.gui.itabpane; + +public interface TitleChangeListener { + + public void fireTitleChange(String addName); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itabpane/UITabPaneCreator.java b/designer_base/src/com/fr/design/gui/itabpane/UITabPaneCreator.java new file mode 100644 index 0000000000..d4b5c6cbbb --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itabpane/UITabPaneCreator.java @@ -0,0 +1,44 @@ +package com.fr.design.gui.itabpane; + +import javax.swing.JPanel; + +public class UITabPaneCreator { + /** + * 父类Component里面有个name成员变量,最好不要用那个 + */ + private String tabName; + + private String iconPath; + + // private String tooltips; + + private JPanel pane; + + public UITabPaneCreator(String tabName, String iconPath, JPanel pane) { + this.tabName = tabName; + this.setIconPath(iconPath); + this.pane = pane; + } + + public void setTabName(String name) { + this.tabName = name; + } + + public String getTabName() { + return this.tabName; + } + + public String getIconPath() { + return iconPath; + } + + public void setIconPath(String iconPath) { + this.iconPath = iconPath; + } + + public JPanel getPane() { + return pane; + } + + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java b/designer_base/src/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java new file mode 100644 index 0000000000..1ba60ed579 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itabpane/UITabsHeaderIconPane.java @@ -0,0 +1,264 @@ +package com.fr.design.gui.itabpane; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JComponent; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.fr.base.BaseUtils; +import com.fr.design.gui.core.UITabComponent; +import com.fr.design.gui.ibutton.UITabButton; +import com.fr.stable.StringUtils; + +/** + * 本来想弄个延迟加载的,发现在单元格属性表那边没有意义,就算了.这个面板是纯粹的,没有与模板的任何交互操作(比如说populate() update()) + * + * @author zhou + * @since 2012-5-11下午3:30:18 + */ +public class UITabsHeaderIconPane extends JPanel implements UITabComponent { + private static final long serialVersionUID = 1L; + + private UILabel nameLabel; + + private UITabPaneCreator[] creators; + private ArrayList labels; + + private JPanel centerPane; + + private int selectedIndex = -1; + + public UITabsHeaderIconPane(final String name, UITabPaneCreator[] tabcreators) { + this.creators = tabcreators; + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createMatteBorder(1, 1, 0, 1, UIConstants.LINE_COLOR)); + + JPanel northTabsPane = new JPanel(new BorderLayout()) { + private static final long serialVersionUID = 1L; + + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, 42); + } + }; + this.add(northTabsPane, BorderLayout.NORTH); + + northTabsPane.setBorder(null); + nameLabel = new UILabel() { + private static final long serialVersionUID = 1L; + + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, 18); + } + }; + nameLabel.setHorizontalAlignment(SwingConstants.CENTER); + northTabsPane.add(nameLabel, BorderLayout.NORTH); + nameLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.LINE_COLOR)); + JPanel tabsPane = new JPanel(); + tabsPane.setLayout(new GridLayout(1, creators.length)); + northTabsPane.add(tabsPane, BorderLayout.CENTER); + labels = new ArrayList(creators.length); + for (int i = 0; i < creators.length; i++) { + String iconpath = creators[i].getIconPath();// august:如果图标路径为空,就说明要用文本了 + final UITabButton label = StringUtils.isEmpty(iconpath) ? new UITabButton(creators[i].getTabName()) : new IconTabLabel(BaseUtils.readIcon(creators[i] + .getIconPath())); + tabsPane.add(label); + labels.add(label); + label.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + int newselectedIndex = labels.indexOf(label); + if (selectedIndex != newselectedIndex) { + setSelectedIndex(newselectedIndex); + } + } + }); + } + + centerPane = new JPanel(new BorderLayout()); + centerPane.setBorder(null); + this.add(centerPane, BorderLayout.CENTER); + + this.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + nameLabel.setText(name + '-' + creators[selectedIndex].getTabName()); + show(creators[selectedIndex].getPane()); + } + }); + + setSelectedIndex(0); + + initKeyListener(); + } + + private void initKeyListener() { + setFocusable(true); + setFocusTraversalKeysEnabled(false); + InputMap inputMapAncestor = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + ActionMap actionMap = this.getActionMap(); + inputMapAncestor.clear(); + actionMap.clear(); + + inputMapAncestor.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_MASK), "switch"); + actionMap.put("switch", new AbstractAction() { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public void actionPerformed(ActionEvent evt) { + setSelectedIndex(selectedIndex + 1 == creators.length ? 0 : selectedIndex + 1); + } + }); + } + + // august: 滑动效果方法 + private void show(final JPanel panel) { + int count = centerPane.getComponentCount();// 获取centerPanel中控件数 + List list = new ArrayList();// + for (Component comp : centerPane.getComponents()) { + list.add(comp); + } + if (count > 0) {// 如果centerPanel中控件数大于0就执行效果 + for (int i = 0; i < count; i++) { + Component comp = centerPane.getComponent(i);// 获得该位置的控件 + + if (comp instanceof JPanel) { + final JPanel currentPanel = (JPanel)comp;// 获得当前panel + + // augsut:必须用多线程,因为swing是单线程的,不用就实现不了动态效果 + new Thread() { + public void run() { + int height = centerPane.getHeight(); + int width = centerPane.getWidth(); + int y = -height; + for (int i = 0; i <= height; i += 30) { + // 设置面板位置 + currentPanel.setBounds(0, i, width, height); + panel.setBounds(0, y, width, height); + y += 30; + try { + Thread.sleep(3); + } catch (InterruptedException e) { + } + } + if (currentPanel != panel) { + centerPane.remove(currentPanel);// 移除当前面板 + } + panel.setBounds(0, 0, width, height); + + } + }.start(); + break; + } + } + } else { + panel.setBounds(0, 0, centerPane.getWidth(), centerPane.getHeight());// 设置滑动初始位置 + } + + if (!list.contains(panel)) { + centerPane.add(panel);// 添加要切换的面板 + } + + centerPane.validate();// 重构内容面板 + centerPane.repaint();// 重绘内容面板 + } + + /** + * Adds a ChangeListener to the listener list. + */ + public void addChangeListener(ChangeListener l) { + this.listenerList.add(ChangeListener.class, l); + } + + /** + * removes a ChangeListener from the listener list. + */ + public void removeChangeListener(ChangeListener l) { + this.listenerList.remove(ChangeListener.class, l); + } + + // august: Process the listeners last to first + private void fireSelectedChanged() { + Object[] listeners = listenerList.getListenerList(); + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ChangeListener.class) { + ((ChangeListener)listeners[i + 1]).stateChanged(new ChangeEvent(this)); + } + } + } + + @Override + public int getSelectedIndex() { + return selectedIndex; + } + + @Override + public synchronized void setSelectedIndex(int newselectedIndex) { + selectedIndex = newselectedIndex; + fireSelectedChanged(); + for (int i = 0; i < labels.size(); i++) { + labels.get(i).setSelectedDoNotFireListener(i == selectedIndex); + } + } + + private class IconTabLabel extends UITabButton { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public IconTabLabel(Icon readIcon) { + super(readIcon); + this.setLayout(new BorderLayout()); + this.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 1, UIConstants.LINE_COLOR)); + } + + @Override + protected void paintRolloverAndSelected(Graphics2D g2d, int w, int h) { + if (!isSelected()) { + GradientPaint gp = new GradientPaint(1, 1, TOP, 1, h - 1, DOWN); + g2d.setPaint(gp); + g2d.fillRect(0, h / 2, w, h / 2); + } else { + Color blue = UIConstants.LIGHT_BLUE; + g2d.setColor(blue); + g2d.fillRect(0, 0, w, h / 2); + GradientPaint gp = new GradientPaint(1, 1, blue, 1, h - 1, blue); + g2d.setPaint(gp); + g2d.fillRect(0, h / 2, w, h / 2); + } + } + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextarea/DescriptionTextArea.java b/designer_base/src/com/fr/design/gui/itextarea/DescriptionTextArea.java new file mode 100644 index 0000000000..0a6295c370 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextarea/DescriptionTextArea.java @@ -0,0 +1,27 @@ +/* + * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. + */ +package com.fr.design.gui.itextarea; + + +/** + * peter:这个控件主要是用来在界面显示帮助信息的. + */ +public class DescriptionTextArea extends UITextArea { + public DescriptionTextArea() { + this(3); + } + + public DescriptionTextArea(int row) { + this(row, 8); + } + + public DescriptionTextArea(int rows, int columns) { + super(rows, columns); + this.setBackground(null); + this.setLineWrap(true); + + this.setWrapStyleWord(true); + this.setEditable(false); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextarea/FRExplainTextArea.java b/designer_base/src/com/fr/design/gui/itextarea/FRExplainTextArea.java new file mode 100644 index 0000000000..eef0cf0cd9 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextarea/FRExplainTextArea.java @@ -0,0 +1,66 @@ +package com.fr.design.gui.itextarea; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Insets; + +import javax.swing.*; + +import com.fr.design.gui.ilable.UILabel; + +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.layout.FRGUIPaneFactory; + +public class FRExplainTextArea extends JPanel{ + + private static final long serialVersionUID = 1L; + private Icon icon; + private String string; + private int column; + + public FRExplainTextArea(String string,int column){ + this.setString(string); + this.column = column; + init(); + } + + private void init(){ + this.setLayout(new /**/FlowLayout(FlowLayout.LEFT, 0, 0)); + JPanel pane =FRGUIPaneFactory.createX_AXISBoxInnerContainer_S_Pane(); +// pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS)); + + JPanel pane_icon =FRGUIPaneFactory.createBorderLayout_S_Pane(); + pane.add(pane_icon); +// pane_icon.setLayout(FRGUIPaneFactory.createBorderLayout()); + this.setIcon(new ImageIcon("/com/fr/design/images/warnings/warning3.png")); + UILabel UILabel = new UILabel(this.icon, SwingConstants.LEFT); + pane_icon.add(UILabel, BorderLayout.NORTH); + UITextArea jta = new UITextArea(this.string); + jta.setMargin(new Insets(0, 3, 0, 0)); + jta.setForeground(new Color(255, 0, 0)); + jta.setColumns(column); + jta.setLineWrap(true); + jta.setEditable(false); + pane.add(jta); + this.add(pane); + + + } + + public void setIcon(Icon icon) { + this.icon = icon; + } + + public Icon getIcon() { + return icon; + } + + public void setString(String string) { + this.string = string; + } + + public String getString() { + return string; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextarea/UITextArea.java b/designer_base/src/com/fr/design/gui/itextarea/UITextArea.java new file mode 100644 index 0000000000..cf89971b3a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextarea/UITextArea.java @@ -0,0 +1,131 @@ +package com.fr.design.gui.itextarea; + +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; + +public class UITextArea extends JTextArea implements UIObserver { + private UIObserverListener uiObserverListener; + + public UITextArea(int i, int j) { + super(i, j); + initComponents(); + } + + @Override + public Insets getInsets() { + return new Insets(5, 5, 5, 5); + } + + public UITextArea() { + super(); + initComponents(); + } + + public UITextArea(String s) { + super(s); + initComponents(); + } + + private void initComponents() { + setLineWrap(true); + setWrapStyleWord(true); + initListener(); + } + + private void initListener() { + if (shouldResponseChangeListener()) { + getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + attributeChange(); + } + }); + } + + @Override + public void removeUpdate(DocumentEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + attributeChange(); + } + }); + } + + @Override + public void changedUpdate(DocumentEvent e) { + EventQueue.invokeLater(new Runnable() { + public void run() { + attributeChange(); + } + }); + } + }); + } + } + + private void attributeChange() { + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + } + + @Override + /** + * + */ + public UITextAreaUI getUI() { + return (UITextAreaUI) ui; + } + + @Override + /** + * + */ + public void updateUI() { + this.setUI(new UITextAreaUI(this)); + } + + @Override + protected void paintBorder(Graphics g) { + + } + + + @Override + /** + * + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * @return + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * @param args + */ + public static void main(String... args) { + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(new BorderLayout()); + UITextArea bb = new UITextArea("123455weoijweio reiwj kewl jfejkfljds kl jfldk jfk jdskfjkdsfklj dkl jfsdjf"); + content.add(bb, BorderLayout.CENTER); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextarea/UITextAreaUI.java b/designer_base/src/com/fr/design/gui/itextarea/UITextAreaUI.java new file mode 100644 index 0000000000..86c3a17223 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextarea/UITextAreaUI.java @@ -0,0 +1,56 @@ +package com.fr.design.gui.itextarea; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.JComponent; +import javax.swing.plaf.basic.BasicTextAreaUI; +import javax.swing.text.JTextComponent; + +import com.fr.design.constants.UIConstants; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class UITextAreaUI extends BasicTextAreaUI { + protected boolean isRollOver; + private JComponent textField; + + public UITextAreaUI(final JComponent textField) { + super(); + this.textField = textField; + this.textField.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + isRollOver = true; + textField.repaint(); + } + + @Override + public void mouseExited(MouseEvent e) { + isRollOver = false; + textField.repaint(); + } + }); + } + + @Override + protected void paintBackground(Graphics g) { + JTextComponent editor = getComponent(); + int width = editor.getWidth(); + int height = editor.getHeight(); + Graphics2D g2d = (Graphics2D)g; + g2d.clearRect(0, 0, width, height); + if(isRollOver && textField.isEnabled() && ((UITextArea)textField).isEditable()) { + Shape shape = new RoundRectangle2D.Double(1, 1, width - 3, height - 3, UIConstants.ARC, UIConstants.ARC); + GUIPaintUtils.paintBorderShadow(g2d, 3, shape, UIConstants.HOVER_BLUE, Color.white); + } else { + g2d.setColor(UIConstants.LINE_COLOR); + g2d.drawRoundRect(1, 1, width - 2, height - 2, UIConstants.ARC, UIConstants.ARC); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/AutoCompletionDemo.java b/designer_base/src/com/fr/design/gui/itextfield/AutoCompletionDemo.java new file mode 100644 index 0000000000..a57f097f22 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/AutoCompletionDemo.java @@ -0,0 +1,76 @@ +package com.fr.design.gui.itextfield; + +import java.io.File; + +import com.fr.design.gui.ilable.UILabel; +import javax.swing.UIManager; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.stable.ArrayUtils; + +public class AutoCompletionDemo extends javax.swing.JFrame { + private UIAutoCompletionField autoCompletionField1; + private UIButton jButton1; + private UILabel jLabel1; + + public AutoCompletionDemo() { + initComponents(); + Object[] v = new String[0]; + File file = new File(System.getProperty("user.home")); + String[] files = file.list(); + for (String filename : files) + v= ArrayUtils.add(v, filename); + autoCompletionField1.setFilter(new DefaultCompletionFilter(v)); + } + + private void initComponents() { + autoCompletionField1 = new UIAutoCompletionField(); + autoCompletionField1.setText(".F"); + autoCompletionField1.addDocumentListener(); + jButton1 = new UIButton(); + jLabel1 = new UILabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + + jButton1.setText("Exit"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + System.exit(0); + } + }); + + jLabel1.setText("

fuck

"); + jLabel1.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( + layout.createSequentialGroup() + .addContainerGap() + .addGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 303, Short.MAX_VALUE) + .addComponent(autoCompletionField1, javax.swing.GroupLayout.DEFAULT_SIZE, 303, Short.MAX_VALUE) + .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING)).addContainerGap())); + layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup( + javax.swing.GroupLayout.Alignment.TRAILING, + layout.createSequentialGroup().addContainerGap().addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(autoCompletionField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jButton1).addContainerGap())); + pack(); + } + + public static void main(String args[]) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ex) { + } + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + new AutoCompletionDemo().setVisible(true); + } + }); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/CompletionFilter.java b/designer_base/src/com/fr/design/gui/itextfield/CompletionFilter.java new file mode 100644 index 0000000000..934739b20e --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/CompletionFilter.java @@ -0,0 +1,8 @@ +package com.fr.design.gui.itextfield; + +import java.util.ArrayList; + +public interface CompletionFilter { + + public ArrayList filter(String text); +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/DefaultCompletionFilter.java b/designer_base/src/com/fr/design/gui/itextfield/DefaultCompletionFilter.java new file mode 100644 index 0000000000..82b8ad640d --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/DefaultCompletionFilter.java @@ -0,0 +1,28 @@ +package com.fr.design.gui.itextfield; + +import java.util.ArrayList; + + + +public class DefaultCompletionFilter implements CompletionFilter { + + private Object[] vector; + + public DefaultCompletionFilter(Object[] v) { + vector = v; + } + + public ArrayList filter(String text) { + ArrayList list = new ArrayList(); + //不区分大小写 + String txt = text.trim().toLowerCase(); + int length = txt.length(); + for (int i = 0; i < vector.length; i++) { + Object o = vector[i]; + String str = o.toString().toLowerCase(); + if (length == 0 || str.startsWith(txt)) + list.add(o); + } + return list; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/EditTextField.java b/designer_base/src/com/fr/design/gui/itextfield/EditTextField.java new file mode 100644 index 0000000000..b0decbdb28 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/EditTextField.java @@ -0,0 +1,55 @@ +package com.fr.design.gui.itextfield; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Toolkit; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + + +/** + * Number Field. + */ +public class EditTextField extends UIGridTextField { + private int maxLength = 24; + + public EditTextField() { + this(10000); + } + + public EditTextField(int maxLength) { + this.maxLength = maxLength; + setDocument(new TextDocument()); + } + + public int getMaxLength() { + return maxLength; + } + + public void setMaxLength(int maxLength) { + this.maxLength = maxLength; + } + + @Override + public void paint(Graphics g) { + FRGraphics2D FRg2d = new FRGraphics2D((Graphics2D)g); + super.paint(FRg2d); + } + + class TextDocument extends PlainDocument { + public TextDocument() { + } + + @Override + public void insertString(int offset, String s, AttributeSet a) throws BadLocationException { + String str = getText(0, getLength()); + if (str != null && str.length() > getMaxLength()) { + Toolkit.getDefaultToolkit().beep(); + return; + } + super.insertString(offset, s, a); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/FRGraphics2D.java b/designer_base/src/com/fr/design/gui/itextfield/FRGraphics2D.java new file mode 100644 index 0000000000..96d486d8b3 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/FRGraphics2D.java @@ -0,0 +1,397 @@ +package com.fr.design.gui.itextfield; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.RenderingHints.Key; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.Map; + +import com.fr.base.GraphHelper; + +public class FRGraphics2D extends Graphics2D { + Graphics2D g2d; + + public FRGraphics2D (Graphics2D sg2d) { + this.g2d = sg2d; + } + @Override + public void draw(Shape s) { + g2d.draw(s); + } + + @Override + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { + return g2d.drawImage(img, xform, obs); + } + + @Override + public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { + g2d.drawImage(img, op, x, y); + } + + @Override + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + g2d.drawRenderedImage(img, xform); + } + + @Override + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + g2d.drawRenderableImage(img, xform); + } + + @Override + public void drawString(String str, int x, int y) { + GraphHelper.drawString(g2d, str, x, y); + } + + @Override + public void drawString(String str, float x, float y) { + GraphHelper.drawString(g2d, str, x, y); + } + + @Override + public void drawString(AttributedCharacterIterator iterator, int x, int y) { + g2d.drawString(iterator, x, y); + } + + @Override + public void drawString(AttributedCharacterIterator iterator, float x, + float y) { + g2d.drawString(iterator, x, y); + } + + @Override + public void drawGlyphVector(GlyphVector g, float x, float y) { + g2d.drawGlyphVector(g, x, y); + } + + @Override + public void fill(Shape s) { + g2d.fill(s); + } + + @Override + public boolean hit(Rectangle rect, Shape s, boolean onStroke) { + return g2d.hit(rect, s, onStroke); + } + + @Override + public GraphicsConfiguration getDeviceConfiguration() { + return g2d.getDeviceConfiguration(); + } + + @Override + public void setComposite(Composite comp) { + g2d.setComposite(comp); + } + + @Override + public void setPaint(Paint paint) { + g2d.setPaint(paint); + } + + @Override + public void setStroke(Stroke s) { + g2d.setStroke(s); + } + + @Override + public void setRenderingHint(Key hintKey, Object hintValue) { + g2d.setRenderingHint(hintKey, hintValue); + } + + @Override + public Object getRenderingHint(Key hintKey) { + return g2d.getRenderingHint(hintKey); + } + + @Override + public void setRenderingHints(Map hints) { + g2d.setRenderingHints(hints); + } + + @Override + public void addRenderingHints(Map hints) { + g2d.addRenderingHints(hints); + } + + @Override + public RenderingHints getRenderingHints() { + return g2d.getRenderingHints(); + } + + @Override + public void translate(int x, int y) { + g2d.translate(x, y); + } + + @Override + public void translate(double tx, double ty) { + g2d.translate(tx, ty); + } + + @Override + public void rotate(double theta) { + g2d.rotate(theta); + } + + @Override + public void rotate(double theta, double x, double y) { + g2d.rotate(theta, x, y); + } + + @Override + public void scale(double sx, double sy) { + g2d.scale(sx, sy); + } + + @Override + public void shear(double shx, double shy) { + g2d.shear(shx, shy); + } + + @Override + public void transform(AffineTransform Tx) { + g2d.transform(Tx); + } + + @Override + public void setTransform(AffineTransform Tx) { + g2d.setTransform(Tx); + } + + @Override + public AffineTransform getTransform() { + return g2d.getTransform(); + } + + @Override + public Paint getPaint() { + return g2d.getPaint(); + } + + @Override + public Composite getComposite() { + return g2d.getComposite(); + } + + @Override + public void setBackground(Color color) { + g2d.setBackground(color); + } + + @Override + public Color getBackground() { + return g2d.getBackground(); + } + + @Override + public Stroke getStroke() { + return g2d.getStroke(); + } + + @Override + public void clip(Shape s) { + g2d.clip(s); + } + + @Override + public FontRenderContext getFontRenderContext() { + return g2d.getFontRenderContext(); + } + + @Override + public Graphics create() { + return new FRGraphics2D((Graphics2D) g2d.create()); + } + + @Override + public Color getColor() { + return g2d.getColor(); + } + + @Override + public void setColor(Color c) { + g2d.setColor(c); + } + + @Override + public void setPaintMode() { + g2d.setPaintMode(); + } + + @Override + public void setXORMode(Color c1) { + g2d.setXORMode(c1); + } + + @Override + public Font getFont() { + return g2d.getFont(); + } + + @Override + public void setFont(Font font) { + g2d.setFont(font); + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return g2d.getFontMetrics(f); + } + + @Override + public Rectangle getClipBounds() { + return g2d.getClipBounds(); + } + + @Override + public void clipRect(int x, int y, int width, int height) { + g2d.clipRect(x, y, width, height); + } + + @Override + public void setClip(int x, int y, int width, int height) { + g2d.setClip(x, y, width, height); + } + + @Override + public Shape getClip() { + return g2d.getClip(); + } + + @Override + public void setClip(Shape clip) { + g2d.setClip(clip); + } + + @Override + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + g2d.copyArea(x, y, width, height, dx, dy); + } + + @Override + public void drawLine(int x1, int y1, int x2, int y2) { + g2d.drawLine(x1, y1, x2, y2); + } + + @Override + public void fillRect(int x, int y, int width, int height) { + g2d.fillRect(x, y, width, height); + } + + @Override + public void clearRect(int x, int y, int width, int height) { + g2d.clearRect(x, y, width, height); + } + + @Override + public void drawRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) { + g2d.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + @Override + public void fillRoundRect(int x, int y, int width, int height, + int arcWidth, int arcHeight) { + g2d.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + @Override + public void drawOval(int x, int y, int width, int height) { + g2d.drawOval(x, y, width, height); + } + + @Override + public void fillOval(int x, int y, int width, int height) { + g2d.fillOval(x, y, width, height); + } + + @Override + public void drawArc(int x, int y, int width, int height, int startAngle, + int arcAngle) { + g2d.drawArc(x, y, width, height, startAngle, arcAngle); + } + + @Override + public void fillArc(int x, int y, int width, int height, int startAngle, + int arcAngle) { + g2d.fillArc(x, y, width, height, startAngle, arcAngle); + } + + @Override + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) { + g2d.drawPolyline(xPoints, yPoints, nPoints); + } + + @Override + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) { + g2d.drawPolygon(xPoints, yPoints, nPoints); + } + + @Override + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) { + g2d.fillPolygon(xPoints, yPoints, nPoints); + } + + @Override + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + return g2d.drawImage(img, x, y, observer); + } + + @Override + public boolean drawImage(Image img, int x, int y, int width, int height, + ImageObserver observer) { + return g2d.drawImage(img, x, y, width, height, observer); + } + + @Override + public boolean drawImage(Image img, int x, int y, Color bgcolor, + ImageObserver observer) { + return g2d.drawImage(img, x, y, bgcolor, observer); + } + + @Override + public boolean drawImage(Image img, int x, int y, int width, int height, + Color bgcolor, ImageObserver observer) { + return g2d.drawImage(img, x, y, width, height, bgcolor, observer); + } + + @Override + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { + return g2d.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + + @Override + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, + int sx1, int sy1, int sx2, int sy2, Color bgcolor, + ImageObserver observer) { + return g2d.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer); + } + + @Override + public void dispose() { + g2d.dispose(); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/PlaceholderTextField.java b/designer_base/src/com/fr/design/gui/itextfield/PlaceholderTextField.java new file mode 100644 index 0000000000..3ff686099a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/PlaceholderTextField.java @@ -0,0 +1,54 @@ +package com.fr.design.gui.itextfield; + +import javax.swing.text.Document; +import java.awt.*; + +public class PlaceholderTextField extends UITextField { + + private String placeholder; + + public PlaceholderTextField() { + } + + public PlaceholderTextField( + final Document pDoc, + final String pText, + final int pColumns) { + super(pDoc, pText, pColumns); + } + + public PlaceholderTextField(final int pColumns) { + super(pColumns); + } + + public PlaceholderTextField(final String pText) { + super(pText); + } + + public PlaceholderTextField(final String pText, final int pColumns) { + super(pText, pColumns); + } + + public String getPlaceholder() { + return placeholder; + } + + @Override + protected void paintComponent(final Graphics pG) { + super.paintComponent(pG); + if (placeholder.length() == 0 || getText().length() > 0) { + return; + } + final Graphics2D g = (Graphics2D) pG; + g.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(getDisabledTextColor()); + g.drawString(placeholder, getInsets().left, pG.getFontMetrics() + .getMaxAscent() + getInsets().top + 1); + } + + public void setPlaceholder(final String s) { + placeholder = s; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/TextFieldUI.java b/designer_base/src/com/fr/design/gui/itextfield/TextFieldUI.java new file mode 100644 index 0000000000..baf9980ff2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/TextFieldUI.java @@ -0,0 +1,53 @@ +package com.fr.design.gui.itextfield; + +import java.awt.Graphics; + +import javax.swing.plaf.metal.MetalTextFieldUI; +import javax.swing.text.JTextComponent; + +import de.muntjak.tinylookandfeel.Theme; + +public class TextFieldUI extends MetalTextFieldUI { + + + protected void paintBackground(Graphics g) { + JTextComponent editor = getComponent(); + // We will only be here if editor is opaque, so we don't have to test + + if(editor.isEnabled()) { + if(editor.isEditable()) { + g.setColor(editor.getBackground()); + } + else { + // not editable + if(editor.getBackground().equals(Theme.textBgColor[Theme.style].getColor())) { + // set default panel background + g.setColor(Theme.backColor[Theme.style].getColor()); + } + else { + // color changed by user - set textfield background + g.setColor(editor.getBackground()); + } + } + + g.fillRect(0, 0, editor.getWidth(), editor.getHeight()); + } + else { + if(editor.getBackground().equals(Theme.textBgColor[Theme.style].getColor())) { + g.setColor(Theme.textDisabledBgColor[Theme.style].getColor()); + } + else { + // color changed by user - set textfield background + g.setColor(editor.getBackground()); + } + + g.fillRect(0, 0, editor.getWidth(), editor.getHeight()); + + if(Theme.style != Theme.YQ_STYLE) return; + + g.setColor(Theme.backColor[Theme.style].getColor()); + g.drawRect(1, 1, editor.getWidth() - 3, editor.getHeight() - 3); + g.drawRect(2, 2, editor.getWidth() - 5, editor.getHeight() - 5); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/UIAutoCompletionField.java b/designer_base/src/com/fr/design/gui/itextfield/UIAutoCompletionField.java new file mode 100644 index 0000000000..de6bccd865 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/UIAutoCompletionField.java @@ -0,0 +1,280 @@ +package com.fr.design.gui.itextfield; + +import com.fr.design.gui.imenu.UIListPopup; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.ComparatorUtils; +import com.fr.stable.OperatingSystem; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.text.AbstractDocument; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; + +import java.awt.Dimension; +import java.awt.LayoutManager; +import java.awt.event.*; +import java.util.ArrayList; + +public class UIAutoCompletionField extends UITextField implements DocumentListener, MouseListener, ListSelectionListener, ActionListener, KeyListener { + + + private static final long serialVersionUID = 1L; + private static int DEFAULT_PREFERRED_HEIGHT = 100; + private static int PAGE_UP = -5; + private static int PAGE_DOWN = 5; + public boolean isOpen = false; + private int preferredHeight = DEFAULT_PREFERRED_HEIGHT; + private CompletionFilter filter; + private UIListPopup popup; + + + public void setFilter(CompletionFilter f) { + filter = f; + } + + public UIAutoCompletionField() { + popup = new UIListPopup(); + // getDocument().addDocumentListener(this); + addMouseListener(this); + popup.addListSelectionListener(this); + addActionListener(this); + addKeyListener(this); + } + + // 奶奶的 setText和释放UITextField内存时也会触发DocumentListener + // 只能在setText后加上DocumentListener了 + + /** + * + */ + public void addDocumentListener() { + getDocument().addDocumentListener(this); + } + + /** + * + */ + public void removeDocumentListener() { + getDocument().removeDocumentListener(this); + } + + /** + * @param h + */ + public void setPopupPreferredHeight(int h) { + preferredHeight = h; + } + + private boolean isListChange(ArrayList array) { + if (array.size() != popup.getItemCount()) { + return true; + } + for (int i = 0; i < array.size(); i++) { + if (!ComparatorUtils.equals(array.get(i), popup.getItem(i))) { + return true; + } + } + return false; + } + + private void textChanged() { + if (OperatingSystem.isMacOS()) { + return; + } + if (!popup.isVisible()) { + showPopup(); + requestFocus(); + } + if (filter != null) { + ArrayList array = filter.filter(getText()); + changeList(array); + } + } + + private void showPopup() { + popup.setFocusable(false); + popup.setPopupSize(getWidth(), preferredHeight); + popup.show(this, 0, getHeight() - 1); + } + + private void changeList(ArrayList array) { + if (array.size() == 0) { + if (popup.isVisible()) { + popup.setVisible(false); + } + } else { + if (!popup.isVisible()) { +// showPopup(); + } + } + if (isListChange(array) && array.size() != 0) { + popup.setList(array); + } + } + + /** + * @param e + */ + public void insertUpdate(DocumentEvent e) { + textChanged(); + } + + /** + * @param e + */ + public void removeUpdate(DocumentEvent e) { + textChanged(); + } + + /** + * @param e + */ + public void changedUpdate(DocumentEvent e) { + textChanged(); + } + + /** + * @param e + */ + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() > 1 && !popup.isVisible()) { + textChanged(); + } + } + + /** + * @param e + */ + public void mousePressed(MouseEvent e) { + } + + /** + * @param e + */ + public void mouseReleased(MouseEvent e) { + } + + /** + * @param e + */ + public void mouseEntered(MouseEvent e) { + } + + /** + * @param e + */ + public void mouseExited(MouseEvent e) { + } + + + /** + * @param e + */ + public void valueChanged(ListSelectionEvent e) { + JList list = (JList) e.getSource(); + String text = list.getSelectedValue().toString(); + setText(text); + popup.setVisible(false); + } + + /** + * @param e + */ + public void actionPerformed(ActionEvent e) { + if (popup.isVisible()) { + Object o = popup.getSelectedValue(); + if (o != null) { + setText(o.toString()); + } + popup.setVisible(false); + } + this.selectAll(); + this.requestFocus(); + } + + /** + * @param e + */ + public void keyTyped(KeyEvent e) { + } + + /** + * @param e + */ + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_DOWN) { + if (popup.isVisible()) { + if (!popup.isSelected()) { + popup.setSelectedIndex(0); + } else { + popup.setSelectedIndex(popup.getSelectedIndex() + 1); + } + + } + } else if (e.getKeyCode() == KeyEvent.VK_UP) { + if (popup.isVisible()) { + if (!popup.isSelected()) { + popup.setLastOneSelected(); + } else { + popup.setSelectedIndex(popup.getSelectedIndex() - 1); + } + } + } else if (e.getKeyCode() == KeyEvent.VK_PAGE_DOWN) { + if (popup.isVisible()) { + if (!popup.isSelected()) { + popup.setSelectedIndex(0); + } else { + popup.setSelectedIndex(popup.getSelectedIndex() + PAGE_DOWN); + } + } + } else if (e.getKeyCode() == KeyEvent.VK_PAGE_UP) { + if (popup.isVisible()) { + if (!popup.isSelected()) { + popup.setLastOneSelected(); + } else { + popup.setSelectedIndex(popup.getSelectedIndex() + PAGE_UP); + } + + } + } + } + + /** + * @param e + */ + public void keyReleased(KeyEvent e) { + } + + @Override + /** + * + */ + public void setText(String t) { + if (this.isOpen == true) { + if (!UIAutoCompletionField.this.isShowing()) { + return; + } + } + try { + Document doc = getDocument(); + if (doc instanceof AbstractDocument) { + ((AbstractDocument) doc).replace(0, doc.getLength(), t, null); + this.setSelectionStart(0); + this.setSelectionEnd(this.getText().length()); + } else { + doc.remove(0, doc.getLength()); + doc.insertString(0, t, null); + this.setSelectionStart(0); + this.setSelectionEnd(this.getText().length()); + } + } catch (BadLocationException e) { + UIManager.getLookAndFeel().provideErrorFeedback(UIAutoCompletionField.this); + } + + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/UIGridTextField.java b/designer_base/src/com/fr/design/gui/itextfield/UIGridTextField.java new file mode 100644 index 0000000000..a3e23a600b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/UIGridTextField.java @@ -0,0 +1 @@ +package com.fr.design.gui.itextfield; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.Document; /** * Author : Shockway * Date: 13-5-20 * Time: 上午10:04 */ public class UIGridTextField extends JTextField implements UIObserver { private UIObserverListener uiObserverListener; /** * */ public UIGridTextField() { super(); initListener(); } /** * * @param columns */ public UIGridTextField(int columns) { super(columns); initListener(); } /** * * @param text * @param columns */ public UIGridTextField(String text, int columns) { super(text, columns); initListener(); } /** * * @param text */ public UIGridTextField(String text) { super(text); initListener(); } /** * * @param doc * @param text * @param columns */ public UIGridTextField(Document doc, String text, int columns) { super(doc, text, columns); initListener(); } protected void initListener() { if (shouldResponseChangeListener()) { getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { attributeChange(); } @Override public void removeUpdate(DocumentEvent e) { attributeChange(); } @Override public void changedUpdate(DocumentEvent e) { attributeChange(); } }); } } protected void attributeChange() { if (uiObserverListener != null) { uiObserverListener.doChange(); } } /** * * @param listener 观察者监听事件 */ public void registerChangeListener(UIObserverListener listener) { uiObserverListener = listener; } /** * * @return */ public boolean shouldResponseChangeListener() { return true; } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/UINumberField.java b/designer_base/src/com/fr/design/gui/itextfield/UINumberField.java new file mode 100644 index 0000000000..eb24fab9b5 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/UINumberField.java @@ -0,0 +1,250 @@ +package com.fr.design.gui.itextfield; + +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Toolkit; + +import javax.swing.JFrame; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +import com.fr.base.Utils; +import com.fr.design.gui.ilable.UILabel; +import com.fr.general.ComparatorUtils; +import com.fr.stable.CoreConstants; +import com.fr.stable.StringUtils; + +/** + * Number Field. + */ +public class UINumberField extends UITextField { + public static final double ERROR_VALUE = Double.MAX_VALUE + 4.44; // peter:错误的值. + /** + * 整数部分的长度 + */ + private int maxIntegerLength = 24; + /** + * 小数部分的长度 + */ + private static final int DEFAULTMAXDECIMALLENTH = 16; + private static final int TESTMAXVALUE = 100; + private static final int TESTMINVALUE = -10; + private int maxDecimalLength = 16; + private double minValue = -Double.MAX_VALUE; + private double maxValue = Double.MAX_VALUE; + + private boolean isContentChanged = false; + + public UINumberField() { + this(32, 16); + } + + public UINumberField(int columns) { + this(); + setColumns(columns); + } + + public UINumberField(int maxIntegerLength, int maxDecimalLength) { + this(maxIntegerLength, maxDecimalLength, -Double.MAX_VALUE, Double.MAX_VALUE); + } + + public UINumberField(int maxIntegerLength, int maxDecimalLength, double minValue, double maxValue) { + this.maxIntegerLength = maxIntegerLength; + this.maxDecimalLength = maxDecimalLength; + this.minValue = minValue; + this.maxValue = maxValue; + + setFieldDocument(); + } + + public void setFieldDocument(){ + setDocument(new NumberDocument()); + initListener(); + } + + public int getMaxIntegerLength() { + return maxIntegerLength; + } + + public void setMaxIntegerLength(int maxIntegerLength) { + this.maxIntegerLength = maxIntegerLength; + } + + public int getMaxDecimalLength() { + return maxDecimalLength; + } + + public void setMaxDecimalLength(int maxDecimalLength) { + this.maxDecimalLength = maxDecimalLength; + } + + public double getMinValue() { + return minValue; + } + + public void setMinValue(double minValue) { + this.minValue = minValue; + } + + public double getMaxValue() { + return maxValue; + } + + public void setMaxValue(double maxValue) { + this.maxValue = maxValue; + } + + /** + * Set the value. + */ + public void setValue(double value) { + this.setText(Utils.doubleToString(value)); + } + + /** + * Return the value. + */ + public double getValue() throws NumberFormatException { + try { + if (this.getText().length() == 0) { + return 0; + } + + return Double.parseDouble(this.getText()); + } catch (NumberFormatException numberFormatException) { + return UINumberField.ERROR_VALUE; + } + } + + /** + * Retusn text value. + */ + public String getTextValue() { + return this.getText(); + } + + /** + * Set property integer. + * + * @param integer + * New value of property integer. + */ + public void setInteger(boolean integer) { + if (integer) { + this.maxDecimalLength = 0; + } else { + this.maxDecimalLength = DEFAULTMAXDECIMALLENTH; + } + } + + /** + * Check whether the content changed. + */ + public boolean isContentChanged() { + return isContentChanged; + } + + public void setisContentChanged(boolean isContentChanged){ + this.isContentChanged = isContentChanged; + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(super.getPreferredSize().width, 20); + } + + class NumberDocument extends PlainDocument { + public NumberDocument() { + } + public boolean checkString(int offset, String s, String str) { + return (ComparatorUtils.equals(s,"F") + || ComparatorUtils.equals(s,"f") + || ComparatorUtils.equals(s,"D") + || ComparatorUtils.equals(s,"d") + ||(ComparatorUtils.equals(str.trim(),"0") && !ComparatorUtils.equals(s.substring(0, 1),".") && offset != 0)// 第一位是0时,第二位只能为小数点 + ||(ComparatorUtils.equals(s,".") && maxDecimalLength == 0)); + + } + + public void insertString(int offset, String s, AttributeSet a) throws BadLocationException { + String str = getText(0, getLength()); + + // 不能为f,F,d,D + if (checkString(offset,s, str) ) { + Toolkit.getDefaultToolkit().beep(); + return; + } + + String strNew = str.substring(0, offset) + s + str.substring(offset, getLength()); + if(notChange(strNew)) { + return; + } + setisContentChanged(true); + super.insertString(offset, s, a); + } + + // kunsnat: 这种限制输入 有个不好的地方, 比如删除时: 10.1 最大值限定100, 那么就删除中间的小数点之后变为101, 超出了100. + // 但是直接限制不能删除中间类似小数点, 那么也可能遇到: 最小值10 , 从100变化到其中的19, 就很难.. + private boolean notChange(String strNew) { + boolean noChange = false; + strNew = strNew.replaceFirst("-", StringUtils.EMPTY); // 控制能输入负数 + boolean isMinus = strNew.startsWith("-"); + String strIntPart; + String strDecPart = StringUtils.EMPTY; + int decPos = strNew.indexOf(CoreConstants.DOT); + if (decPos > -1) { + strIntPart = strNew.substring(0, decPos); + strDecPart = strNew.substring(decPos + 1); + } else { + strIntPart = strNew; + } + if (isOverMaxOrMinValue(strIntPart, strDecPart, strNew)) { + Toolkit.getDefaultToolkit().beep(); + noChange = true; + } + + try { + if (!ComparatorUtils.equals(strNew, StringUtils.EMPTY) && !ComparatorUtils.equals(strNew, "-")) {// 控制能输入负数 + double d = Double.parseDouble(strNew) * (isMinus ? -1 : 1); + if (d < minValue || d > maxValue) { + throw new Exception(); + } + } + } catch (Exception e) { + Toolkit.getDefaultToolkit().beep(); + noChange = true; + } + + return noChange; + } + + private boolean isOverMaxOrMinValue(String strIntPart, String strDecPart, String strNew) { + return strIntPart.length() > maxIntegerLength + || strDecPart.length() > maxDecimalLength + || (strNew.length() > 1 && ComparatorUtils.equals(strNew.substring(0, 1), "0") && !ComparatorUtils.equals(strNew.substring(1, 2),".")); + } + } + + /** + * 测试程序 + */ + public static void main(String[] args) { + JFrame frame = new JFrame(""); + frame.setSize(400, 320); + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2); + UINumberField tt = new UINumberField(); + tt.setMinValue(0.0); + tt.setMaxValue(100.0); + frame.getContentPane().setLayout(new GridLayout(10, 2)); + frame.getContentPane().add(new UILabel("New JNumberField()")); + frame.getContentPane().add(tt); + frame.getContentPane().add(new UILabel("New JNumberField(2)")); + frame.getContentPane().add(new UILabel("New JNumberField(8,2)")); + frame.getContentPane().add(new UINumberField(8, 2)); + frame.getContentPane().add(new UILabel("New JNumberField(5,2,-10,100)")); + frame.getContentPane().add(new UINumberField(5, 2, TESTMINVALUE, TESTMAXVALUE)); + frame.setVisible(true); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/UISearchTextField.java b/designer_base/src/com/fr/design/gui/itextfield/UISearchTextField.java new file mode 100644 index 0000000000..683477bd48 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/UISearchTextField.java @@ -0,0 +1 @@ +package com.fr.design.gui.itextfield; import com.fr.design.constants.UIConstants; import com.fr.design.gui.ilable.UILabel; import com.fr.general.Inter; import javax.swing.*; import javax.swing.text.Document; import java.awt.*; import java.awt.event.*; import java.awt.geom.RoundRectangle2D; /** * Created by IntelliJ IDEA. * Author : Richer * Version: 7.0.3 * Date: 13-1-4 * Time: 上午11:07 * 带图标的文本框,可以用作搜索等用途 */ public class UISearchTextField extends UITextField { private UILabel iconLabel = new UILabel(UIConstants.SEARCH_ICON); private UILabel clearLabel = new UILabel(UIConstants.CLEAR_ICON); private UILabel infoLabel = new UILabel(Inter.getLocText("Search")); private Dimension iconSize; private Dimension infoSize; private int iconPosition = SwingConstants.LEFT; private boolean showClearIcon = true; private CellRendererPane cellRendererPane = new CellRendererPane(); public UISearchTextField() { initTextField(); } public UISearchTextField(String text) { super(text); initTextField(); } public UISearchTextField(int columns) { super(columns); initTextField(); } public UISearchTextField(String text, int columns) { super(text, columns); initTextField(); } public UISearchTextField(Document doc, String text, int columns) { super(doc, text, columns); initTextField(); } private void initTextField() { iconLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); iconLabel.setToolTipText(Inter.getLocText("Search")); clearLabel.setToolTipText(Inter.getLocText("Clear")); clearLabel.setOpaque(false); iconSize = iconLabel.getPreferredSize(); infoSize = infoLabel.getPreferredSize(); infoLabel.setEnabled(false); this.addMouseListener(new MouseAdapter() { public void mouseExited(MouseEvent e) { setMouseComponent(null); } public void mouseClicked(MouseEvent e) { if (mouseCom == clearLabel) { setText(""); } else if (mouseCom == iconLabel) { handleIconClick(); } } }); this.addMouseMotionListener(new MouseMotionListener() { public void mouseMoved(MouseEvent e) { JComponent com = getComponentAtPoint(e.getPoint()); setMouseComponent(com); } public void mouseDragged(MouseEvent e) { } }); this.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { repaint(); } public void focusGained(FocusEvent e) { repaint(); } }); } private void handleIconClick() { } public String getToolTipText(MouseEvent event) { event.getPoint(); if (mouseCom == null) { return null; } if (mouseCom == this) { return super.getToolTipText(event); } return mouseCom.getToolTipText(event); } private int iconGap = 3; public Insets getInsets() { Insets insets = super.getInsets(); if (iconPosition == SwingConstants.LEFT) { insets.left += iconSize.width + iconGap + 2; if (this.getText() != null && this.getText().length() != 0 && showClearIcon) { insets.right += iconSize.width + iconGap + 2; } else { insets.right += iconGap; } } else { insets.left += iconGap; if (this.getText() != null && this.getText().length() != 0 && showClearIcon) { insets.right += iconSize.width + iconGap + 2; } else { insets.right += iconGap; } } return insets; } private JComponent getComponentAtPoint(Point point) { int x = (int) point.getX(); int y = (int) point.getY(); if (!contains(x, y)) { return null; } if (iconPosition == SwingConstants.LEFT) { if (x < iconSize.width + iconGap + 2) { return iconLabel; } if (getText() != null && getText().length() != 0 && showClearIcon) { if (x > getWidth() - iconSize.width - iconGap) { return clearLabel; } } } else { if (this.getText() == null || this.getText().length() == 0) { if (x > getWidth() - iconSize.width - iconGap - 2) { return iconLabel; } } if (getText() != null && getText().length() != 0 && showClearIcon) { if (x > getWidth() - iconSize.width - iconGap - 2) { return clearLabel; } } } return this; } private JComponent mouseCom; private void setMouseComponent(JComponent com) { if (mouseCom == com) { return; } if (mouseCom != null && mouseCom instanceof UILabel) { mouseCom.setBorder(null); } mouseCom = com; if (mouseCom != null && mouseCom instanceof UILabel) { mouseCom.setBorder(BorderFactory.createLineBorder(Color.ORANGE, 1)); } this.repaint(); if (mouseCom == null || mouseCom == clearLabel) { setCursor(Cursor.getDefaultCursor()); return; } if (mouseCom == this) { setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); return; } if (mouseCom == iconLabel) { setCursor(iconLabel.getCursor()); } } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; int y = (int) (this.getHeight() / 2.0 - iconSize.getHeight() / 2); if (iconPosition == SwingConstants.LEFT) { cellRendererPane.paintComponent(g2d, iconLabel, this, iconGap, y, iconSize.width, iconSize.height); if (this.getText() != null && this.getText().length() != 0 && showClearIcon) { cellRendererPane.paintComponent(g2d, clearLabel, this, this.getWidth() - iconSize.width - iconGap, y, iconSize.width, iconSize.height); } } else { if (this.getText() == null || this.getText().length() == 0) { cellRendererPane.paintComponent(g2d, iconLabel, this, this.getWidth() - iconSize.width - iconGap, y, iconSize.width, iconSize.height); } else { if (showClearIcon) { cellRendererPane.paintComponent(g2d, clearLabel, this, this.getWidth() - iconSize.width - iconGap, y, iconSize.width, iconSize.height); } } } if (!this.isFocusOwner()) { if (this.getText() == null || this.getText().length() == 0) { int x = iconGap + 2; if (iconPosition == SwingConstants.LEFT) { x = iconSize.width + iconGap + 2; } y = (int) (this.getHeight() / 2.0 - infoSize.getHeight() / 2); cellRendererPane.paintComponent(g2d, infoLabel, this, x, y, infoSize.width, infoSize.height); } } } public Dimension getPreferredSize() { Insets s = super.getInsets(); Insets t = this.getInsets(); Dimension preferredSize = super.getPreferredSize(); preferredSize.setSize(preferredSize.width - (t.left + t.right - s.left - s.right), preferredSize.height + 2); return preferredSize; } protected void paintBorder(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); if (this.isFocusOwner()) { g2d.setStroke(new BasicStroke(1.5f)); } else { g2d.setStroke(new BasicStroke(1f)); } RoundRectangle2D.Double rect = new RoundRectangle2D.Double(0, 0, this.getWidth() - 2, this.getHeight() - 2, 4, 4); g2d.setColor(new Color(0, 100, 100, 150)); g2d.draw(rect); } public int getIconPosition() { return iconPosition; } public void setIconPosition(int iconPosition) { this.iconPosition = iconPosition; this.invalidate(); this.repaint(); } public boolean isShowClearIcon() { return showClearIcon; } public void setShowClearIcon(boolean showClearIcon) { this.showClearIcon = showClearIcon; this.repaint(); } public static void main(String[] args) { JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT)); UISearchTextField comp = new UISearchTextField(20); p.add(comp); comp = new UISearchTextField(20); comp.setShowClearIcon(false); p.add(comp); comp = new UISearchTextField(20); comp.setIconPosition(SwingConstants.RIGHT); p.add(comp); comp = new UISearchTextField(20); comp.setShowClearIcon(false); comp.setIconPosition(SwingConstants.RIGHT); p.add(comp); p.add(new JTextField(20)); JFrame frame = new JFrame(); frame.setTitle("UITextField"); frame.setContentPane(p); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/UITextField.java b/designer_base/src/com/fr/design/gui/itextfield/UITextField.java new file mode 100644 index 0000000000..7a451593bd --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/UITextField.java @@ -0,0 +1,210 @@ +package com.fr.design.gui.itextfield; + +import java.awt.*; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Document; + +import com.fr.design.event.GlobalNameListener; +import com.fr.design.event.GlobalNameObserver; +import com.fr.design.event.UIObserver; +import com.fr.design.event.UIObserverListener; +import com.fr.stable.Constants; +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * @author Jerry + */ +public class UITextField extends JTextField implements UIObserver, GlobalNameObserver { + private boolean isBorderPainted = true; + private boolean isRoundBorder = true; + private int rectDirection = Constants.NULL; + private UIObserverListener uiObserverListener; + private String textFeildName = ""; + private GlobalNameListener globalNameListener = null; + private Dimension preferredSize = null; + + public UITextField() { + super(); + initListener(); + } + + public UITextField(int columns) { + super(columns); + initListener(); + } + + public UITextField(String text, int columns) { + super(text, columns); + initListener(); + } + + public UITextField(String text) { + super(text); + initListener(); + } + + public UITextField(Document doc, String text, int columns) { + super(doc, text, columns); + initListener(); + } + + protected void initListener() { + if (shouldResponseChangeListener()) { + getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + attributeChange(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + attributeChange(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + attributeChange(); + } + }); + } + } + + + public void setPreferredSize(Dimension preferredSize) { + this.preferredSize = preferredSize; + } + + public void setGlobalName(String name) { + textFeildName = name; + } + + protected void attributeChange() { + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(textFeildName); + } + if (uiObserverListener != null) { + uiObserverListener.doChange(); + } + } + + @Override + public Insets getInsets() { + return new Insets(0, 4, 0, 4); + } + + @Override + public Dimension getPreferredSize() { + if (preferredSize == null) { + return new Dimension(super.getPreferredSize().width, 20); + } + return preferredSize; + } + + @Override + public UITextFieldUI getUI() { + return (UITextFieldUI) ui; + } + + /** + * 设置变化的背景颜色 + */ + public void setBackgroundUIColor(Color color) { + ((UITextFieldUI) this.ui).setBackgroundColor4NoGiveNumber(color); + } + + /** + * 更新UI + */ + public void updateUI() { + this.setUI(new UITextFieldUI(this)); + } + + @Override + protected void paintBorder(Graphics g) { + if (!isBorderPainted) { + return; + } + getUI().paintBorder((Graphics2D) g, getWidth(), getHeight(), isRoundBorder, rectDirection); + } + + /** + * @param isRoundBorder + */ + public void setRoundBorder(boolean isRoundBorder) { + this.isRoundBorder = isRoundBorder; + } + + + /** + * @param rectDirection + */ + public void setRectDirection(int rectDirection) { + this.rectDirection = rectDirection; + } + + /** + * 注册监听 + * + * @param listener 观察者监听事件 + */ + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 是否需要回应监听器响应 + * + * @return 是则返回true + */ + public boolean shouldResponseNameListener() { + return true; + } + + + /** + * 注册监听器 + * + * @param listener 观察者监听事件 + */ + public void registerChangeListener(UIObserverListener listener) { + uiObserverListener = listener; + } + + /** + * 是否需要回应监听器响应 + * + * @return 是则返回true + */ + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * 主函数 + * @param args 参数 + */ + public static void main(String... args) { + LayoutManager layoutManager = null; + JFrame jf = new JFrame("test"); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel content = (JPanel) jf.getContentPane(); + content.setLayout(layoutManager); + + UITextField bb = new UITextField(5); + bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); + content.add(bb); + GUICoreUtils.centerWindow(jf); + jf.setSize(400, 400); + jf.setVisible(true); + } + + public void setBorderPainted(boolean isBorderPainted) { + this.isBorderPainted = isBorderPainted; + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itextfield/UITextFieldUI.java b/designer_base/src/com/fr/design/gui/itextfield/UITextFieldUI.java new file mode 100644 index 0000000000..be3d46fa1c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itextfield/UITextFieldUI.java @@ -0,0 +1,77 @@ +package com.fr.design.gui.itextfield; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.JComponent; +import javax.swing.plaf.basic.BasicTextFieldUI; +import javax.swing.text.JTextComponent; + +import com.fr.design.constants.UIConstants; +import com.fr.design.utils.gui.GUIPaintUtils; + +public class UITextFieldUI extends BasicTextFieldUI { + protected boolean isRollOver; + private JComponent textField; + + private Color backgroundColor = Color.white; + + public UITextFieldUI(final JComponent textField) { + super(); + this.textField = textField; + this.textField.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + isRollOver = true; + textField.repaint(); + } + + @Override + public void mouseExited(MouseEvent e) { + isRollOver = false; + textField.repaint(); + } + }); + } + + @Override + protected void paintBackground(Graphics g) { + JTextComponent editor = getComponent(); + int width = editor.getWidth(); + int height = editor.getHeight(); + Shape roundShape = new RoundRectangle2D.Double(0, 0, width, height, 0, 0); + Graphics2D g2d = (Graphics2D)g; + g2d.clearRect(0, 0, width, height); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); + g2d.clip(roundShape); + g2d.setColor(backgroundColor); + if(!textField.isEnabled()){ + g2d.setColor(UIConstants.NORMAL_BACKGROUND); + } + g2d.fillRoundRect(1, 1, width - 2, height - 2, 0, 0); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF); + } + + /** + * 在出现不允许的数字时, 变换背景. + */ + public void setBackgroundColor4NoGiveNumber(Color color) { + this.backgroundColor = color; + } + + public void paintBorder(Graphics2D g2d, int width, int height, boolean isRound, int rectDirection) { + if(isRollOver && textField.isEnabled()) { + g2d.setColor(UIConstants.TEXT_FILED_BORDER_SELECTED); + g2d.drawRect(0, 0, width - 1, height - 1); + } else { + GUIPaintUtils.drawBorder(g2d, 0, 0, width, height, isRound, rectDirection); + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itoolbar/UILargeToolbar.java b/designer_base/src/com/fr/design/gui/itoolbar/UILargeToolbar.java new file mode 100644 index 0000000000..547f57299b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itoolbar/UILargeToolbar.java @@ -0,0 +1,18 @@ +package com.fr.design.gui.itoolbar; + +import java.awt.*; + +public class UILargeToolbar extends UIToolbar { + + private static final int HEIGHT = 53; + private static final int WIDTH = 60; + + public UILargeToolbar(int align) { + super(align); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(WIDTH ,HEIGHT); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarBorder.java b/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarBorder.java new file mode 100644 index 0000000000..c535291167 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarBorder.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved. + */ + +package com.fr.design.gui.itoolbar; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.metal.MetalBorders; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-3-6 + * Time: 上午9:57 + */ +public class UIToolBarBorder extends MetalBorders.ToolBarBorder { + + public Insets getBorderInsets(Component c) { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + public Insets getBorderInsets(Component c, Insets newInsets) { + newInsets.top = newInsets.left = newInsets.bottom = newInsets.right = 2; + + // we cannot assume that c is a JToolBar + if (!(c instanceof JToolBar)){ + return newInsets; + } + + if (((JToolBar) c).isFloatable()) { + if (((JToolBar) c).getOrientation() == HORIZONTAL) { + if (c.getComponentOrientation().isLeftToRight()) { + newInsets.left = UIToolBarUI.FLOATABLE_GRIP_SIZE + 2; + } else { + newInsets.right = UIToolBarUI.FLOATABLE_GRIP_SIZE + 2; + } + } else { // vertical + newInsets.top = UIToolBarUI.FLOATABLE_GRIP_SIZE + 2; + } + } + + Insets margin = ((JToolBar) c).getMargin(); + + if (margin != null) { + newInsets.left += margin.left; + newInsets.top += margin.top; + newInsets.right += margin.right; + newInsets.bottom += margin.bottom; + } + + return newInsets; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + if (!(c instanceof JToolBar)){ + return; + } + drawWinBorder(c, g, x, y, w, h); + if (((JToolBar) c).getOrientation() == HORIZONTAL) { + g.setColor(ThemeUtils.TOOL_BAR_LIGHT_COLOR); + g.drawLine(x, y, w - 1, y); // top + g.setColor(ThemeUtils.TOOL_BAR_DARK_COLOR); + g.drawLine(x, h - 1, w - 1, h - 1); // bottom + } else { + g.setColor(ThemeUtils.TOOL_BAR_LIGHT_COLOR); + g.drawLine(x, y, x, h - 1); // left + g.setColor(ThemeUtils.TOOL_BAR_DARK_COLOR); + g.drawLine(w - 1, y, w - 1, h - 1); // right + } + } + + protected void drawWinBorder(Component c, Graphics g, int x, int y, int w, int h) { + g.translate(x, y); + + if (((JToolBar) c).isFloatable()) { + // paint grip + if (((JToolBar) c).getOrientation() == HORIZONTAL) { + int xoff = 3; + if (!c.getComponentOrientation().isLeftToRight()) { + xoff = c.getBounds().width - UIToolBarUI.FLOATABLE_GRIP_SIZE + 3; + } + + g.setColor(ThemeUtils.TOOL_GRIP_LIGHT_COLOR); + g.drawLine(xoff, 3, xoff + 1, 3); + g.drawLine(xoff, 3, xoff, h - 5); + g.setColor(ThemeUtils.TOOL_GRIP_DARK_COLOR); + g.drawLine(xoff, h - 4, xoff + 1, h - 4); + g.drawLine(xoff + 2, 3, xoff + 2, h - 4); + } else { // vertical + g.setColor(ThemeUtils.TOOL_GRIP_LIGHT_COLOR); + g.drawLine(3, 3, 3, 4); + g.drawLine(3, 3, w - 4, 3); + g.setColor(ThemeUtils.TOOL_GRIP_DARK_COLOR); + g.drawLine(w - 4, 4, w - 4, 5); + g.drawLine(3, 5, w - 4, 5); + } + } + + g.translate(-x, -y); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarSeparatorUI.java b/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarSeparatorUI.java new file mode 100644 index 0000000000..56f89c8029 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarSeparatorUI.java @@ -0,0 +1,98 @@ +package com.fr.design.gui.itoolbar; + +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToolBarSeparatorUI; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 14-2-14 + * Time: 下午5:25 + */ +public class UIToolBarSeparatorUI extends BasicToolBarSeparatorUI { + + private static final int YQ_SIZE = 7; + private int defaultSize = YQ_SIZE; + + /** + * 创建组件UI + * + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIToolBarSeparatorUI(); + } + + /** + * Overridden to do nothing + */ + protected void installDefaults(JSeparator s) { + } + + public Dimension getMinimumSize(JComponent c) { + JToolBar.Separator sep = (JToolBar.Separator) c; + + if (sep.getOrientation() == JSeparator.HORIZONTAL) { + return new Dimension(0, 1); + } else { + return new Dimension(1, 0); + } + } + + public Dimension getMaximumSize(JComponent c) { + JToolBar.Separator sep = (JToolBar.Separator) c; + Dimension size = sep.getSeparatorSize(); + + if (sep.getOrientation() == JSeparator.HORIZONTAL) { + if (size != null) { + return new Dimension(32767, size.height); + } + return new Dimension(32767, defaultSize); + } else { + if (size != null) { + return new Dimension(32767, size.width); + } + + return new Dimension(defaultSize, 32767); + } + } + + public Dimension getPreferredSize(JComponent c) { + JToolBar.Separator sep = (JToolBar.Separator) c; + + Dimension size = sep.getSeparatorSize(); + + if (size != null) { + return size.getSize(); + } + + if (sep.getOrientation() == JSeparator.HORIZONTAL) { + return new Dimension(0, defaultSize); + } else { + return new Dimension(defaultSize, 0); + } + } + + public void paint(Graphics g, JComponent c) { + JToolBar.Separator sep = (JToolBar.Separator) c; + + if (sep.getOrientation() == JSeparator.HORIZONTAL) { + int y = sep.getHeight() / 2; // centered if height is odd + + g.setColor(ThemeUtils.TOOL_SEP_DARK_COLOR); + g.drawLine(0, y, sep.getWidth(), y); + } else { + int x = sep.getWidth() / 2; // centered if width is odd + + g.setColor(ThemeUtils.TOOL_SEP_DARK_COLOR); + g.drawLine(x, 0, x, sep.getHeight()); + } + + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarUI.java b/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarUI.java new file mode 100644 index 0000000000..bdebfe3339 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itoolbar/UIToolBarUI.java @@ -0,0 +1,124 @@ +package com.fr.design.gui.itoolbar; + + +import java.awt.Component; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Window; +import java.awt.event.WindowListener; + +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JRadioButton; +import javax.swing.JToolBar; +import javax.swing.RootPaneContainer; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.metal.MetalToolBarUI; + +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ibutton.UIToolButtonBorder; +import com.fr.design.gui.icheckbox.UICheckBox; + +public class UIToolBarUI extends MetalToolBarUI { + public static final String IS_TOOL_BAR_BUTTON_KEY = "JToolBar.isToolbarButton"; + public static final int FLOATABLE_GRIP_SIZE = 8; + + /** + * The Border used for buttons in a toolbar + */ + private static Border toolButtonBorder = new UIToolButtonBorder(); + + /** + * 创建组件UI + * + * @param c 组件 + * @return 组件UI + */ + public static ComponentUI createUI(JComponent c) { + return new UIToolBarUI(); + } + + /** + * 加载组件ui + * + * @param c 组件 + */ + public void installUI(JComponent c) { + super.installUI(c); + c.putClientProperty("JToolBar.isRollover", Boolean.TRUE); + } + + /** + * Overrides BasicToolBarUI.createFloatingWindow() to return a simple dialog + * (which works with TinyLaF). Creates a window which contains the toolbar + * after it has been dragged out from its container + * + * @return a RootPaneContainer object, containing the toolbar. + */ + protected RootPaneContainer createFloatingWindow(JToolBar toolbar) { + JDialog dialog; + Window window = SwingUtilities.getWindowAncestor(toolbar); + + if (window instanceof Frame) { + dialog = new JDialog((Frame) window, toolbar.getName(), false); + } else if (window instanceof Dialog) { + dialog = new JDialog((Dialog) window, toolbar.getName(), false); + } else { + dialog = new JDialog((Frame) null, toolbar.getName(), false); + } + + dialog.setTitle(toolbar.getName()); + dialog.setResizable(false); + WindowListener wl = createFrameListener(); + dialog.addWindowListener(wl); + + return dialog; + } + + /** + * Paints the given component. + * + * @param g The graphics context to use. + * @param c The component to paint. + */ + public void paint(Graphics g, JComponent c) { + Graphics2D g2 = (Graphics2D) g; + g2.setColor(UIConstants.NORMAL_BACKGROUND); + g2.fillRect(0, 0, c.getWidth(), c.getHeight()); + } + + /** + * Rewritten in 1.3. Now the border is defined through button margin. + */ + protected void setBorderToRollover(Component c) { + setBorderToNormal(c); + } + + protected void setBorderToNormal(Component c) { + if (!(c instanceof AbstractButton)) { + return; + } + if (c instanceof UICheckBox) { + return; + } + if (c instanceof JRadioButton) { + return; + } + AbstractButton b = (AbstractButton) c; + b.setRolloverEnabled(true); + b.putClientProperty(IS_TOOL_BAR_BUTTON_KEY, Boolean.TRUE); + + if (!(b.getBorder() instanceof UIResource) && !(b.getBorder() instanceof UIToolButtonBorder)) { + // user has installed her own border + return; + } + + b.setBorder(toolButtonBorder); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itoolbar/UIToolbar.java b/designer_base/src/com/fr/design/gui/itoolbar/UIToolbar.java new file mode 100644 index 0000000000..7386c4d490 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itoolbar/UIToolbar.java @@ -0,0 +1,37 @@ +package com.fr.design.gui.itoolbar; + +import java.awt.*; +import java.util.ArrayList; + +import javax.swing.JToolBar; + +public class UIToolbar extends JToolBar{ + private static final int TOOLBAR_HEIGNT = 26; + public UIToolbar() { + this(FlowLayout.LEFT); + } + + public UIToolbar(int align) { + super(); + setFloatable(false); + setRollover(true); + setLayout(new FlowLayout(align, 4, 0)); + setUI(new UIToolBarUI()); + } + + @Override + public Dimension getPreferredSize() { + Dimension dim = super.getPreferredSize(); + dim.height = TOOLBAR_HEIGNT; + return dim; + } + + public void checkComponentsByNames (boolean flag, ArrayList names) { + for (int i = 0; i < getComponentCount(); i ++) { + Component component = getComponents()[i]; + if (names.contains(component.getName())) { + component.setEnabled(flag); + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTip.java b/designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTip.java new file mode 100644 index 0000000000..b644ae4db6 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTip.java @@ -0,0 +1,10 @@ +package com.fr.design.gui.itooltip; + +import javax.swing.JToolTip; + +public class MultiLineToolTip extends JToolTip { + + public MultiLineToolTip() { + setUI(new MultiLineToolTipUI()); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTipUI.java b/designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTipUI.java new file mode 100644 index 0000000000..0e94524a93 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itooltip/MultiLineToolTipUI.java @@ -0,0 +1,84 @@ +package com.fr.design.gui.itooltip; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.Enumeration; +import java.util.Vector; + +import javax.swing.JComponent; +import javax.swing.JToolTip; +import javax.swing.SwingUtilities; +import javax.swing.plaf.ToolTipUI; + +import com.fr.base.FRContext; +import com.fr.base.GraphHelper; + +public class MultiLineToolTipUI extends ToolTipUI { + + private String[] strs; + public void paint(Graphics g, JComponent c) { + FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont()); + Dimension size = c.getSize(); + int width = size.width; + int height = size.height; + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint paint = new GradientPaint(0, 0, new Color(250, 250, 250), 0, 50, + new Color(165, 217, 249)); + g2.setPaint(paint); + g2.fillRoundRect(0, 0, width, height, 5, 5); + g2.setColor(Color.WHITE); + g2.drawRoundRect(1, 1, width - 3, height - 3, 5, 5); + g2.setColor(new Color(198, 198, 198)); + g2.drawRoundRect(0, 0, width - 1, height - 1, 5, 5); + g2.setColor(c.getForeground()); + if (strs != null) { + for (int i = 0; i < strs.length; i++) { + g2.drawString(strs[i], 3, (metrics.getHeight()) * (i + 1)); + } + } + } + + @Override + public Dimension getPreferredSize(JComponent c) { + FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont()); + String tipText = ((JToolTip) c).getTipText(); + if (tipText == null) { + tipText = " "; + } + BufferedReader br = new BufferedReader(new StringReader(tipText)); + String line; + int maxWidth = 0; + Vector v = new Vector(); + try { + while ((line = br.readLine()) != null) { + int width = SwingUtilities.computeStringWidth(metrics, line); + maxWidth = (maxWidth < width) ? width : maxWidth; + v.addElement(line); + } + } catch (IOException ex) { + FRContext.getLogger().error(ex.getMessage(), ex); + } + int lines = v.size(); + if (lines < 1) { + strs = null; + lines = 1; + } else { + strs = new String[lines]; + int i = 0; + for (Enumeration e = v.elements(); e.hasMoreElements(); i++) { + strs[i] = e.nextElement(); + } + } + int height = metrics.getHeight() * lines; + return new Dimension(maxWidth + 11, height + 9); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itooltip/UIToolTip.java b/designer_base/src/com/fr/design/gui/itooltip/UIToolTip.java new file mode 100644 index 0000000000..cd291af132 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itooltip/UIToolTip.java @@ -0,0 +1,88 @@ +package com.fr.design.gui.itooltip; + +import com.fr.base.FRContext; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.general.ComparatorUtils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-5-16 + * Time: 下午2:40 + * To change this template use File | Settings | File Templates. + */ +public class UIToolTip extends JToolTip{ + private Icon icon; + public UIToolTip() { + this(new ImageIcon()); + } + + public UIToolTip(Icon icon) { + this.icon = icon; + setUI(new UIToolTipUI()); + try { + this.addMouseListener(new MouseAdapter() { + Robot robot = new Robot(); + public void mousePressed(MouseEvent e) { + setVisible(false); + robot.mousePress(MouseEvent.BUTTON3_MASK); + robot.mouseRelease(MouseEvent.BUTTON3_MASK); + robot.mousePress(MouseEvent.BUTTON1_MASK); + } + + public void mouseReleased(MouseEvent e) { + robot.mouseRelease(MouseEvent.BUTTON1_MASK); + } + }); + } catch (AWTException e) { + FRContext.getLogger().error(e.getMessage(),e); + } + + this.addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + setVisible(false); + } + }); + + this.addMouseListener(new MouseAdapter() { + public void mouseExited(MouseEvent e) { + ToolTipManager.sharedInstance().setEnabled(false); + ToolTipManager.sharedInstance().setEnabled(true); + } + }); + this.addMouseMotionListener(new MouseMotionAdapter() { + public void mouseMoved(MouseEvent e) { + Container container = getComponent(); + while (!ComparatorUtils.equals(container.getClass(), UIScrollPane.class)) { + if (container.getParent() == null) { + break; + } + container = container.getParent(); + } + Point mouse = e.getLocationOnScreen(); + Point parent = container.getLocationOnScreen(); + if (!isInParent(mouse, parent, container.getWidth(), container.getHeight())) { + ToolTipManager.sharedInstance().setEnabled(false); + ToolTipManager.sharedInstance().setEnabled(true); + } + + } + }); + + } + + private boolean isInParent(Point mouse, Point parent, int width, int height) { + int deltaX = (int) (mouse.getX() - parent.getX()); + int deltaY = (int) (mouse.getY() - parent.getY()); + return deltaX > 1 && deltaX < width - 10 && deltaY > 1 && deltaY < height - 1; + } + + + public Icon getIcon() { + return icon; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itooltip/UIToolTipBorder.java b/designer_base/src/com/fr/design/gui/itooltip/UIToolTipBorder.java new file mode 100644 index 0000000000..a266361c43 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itooltip/UIToolTipBorder.java @@ -0,0 +1,44 @@ +package com.fr.design.gui.itooltip; + +import javax.swing.border.Border; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.InsetsUIResource; +import java.awt.*; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-31 + * Time: 上午10:38 + */ +public class UIToolTipBorder implements Border { + + private static final ColorUIResource TIP_BORDER_COLOR = new ColorUIResource(0, 0, 0); + private static final ColorUIResource TIP_BORDER_DIS = new ColorUIResource(143, 141, 139); + + private static final InsetsUIResource INSETS = new InsetsUIResource(3, 3, 3, 3); + private boolean active; + + public UIToolTipBorder(boolean b) { + active = b; + } + + public boolean isBorderOpaque() { + return false; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + if (active) { + g.setColor(TIP_BORDER_COLOR); + } else { + g.setColor(TIP_BORDER_DIS); + } + + g.drawRect(x, y, w - 1, h - 1); + } + + public Insets getBorderInsets(Component c) { + return INSETS; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itooltip/UIToolTipUI.java b/designer_base/src/com/fr/design/gui/itooltip/UIToolTipUI.java new file mode 100644 index 0000000000..4970593a7a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itooltip/UIToolTipUI.java @@ -0,0 +1,118 @@ +package com.fr.design.gui.itooltip; + +import com.fr.base.FRContext; +import com.fr.base.GraphHelper; + +import javax.swing.*; +import javax.swing.plaf.ToolTipUI; +import java.awt.*; +import java.awt.geom.GeneralPath; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.Enumeration; +import java.util.Vector; + +/** + * Created with IntelliJ IDEA. + * User: pony + * Date: 13-5-16 + * Time: 下午2:42 + * To change this template use File | Settings | File Templates. + */ +public class UIToolTipUI extends ToolTipUI { + private String[] strs; + private Icon icon; + private boolean needPaint; + public void paint(Graphics g, JComponent c) { + if (!needPaint) { + return; + } + FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont()); + Dimension size = c.getSize(); + int width = size.width; + int height = size.height; + Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint paint = new GradientPaint(0, 0, new Color(240, 240, 240), 0, height ,new Color(171, 183, 203)); + g2.setPaint(paint); + g2.fillRoundRect(0, 0, width - 3, height - 3, 6, 6); + g2.setColor(new Color(100, 100, 100)); + g2.drawRoundRect(0, 0, width - 3, height - 3, 6, 6); + + GradientPaint cornerPaint = new GradientPaint(width-3, height-3, new Color(100, 100, 100, 191), width - 1, height - 1, new Color(240, 240, 240)); + g2.setPaint(cornerPaint); + g2.fillArc(width - 6, height - 6, 6, 6, 270, 90 ); + + GeneralPath shadowDown = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 4); + shadowDown.moveTo(0, height - 3); + shadowDown.lineTo(3, height); + shadowDown.lineTo(width - 3, height); + shadowDown.lineTo(width - 3, height - 3); + GradientPaint downPaint = new GradientPaint(0, height-3, new Color(100, 100, 100, 191), 0, height, new Color(240, 240, 240)); + g2.setPaint(downPaint); + GraphHelper.fill(g2, shadowDown); + + GeneralPath shadowRight = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 4); + shadowRight.moveTo(width - 3, height - 3); + shadowRight.lineTo(width, height - 3); + shadowRight.lineTo(width, 3); + shadowRight.lineTo(width - 3, 0); + GradientPaint rightPaint = new GradientPaint(width - 3, 0, new Color(100, 100, 100, 191), width, 0, new Color(240, 240, 240)); + g2.setPaint(rightPaint); + GraphHelper.fill(g2, shadowRight); + + g2.setColor(c.getForeground()); + if (icon instanceof ImageIcon) { + ImageIcon imageIcon = (ImageIcon)icon; + g2.drawImage(imageIcon.getImage(), 2 , 2, imageIcon.getImageObserver()); + } + if (strs != null) { + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT); + for (int i = 0; i < strs.length; i++) { + g2.drawString(strs[i], icon.getIconWidth() + 6, (metrics.getHeight()) * (i + 1)); + } + } + } + + @Override + public Dimension getPreferredSize(JComponent c) { + FontMetrics metrics = GraphHelper.getFontMetrics(c.getFont()); + String tipText = ((JToolTip) c).getTipText(); + icon = ((UIToolTip)c).getIcon(); + needPaint = true; + if (tipText == null) { + if(icon.getIconWidth() == -1) { + needPaint = false; + } + tipText = " "; + } + BufferedReader br = new BufferedReader(new StringReader(tipText)); + String line; + int maxWidth = 0; + Vector v = new Vector(); + try { + while ((line = br.readLine()) != null) { + int width = SwingUtilities.computeStringWidth(metrics, line); + maxWidth = (maxWidth < width) ? width : maxWidth; + v.addElement(line); + } + } catch (IOException ex) { + FRContext.getLogger().error(ex.getMessage(), ex); + } + int lines = v.size(); + if (lines < 1) { + strs = null; + lines = 1; + } else { + strs = new String[lines]; + int i = 0; + for (Enumeration e = v.elements(); e.hasMoreElements(); i++) { + strs[i] = e.nextElement(); + } + } + int height = metrics.getHeight() * lines; + return new Dimension(maxWidth + icon.getIconWidth() + 10, Math.max(height, icon.getIconHeight()) + 6); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/UITreeUI.java b/designer_base/src/com/fr/design/gui/itree/UITreeUI.java new file mode 100644 index 0000000000..c2cbe4f475 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/UITreeUI.java @@ -0,0 +1,40 @@ +package com.fr.design.gui.itree; + +import com.fr.base.BaseUtils; +import com.fr.design.utils.ThemeUtils; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.metal.MetalTreeUI; +import javax.swing.tree.DefaultTreeCellRenderer; + +/** + * Created by IntelliJ IDEA. + * Author : daisy + * Version: 6.5.6 + * Date: 13-12-31 + * Time: 下午4:58 + */ +public class UITreeUI extends MetalTreeUI { + /** + * 创建组件UI + * @param x 组件 + * @return 返回组件UI + */ + public static ComponentUI createUI(JComponent x) { + return new UITreeUI(); + } + + protected void installDefaults() { + super.installDefaults(); + setExpandedIcon(BaseUtils.readIcon("/com/fr/design/images/buttonicon/minus.png")); + setCollapsedIcon(BaseUtils.readIcon("/com/fr/design/images/buttonicon/plus.png")); + if (tree.getCellRenderer() instanceof DefaultTreeCellRenderer) { + DefaultTreeCellRenderer r = (DefaultTreeCellRenderer) tree.getCellRenderer(); + r.setBackgroundNonSelectionColor(ThemeUtils.TEXT_BG_COLOR); + r.setBackgroundSelectionColor(ThemeUtils.TEXT_SELECTED_BG_COLOR); + r.setTextNonSelectionColor(ThemeUtils.NORMAL_FOREGROUND); + r.setTextSelectionColor(ThemeUtils.TEXT_BG_COLOR); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTree.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTree.java new file mode 100644 index 0000000000..0511504cf7 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTree.java @@ -0,0 +1,464 @@ +/* + * @(#)CheckBoxTree.java 8/11/2005 + * modified by FineReport + * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved. + */ +package com.fr.design.gui.itree.checkboxtree; + +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Hashtable; +import java.util.Vector; + +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.text.Position; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import com.fr.design.gui.icheckbox.UICheckBox; + +/** + * CheckBoxTree is a special JTree which uses UICheckBox as the tree renderer. + * In addition to regular JTree's features, it also allows you select any number + * of tree nodes in the tree by selecting the check boxes. + *

To select an element, user can mouse click on the check box, or + * select one or several tree nodes and press SPACE key to toggle the + * check box selection for all selected tree nodes. + *

+ * In order to retrieve which tree paths are selected, you need to call + * {@link #getCheckBoxTreeSelectionModel()}. + * It will return the selection model that keeps track of which tree + * paths have been checked. For example + * {@link CheckBoxTreeSelectionModel#getSelectionPaths()} + * will give the list of paths which have + * been checked. + */ +public class CheckBoxTree extends JTree { + public final static String PROPERTY_CHECKBOX_ENABLED = "checkBoxEnabled"; + public final static String PROPERTY_DIG_IN = "digIn"; + + protected CheckBoxTreeCellRenderer _treeCellRenderer; + + private CheckBoxTreeSelectionModel _checkBoxTreeSelectionModel; + + private boolean _checkBoxEnabled = true; + private PropertyChangeListener _modelChangeListener; + + public CheckBoxTree() { + init(); + } + + public CheckBoxTree(Object[] value) { + super(value); + init(); + } + + public CheckBoxTree(Vector value) { + super(value); + init(); + } + + public CheckBoxTree(Hashtable value) { + super(value); + init(); + } + + public CheckBoxTree(TreeNode root) { + super(root); + init(); + } + + public CheckBoxTree(TreeNode root, boolean asksAllowsChildren) { + super(root, asksAllowsChildren); + init(); + } + + public CheckBoxTree(TreeModel newModel) { + super(newModel); + init(); + } + + /** + * Initialize the CheckBoxTree. + */ + protected void init() { + _checkBoxTreeSelectionModel = createCheckBoxTreeSelectionModel(getModel()); + _checkBoxTreeSelectionModel.setTree(this); + Handler handler = createHandler(); + this.insertMouseListener(this, handler, 0); + addKeyListener(handler); + _checkBoxTreeSelectionModel.addTreeSelectionListener(handler); + + if (_modelChangeListener == null) { + _modelChangeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + updateRowMapper(); + } + }; + } + addPropertyChangeListener(JTree.SELECTION_MODEL_PROPERTY, _modelChangeListener); + updateRowMapper(); + } + + /** + * Inserts the mouse listener at the particular index in the listeners' chain. + * + * @param component + * @param l + * @param index + */ + private void insertMouseListener(Component component, MouseListener l, int index) { + MouseListener[] listeners = component.getMouseListeners(); + for (int i = 0, length = listeners.length; i < length; i++) { + component.removeMouseListener(listeners[i]); + } +// for (MouseListener listener : listeners) { +// component.removeMouseListener(listener); +// } + for (int i = 0; i < listeners.length; i++) { + MouseListener listener = listeners[i]; + if (index == i) { + component.addMouseListener(l); + } + component.addMouseListener(listener); + } + // inex is too large, add to the end. + if (index > listeners.length - 1) { + component.addMouseListener(l); + } + } + + /** + * Creates the CheckBoxTreeSelectionModel. + * + * @param model the tree model. + * @return the CheckBoxTreeSelectionModel. + */ + protected CheckBoxTreeSelectionModel createCheckBoxTreeSelectionModel(TreeModel model) { + return new CheckBoxTreeSelectionModel(model); + } + + /** + * RowMapper is necessary for contiguous selection. + */ + private void updateRowMapper() { + _checkBoxTreeSelectionModel.setRowMapper(getSelectionModel().getRowMapper()); + } + + public void setModel(TreeModel newModel) { + super.setModel(newModel); + if (_checkBoxTreeSelectionModel != null) { + _checkBoxTreeSelectionModel.setModel(getModel()); + } + } + + /** + * Gets the cell renderer with check box. + * + * @return CheckBoxTree's own cell renderer which has the check box. The actual cell renderer + * you set by setCellRenderer() can be accessed by using {@link #getActualCellRenderer()}. + */ + public TreeCellRenderer getCellRenderer() { + TreeCellRenderer cellRenderer = super.getCellRenderer(); + if (cellRenderer == null) { + cellRenderer = new DefaultTreeCellRenderer(); + } + if (_treeCellRenderer == null) { + _treeCellRenderer = createCellRenderer(cellRenderer); + } + else { + _treeCellRenderer.setActualTreeRenderer(cellRenderer); + } + return _treeCellRenderer; + } + + /** + * Gets the actual cell renderer. Since CheckBoxTree has its own check box cell renderer, this method + * will give you access to the actual cell renderer which is either the default tree cell renderer or + * the cell renderer you set using {@link #setCellRenderer(javax.swing.tree.TreeCellRenderer)}. + * + * @return the actual cell renderer + */ + public TreeCellRenderer getActualCellRenderer() { + if (_treeCellRenderer != null) { + return _treeCellRenderer.getActualTreeRenderer(); + } + else { + return super.getCellRenderer(); + } + } + + /** + * Creates the cell renderer. + * + * @param renderer the actual renderer for the tree node. This method will + * return a cell renderer that use a check box and put the actual renderer inside it. + * @return the cell renderer. + */ + protected CheckBoxTreeCellRenderer createCellRenderer(TreeCellRenderer renderer) { + final CheckBoxTreeCellRenderer checkBoxTreeCellRenderer = new CheckBoxTreeCellRenderer(renderer); + addPropertyChangeListener(CELL_RENDERER_PROPERTY, new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + checkBoxTreeCellRenderer.setActualTreeRenderer((TreeCellRenderer) evt.getNewValue()); + } + }); + return checkBoxTreeCellRenderer; + } + + /** + * Creates the mouse listener and key listener used by CheckBoxTree. + * + * @return the Handler. + */ + protected Handler createHandler() { + return new Handler(this); + } + + protected static class Handler implements MouseListener, KeyListener, TreeSelectionListener { + protected CheckBoxTree _tree; + int _hotspot = new UICheckBox().getPreferredSize().width; + private int _toggleCount = -1; + + public Handler(CheckBoxTree tree) { + _tree = tree; + } + + protected TreePath getTreePathForMouseEvent(MouseEvent e) { + if (!SwingUtilities.isLeftMouseButton(e)) { + return null; + } + + if (!_tree.isCheckBoxEnabled()) { + return null; + } + + TreePath path = _tree.getPathForLocation(e.getX(), e.getY()); + if (path == null) + return null; + + if (clicksInCheckBox(e, path)) { + return path; + } + else { + return null; + } + } + + protected boolean clicksInCheckBox(MouseEvent e, TreePath path) { + if (!_tree.isCheckBoxVisible(path)) { + return false; + } + else { + Rectangle bounds = _tree.getPathBounds(path); + if (_tree.getComponentOrientation().isLeftToRight()) { + return e.getX() < bounds.x + _hotspot; + } + else { + return e.getX() > bounds.x + bounds.width - _hotspot; + } + } + } + + private TreePath preventToggleEvent(MouseEvent e) { + TreePath pathForMouseEvent = getTreePathForMouseEvent(e); + if (pathForMouseEvent != null) { + int toggleCount = _tree.getToggleClickCount(); + if (toggleCount != -1) { + _toggleCount = toggleCount; + _tree.setToggleClickCount(-1); + } + } + return pathForMouseEvent; + } + + public void mouseClicked(MouseEvent e) { + preventToggleEvent(e); + } + + public void mousePressed(MouseEvent e) { + TreePath path = preventToggleEvent(e); + if (path != null) { + toggleSelection(path); + e.consume(); + } + } + + public void mouseReleased(MouseEvent e) { + TreePath path = preventToggleEvent(e); + if (path != null) { + e.consume(); + } + if (_toggleCount != -1) { + _tree.setToggleClickCount(_toggleCount); + } + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void keyPressed(KeyEvent e) { + if (e.isConsumed()) { + return; + } + + if (!_tree.isCheckBoxEnabled()) { + return; + } + + if (e.getModifiers() == 0 && e.getKeyChar() == KeyEvent.VK_SPACE) + toggleSelections(); + } + + public void keyTyped(KeyEvent e) { + } + + public void keyReleased(KeyEvent e) { + } + + public void valueChanged(TreeSelectionEvent e) { + _tree.treeDidChange(); + } + + private void toggleSelection(TreePath path) { + if (!_tree.isEnabled() || !_tree.isCheckBoxEnabled(path)) { + return; + } + CheckBoxTreeSelectionModel selectionModel = _tree.getCheckBoxTreeSelectionModel(); + boolean selected = selectionModel.isPathSelected(path, selectionModel.isDigIn()); + selectionModel.removeTreeSelectionListener(this); + try { + if (!selectionModel.isSingleEventMode()) { + selectionModel.setBatchMode(true); + } + if (selected) + selectionModel.removeSelectionPath(path); + else + selectionModel.addSelectionPath(path); + } + finally { + if (!selectionModel.isSingleEventMode()) { + selectionModel.setBatchMode(false); + } + selectionModel.addTreeSelectionListener(this); + _tree.treeDidChange(); + } + } + + protected void toggleSelections() { + TreePath[] treePaths = _tree.getSelectionPaths(); + if (treePaths == null) { + return; + } + for (int i = 0, length = treePaths.length; i < length; i++) { + TreePath tmpTreePath = treePaths[i]; + toggleSelection(tmpTreePath); + } +// for (TreePath treePath : treePaths) { +// toggleSelection(treePath); +// } + } + } + + public TreePath getNextMatch(String prefix, int startingRow, Position.Bias bias) { + return null; + } + + /** + * Gets the selection model for the check boxes. To retrieve the state of check boxes, you should use this selection model. + * + * @return the selection model for the check boxes. + */ + public CheckBoxTreeSelectionModel getCheckBoxTreeSelectionModel() { + return _checkBoxTreeSelectionModel; + } + + /** + * Gets the value of property checkBoxEnabled. If true, user can + * click on check boxes on each tree node to select and unselect. + * If false, user can't click but you as developer can programatically + * call API to select/unselect it. + * + * @return the value of property checkBoxEnabled. + */ + public boolean isCheckBoxEnabled() { + return _checkBoxEnabled; + } + + /** + * Sets the value of property checkBoxEnabled. + * + * @param checkBoxEnabled true to allow to check the check box. False to disable it + * which means user can see whether a row is checked or not but they cannot change it. + */ + public void setCheckBoxEnabled(boolean checkBoxEnabled) { + if (checkBoxEnabled != _checkBoxEnabled) { + Boolean oldValue = _checkBoxEnabled ? Boolean.TRUE : Boolean.FALSE; + Boolean newValue = checkBoxEnabled ? Boolean.TRUE : Boolean.FALSE; + _checkBoxEnabled = checkBoxEnabled; + firePropertyChange(PROPERTY_CHECKBOX_ENABLED, oldValue, newValue); + repaint(); + } + } + + /** + * Checks if check box is enabled. There is no setter for it. The only way is to override + * this method to return true or false. + * + * @param path the tree path. + * @return true or false. If false, the check box on the particular tree path will be disabled. + */ + public boolean isCheckBoxEnabled(TreePath path) { + return true; + } + + /** + * Checks if check box is visible. There is no setter for it. The only way is to override + * this method to return true or false. + * + * @param path the tree path. + * @return true or false. If false, the check box on the particular tree path will be disabled. + */ + public boolean isCheckBoxVisible(TreePath path) { + return true; + } + + /** + * Gets the dig-in mode. If the CheckBoxTree is in dig-in mode, checking the parent node + * will check all the children. Correspondingly, getSelectionPaths() will only return the + * parent tree path. If not in dig-in mode, each tree node can be checked or unchecked independently + * + * @return true or false. + */ + public boolean isDigIn() { + return getCheckBoxTreeSelectionModel().isDigIn(); + } + + /** + * Sets the dig-in mode. If the CheckBoxTree is in dig-in mode, checking the parent node + * will check all the children. Correspondingly, getSelectionPaths() will only return the + * parent tree path. If not in dig-in mode, each tree node can be checked or unchecked independently + * + * @param digIn the new digIn mode. + */ + public void setDigIn(boolean digIn) { + boolean old = isDigIn(); + if (old != digIn) { + getCheckBoxTreeSelectionModel().setDigIn(digIn); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java new file mode 100644 index 0000000000..54ce047c14 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java @@ -0,0 +1,134 @@ +/* + * @(#)CheckBoxTreeCellRenderer.java 8/11/2005 + * Modified by FineReport + * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved. + */ + +package com.fr.design.gui.itree.checkboxtree; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.io.Serializable; + +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JTree; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; + +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.layout.FRGUIPaneFactory; + + +/** + * Renderers an item in a tree using UICheckBox. + */ +public class CheckBoxTreeCellRenderer extends NullPanel implements TreeCellRenderer, Serializable { + + protected static Border noFocusBorder; + + /** + * The checkbox that is used to paint the check box in cell renderer + */ + protected TristateCheckBox _checkBox = new NullTristateCheckBox(); + protected UICheckBox PROTOTYPE = new TristateCheckBox(); + protected UILabel _label = new NullLabel(); + + /** + * The label which appears after the check box. + */ + protected TreeCellRenderer _actualTreeRenderer; + + /** + * Constructs a default renderer object for an item + * in a list. + */ + public CheckBoxTreeCellRenderer() { + this(null); + } + + public CheckBoxTreeCellRenderer(TreeCellRenderer renderer) { + if (noFocusBorder == null) { + noFocusBorder = new EmptyBorder(1, 1, 1, 1); + } + _checkBox.setOpaque(false); + setBorder(noFocusBorder); + setLayout(FRGUIPaneFactory.createBorderLayout()); + add(_checkBox, BorderLayout.BEFORE_LINE_BEGINS); + _actualTreeRenderer = renderer; + } + + public TreeCellRenderer getActualTreeRenderer() { + return _actualTreeRenderer; + } + + public void setActualTreeRenderer(TreeCellRenderer actualTreeRenderer) { + _actualTreeRenderer = actualTreeRenderer; + } + + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + _checkBox.setPreferredSize(new Dimension(PROTOTYPE.getPreferredSize().width, 0)); + setComponentOrientation(tree.getComponentOrientation()); + + TreePath path = tree.getPathForRow(row); + if (path != null && tree instanceof CheckBoxTree) { + CheckBoxTreeSelectionModel selectionModel = ((CheckBoxTree) tree).getCheckBoxTreeSelectionModel(); + if (selectionModel != null) { + _checkBox.setEnabled(((CheckBoxTree) tree).isCheckBoxEnabled() && ((CheckBoxTree) tree).isCheckBoxEnabled(path)); + if (selectionModel.isPathSelected(path, selectionModel.isDigIn())) { + _checkBox.setState(TristateCheckBox.SELECTED); + _checkBox.setSelected(true); + } + else { + _checkBox.setState(selectionModel.isDigIn() && selectionModel.isPartiallySelected(path) ? null : TristateCheckBox.NOT_SELECTED); + _checkBox.setSelected(false); + } + } + } + + if (_actualTreeRenderer != null) { + JComponent treeCellRendererComponent = (JComponent) _actualTreeRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + if (path != null && tree instanceof CheckBoxTree) { + if (!((CheckBoxTree) tree).isCheckBoxVisible(path)) { + return treeCellRendererComponent; + } + } + Border border = treeCellRendererComponent.getBorder(); + setBorder(border); + treeCellRendererComponent.setBorder(BorderFactory.createEmptyBorder()); + if (getComponentCount() == 2) { + remove(1); + } + add(treeCellRendererComponent); + } + + return this; + } + + public String getToolTipText(MouseEvent event) { + if (_actualTreeRenderer instanceof JComponent) { + Point p = event.getPoint(); + p.translate(-_checkBox.getWidth(), 0); + MouseEvent newEvent = new MouseEvent(((JComponent) _actualTreeRenderer), event.getID(), + event.getWhen(), + event.getModifiers(), + p.x, p.y, event.getClickCount(), + event.isPopupTrigger()); + + String tip = ((JComponent) _actualTreeRenderer).getToolTipText( + newEvent); + + if (tip != null) { + return tip; + } + } + return super.getToolTipText(event); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeSelectionModel.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeSelectionModel.java new file mode 100644 index 0000000000..0398604602 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeSelectionModel.java @@ -0,0 +1,483 @@ +package com.fr.design.gui.itree.checkboxtree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; +import java.util.Vector; + +import javax.swing.event.TreeSelectionEvent; +import javax.swing.tree.DefaultTreeSelectionModel; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +/** + * CheckBoxTreeSelectionModel is a selection _model based on {@link DefaultTreeSelectionModel} and use + * in {@link CheckBoxTree} to keep track of the checked tree paths. + * + * @author Santhosh Kumar T + */ +public class CheckBoxTreeSelectionModel extends DefaultTreeSelectionModel { + private TreeModel _model; + private boolean _digIn = false;//james:把这个默认值改掉了,方便使用 + private CheckBoxTree _tree; + + private boolean _singleEventMode = false; + + public CheckBoxTreeSelectionModel(TreeModel model) { + _model = model; + setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + } + + void setTree(CheckBoxTree tree) { + _tree = tree; + } + + public CheckBoxTreeSelectionModel(TreeModel model, boolean digIn) { + _model = model; + _digIn = digIn; + } + + public TreeModel getModel() { + return _model; + } + + public void setModel(TreeModel model) { + _model = model; + } + + /** + * Gets the dig-in mode. If the CheckBoxTree is in dig-in mode, checking the parent node + * will check all the children. Correspondingly, getSelectionPaths() will only return the + * parent tree path. If not in dig-in mode, each tree node can be checked or unchecked independently + * + * @return true or false. + */ + public boolean isDigIn() { + return _digIn; + } + + /** + * Sets the dig-in mode. If the CheckBoxTree is in dig-in mode, checking the parent node + * will check all the children. Correspondingly, getSelectionPaths() will only return the + * parent tree path. If not in dig-in mode, each tree node can be checked or unchecked independently + * + * @param digIn true to enable dig-in mode. False to disable it. + */ + public void setDigIn(boolean digIn) { + _digIn = digIn; + } + + /** + * Tests whether there is any unselected node in the subtree of given path. + * + * @param path check if the path is partially selected. + * @return true i fpartially. Otherwise false. + */ + public boolean isPartiallySelected(TreePath path) { + if (isPathSelected(path, true)) + return false; + TreePath[] selectionPaths = getSelectionPaths(); + if (selectionPaths == null) + return false; + for (int i = 0, length = selectionPaths.length; i < length; i++) { + TreePath selectionPath = selectionPaths[i]; + if (isDescendant(selectionPath, path)) + return true; + } +// for (TreePath selectionPath : selectionPaths) { +// if (isDescendant(selectionPath, path)) +// return true; +// } + return false; + } + + /** + * Tells whether given path is selected. if dig is true, + * then a path is assumed to be selected, if one of its ancestor is selected. + * + * @param path check if the path is selected. + * @param digIn whether we will check its descendants. + * @return true if the path is selected. + */ + public boolean isPathSelected(TreePath path, boolean digIn) { + if (!digIn) + return super.isPathSelected(path); + + while (path != null && !super.isPathSelected(path)) { + path = path.getParentPath(); + } + return path != null; + } + + /** + * is path1 descendant of path2. + * + * @param path1 the first path + * @param path2 the second path + * @return true if the first path is the descendant of the second path. + */ + private boolean isDescendant(TreePath path1, TreePath path2) { + Object obj1[] = path1.getPath(); + Object obj2[] = path2.getPath(); + if (obj1.length < obj2.length) + return false; + for (int i = 0; i < obj2.length; i++) { + if (obj1[i] != obj2[i]) + return false; + } + return true; + } + + private boolean _fireEvent = true; + +// @SuppressWarnings({"RawUseOfParameterizedType"}) +// @Override + protected void notifyPathChange(Vector changedPaths, TreePath oldLeadSelection) { + if (_fireEvent) { + super.notifyPathChange(changedPaths, oldLeadSelection); + } + } + + /** + * Overrides the method in DefaultTreeSelectionModel to consider digIn mode. + * + * @param pPaths the tree paths to be selected. + */ +// @Override + public void setSelectionPaths(TreePath[] pPaths) { + if (!isDigIn() || selectionMode == TreeSelectionModel.SINGLE_TREE_SELECTION) { + super.setSelectionPaths(pPaths); + } + else { + clearSelection(); + addSelectionPaths(pPaths); + } + } + + /** + * Overrides the method in DefaultTreeSelectionModel to consider digIn mode. + * + * @param paths the tree paths to be added to selection paths. + */ + public void addSelectionPaths(TreePath[] paths) { + if (!isDigIn()) { + super.addSelectionPaths(paths); + return; + } + + boolean fireEventAtTheEnd = false; + if (isSingleEventMode() && _fireEvent) { + _fireEvent = false; + fireEventAtTheEnd = true; + } + + try { + // unselect all descendants of paths[] + List toBeRemoved = new ArrayList(); + for (int i = 0, plength = paths.length; i < plength; i++) { + TreePath path = paths[i]; + TreePath[] selectionPaths = getSelectionPaths(); + if (selectionPaths == null) + break; + for (int j = 0, splength = selectionPaths.length; j < splength; j++) { + TreePath selectionPath = selectionPaths[j]; + if (isDescendant(selectionPath, path)) + toBeRemoved.add(selectionPath); + } + } +// for (TreePath path : paths) { +// TreePath[] selectionPaths = getSelectionPaths(); +// if (selectionPaths == null) +// break; +// for (TreePath selectionPath : selectionPaths) { +// if (isDescendant(selectionPath, path)) +// toBeRemoved.add(selectionPath); +// } +// } + if (toBeRemoved.size() > 0) { + delegateRemoveSelectionPaths((TreePath[]) toBeRemoved.toArray(new TreePath[toBeRemoved.size()])); + } + + // if all siblings are selected then unselect them and select parent recursively + // otherwize just select that path. +// for (TreePath path : paths) { + for (int i = 0, length = paths.length; i < length; i++) { + TreePath path = paths[i]; + TreePath temp = null; + while (areSiblingsSelected(path)) { + temp = path; + if (path.getParentPath() == null) + break; + path = path.getParentPath(); + } + if (temp != null) { + if (temp.getParentPath() != null) { + addSelectionPath(temp.getParentPath()); + } + else { + if (!isSelectionEmpty()) { + removeSelectionPaths(getSelectionPaths()); + } + delegateAddSelectionPaths(new TreePath[]{temp}); + } + } + else { + delegateAddSelectionPaths(new TreePath[]{path}); + } + } + } + finally { + _fireEvent = true; + if (isSingleEventMode() && fireEventAtTheEnd) { + notifyPathChange(paths, true, paths[0]); + } + } + } + + /** + * tells whether all siblings of given path are selected. + * + * @param path the tree path + * @return true if the siblings are all selected. + */ + private boolean areSiblingsSelected(TreePath path) { + TreePath parent = path.getParentPath(); + if (parent == null) + return true; + Object node = path.getLastPathComponent(); + Object parentNode = parent.getLastPathComponent(); + + int childCount = _model.getChildCount(parentNode); + for (int i = 0; i < childCount; i++) { + Object childNode = _model.getChild(parentNode, i); + if (childNode == node) + continue; + TreePath childPath = parent.pathByAddingChild(childNode); + if (_tree != null && !_tree.isCheckBoxVisible(childPath)) + continue; + if (!isPathSelected(childPath)) { + return false; + } + } + return true; + } + +// @Override + public void removeSelectionPaths(TreePath[] paths) { + if (!isDigIn()) { + super.removeSelectionPaths(paths); + return; + } + + List toBeRemoved = new ArrayList(); +// for (TreePath path : paths) { + for (int i = 0, length = paths.length; i < length; i++) { + TreePath path = paths[i]; + if (path.getPathCount() == 1) { + toBeRemoved.add(path); + } + else { + toggleRemoveSelection(path); + } + } + if (toBeRemoved.size() > 0) { + delegateRemoveSelectionPaths((TreePath[]) toBeRemoved.toArray(new TreePath[toBeRemoved.size()])); + } + } + + /** + * If any ancestor node of given path is selected then unselect + * it and selection all its descendants except given path and descendants. + * Otherwise just unselect the given path + * + * @param path the tree path + */ + private void toggleRemoveSelection(TreePath path) { + boolean fireEventAtTheEnd = false; + if (isSingleEventMode() && _fireEvent) { + _fireEvent = false; + fireEventAtTheEnd = true; + } + + try { + Stack stack = new Stack(); + TreePath parent = path.getParentPath(); + while (parent != null && !isPathSelected(parent)) { + stack.push(parent); + parent = parent.getParentPath(); + } + if (parent != null) + stack.push(parent); + else { + delegateRemoveSelectionPaths(new TreePath[]{path}); + return; + } + + List toBeAdded = new ArrayList(); + while (!stack.isEmpty()) { + TreePath temp = (TreePath) stack.pop(); + TreePath peekPath = (TreePath) (stack.isEmpty() ? path : stack.peek()); + Object node = temp.getLastPathComponent(); + Object peekNode = peekPath.getLastPathComponent(); + int childCount = _model.getChildCount(node); + for (int i = 0; i < childCount; i++) { + Object childNode = _model.getChild(node, i); + if (childNode != peekNode) { + TreePath treePath = temp.pathByAddingChild(childNode); + if (_tree.isCheckBoxVisible(treePath) && _tree.isCheckBoxEnabled(treePath)) { + toBeAdded.add(treePath); + } + } + } + } + if (toBeAdded.size() > 0) { + delegateAddSelectionPaths((TreePath[]) toBeAdded.toArray(new TreePath[toBeAdded.size()])); + } + delegateRemoveSelectionPaths(new TreePath[]{parent}); + } + finally { + _fireEvent = true; + if (isSingleEventMode() && fireEventAtTheEnd) { + notifyPathChange(new TreePath[]{path}, false, path); + } + } + } + + public boolean isSingleEventMode() { + return _singleEventMode; + } + + /** + * Single event mode is a mode that always fires only one event when you select or unselect a tree node. + *

+ * Taking this tree as an example, + *

+ *

+     * A -- a
+     *    |- b
+     *    |- c
+     * 
+ * Case 1: Assuming b and c are selected at this point, you click on a. + *
+ *
    + *
  • In non-single event mode, you will get select-A, deselect-b and deselect-c three events + *
  • In single event mode, you will only get select-a. + *
+ *

+ * Case 2: Assuming none of the nodes are selected, you click on A. In this case, both modes result in the same behavior. + *

    + *
  • In non-single event mode, you will get only select-A event. + *
  • In single event mode, you will only get select-A too. + *
+ * Case 3: Assuming b and c are selected and now you click on A. + *
    + *
  • In non-single event mode, you will get select-A event as well as deselect-b and deselect-c event. + *
  • In single event mode, you will only get select-A. + *
+ * As you can see, single event mode will always fire the event on the nodes you select. However it doesn't reflect + * what really happened inside the selection model. So if you want to get + * a complete picture of the selection state inside selection model, you should use {@link #getSelectionPaths()} to find out. + * In non-single event mode, the events reflect what happened inside the selection model. So you can get a complete picture + * of the exact state without asking the selection model. The downside is it will generate too many events. With this option, you + * can decide which mode you want to use that is the best for your case. + *

+ * By default, singleEventMode is set to false to be compatible with the older versions that don't have this option. + * + * @param singleEventMode true or false. + */ + public void setSingleEventMode(boolean singleEventMode) { + _singleEventMode = singleEventMode; + } + + /** + * Notifies listeners of a change in path. changePaths should contain + * instances of PathPlaceHolder. + * + * @param changedPaths the paths that are changed. + * @param isNew is it a new path. + * @param oldLeadSelection the old selection. + */ + protected void notifyPathChange(TreePath[] changedPaths, boolean isNew, TreePath oldLeadSelection) { + int cPathCount = changedPaths.length; + boolean[] newness = new boolean[cPathCount]; + + for (int counter = 0; counter < cPathCount; counter++) { + newness[counter] = isNew; + } + + TreeSelectionEvent event = new TreeSelectionEvent + (this, changedPaths, newness, oldLeadSelection, leadPath); + + fireValueChanged(event); + } + + // do not use it for now + private boolean _batchMode = false; + + private boolean isBatchMode() { + return _batchMode; + } + + public void setBatchMode(boolean batchMode) { + _batchMode = batchMode; + if (!_batchMode) { + super.addSelectionPaths((TreePath[]) _toBeAdded.toArray(new TreePath[_toBeAdded.size()])); + _toBeAdded.clear(); + super.removeSelectionPaths((TreePath[]) _toBeRemoved.toArray(new TreePath[_toBeRemoved.size()])); + _toBeRemoved.clear(); + } + } + + private List _toBeAdded = new ArrayList(); + private List _toBeRemoved = new ArrayList(); + + private void delegateRemoveSelectionPaths(TreePath[] paths) { + if (!isBatchMode()) { + super.removeSelectionPaths(paths); + } + else { +// for (TreePath path : paths) { + for (int i = 0, length = paths.length; i < length; i++) { + TreePath path = paths[i]; + _toBeRemoved.add(path); + _toBeAdded.remove(path); + } + } + } + + private void delegateRemoveSelectionPath(TreePath path) { + if (!isBatchMode()) { + super.removeSelectionPath(path); + } + else { + _toBeRemoved.add(path); + _toBeAdded.remove(path); + } + + } + + private void delegateAddSelectionPaths(TreePath[] paths) { + if (!isBatchMode()) { + super.addSelectionPaths(paths); + } + else { +// for (TreePath path : paths) { + for (int i = 0, length = paths.length; i < length; i++) { + TreePath path = paths[i]; + _toBeAdded.add(path); + _toBeRemoved.remove(path); + } + } + } + + private void delegateAddSelectionPath(TreePath path) { + if (!isBatchMode()) { + super.addSelectionPath(path); + } + else { + _toBeAdded.add(path); + _toBeRemoved.remove(path); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullLabel.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullLabel.java new file mode 100644 index 0000000000..75e45fafb2 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullLabel.java @@ -0,0 +1,86 @@ +/* + * @(#)HollowLabel.java 7/12/2005 + * Modified by FineReport + * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved. + */ +package com.fr.design.gui.itree.checkboxtree; + +import javax.swing.Icon; +import com.fr.design.gui.ilable.UILabel; + +/** + * This is part of the null-components. A null component doesn't have + * foreground, background or font value set. In the other words, the + * foreground, background and font value of null-component are null. + * But this doesn't mean getBackground(), getForeground() or getFont() + * will return null. According to {@link java.awt.Component#getBackground()}, + * {@link java.awt.Component#getForeground()} and {@link java.awt.Component#getFont()}, + * if the value is null, it will get the value from its parent. + * In the other words, if you add a null-component to JPanel, you can use + * JPanel to control the background, foreground and font of this null-component. + * The feature is very helpful if you want to make sure all components in a JPanel + * has the same background, foreground or font. + *

+ * We creates a few null-components. It doesn't cover all components. You can always + * create your own. All you need to do is this + *


+ * public class NullXxxComponent extends XxxComponent {
+ *     // all the constructors
+ * 

+ * public void updateUI() { + * super.updateUI(); + * clearAttribute(); + * } + *

+ * private void clearAttribute() { + * setFont(null); + * setBackground(null); + * // do not do this for UIButton since UIButton always paints button + * // content background. So it'd better to leave the foreground alone + * setForeground(null); + * } + * } + *

+ * + * @see NullPanel + * @see NullCheckBox + * @see NullJideButton + * @see NullButton + * @see NullRadioButton + */ +public class NullLabel extends UILabel { + public NullLabel() { + } + + public NullLabel(String text, Icon icon, int horizontalAlignment) { + super(text, icon, horizontalAlignment); + } + + public NullLabel(String text, int horizontalAlignment) { + super(text, horizontalAlignment); + } + + public NullLabel(String text) { + super(text); + } + + public NullLabel(Icon image, int horizontalAlignment) { + super(image, horizontalAlignment); + } + + public NullLabel(Icon image) { + super(image); + } + +// @Override + public void updateUI() { + super.updateUI(); + clearAttribute(); + } + + private void clearAttribute() { + setFont(null); + setBackground(null); + setForeground(null); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullPanel.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullPanel.java new file mode 100644 index 0000000000..aace3b414c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullPanel.java @@ -0,0 +1,79 @@ +/* + * @(#)HollowPanel.java 7/12/2005 + * Modified by FineReport + * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved. + */ +package com.fr.design.gui.itree.checkboxtree; + +import java.awt.LayoutManager; + +import javax.swing.JPanel; + +/** + * This is part of the null-components. A null component doesn't have + * foreground, background or font value set. In the other words, the + * foreground, background and font value of null-component are null. + * But this doesn't mean getBackground(), getForeground() or getFont() + * will return null. According to {@link java.awt.Component#getBackground()}, + * {@link java.awt.Component#getForeground()} and {@link java.awt.Component#getFont()}, + * if the value is null, it will get the value from its parent. + * In the other words, if you add a null-component to JPanel, you can use + * JPanel to control the background, foreground and font of this null-component. + * The feature is very helpful if you want to make sure all components in a JPanel + * has the same background, foreground or font. + *

+ * We creates a few null-components. It doesn't cover all components. You can always + * create your own. All you need to do is this + *


+ * public class NullXxxComponent extends XxxComponent {
+ *     // all the constructors
+ * 

+ * public void updateUI() { + * super.updateUI(); + * clearAttribute(); + * } + *

+ * private void clearAttribute() { + * setFont(null); + * setBackground(null); + * // do not do this for UIButton since UIButton always paints button + * // content background. So it'd better to leave the foreground alone + * setForeground(null); + * } + * } + *

+ * + * @see NullButton + * @see NullCheckBox + * @see NullJideButton + * @see NullLabel + * @see NullRadioButton + */ +public class NullPanel extends JPanel { + public NullPanel() { + } + + public NullPanel(boolean isDoubleBuffered) { + super(isDoubleBuffered); + } + + public NullPanel(LayoutManager layout) { + super(layout); + } + + public NullPanel(LayoutManager layout, boolean isDoubleBuffered) { + super(layout, isDoubleBuffered); + } + +// @Override + public void updateUI() { + super.updateUI(); + clearAttribute(); + } + + private void clearAttribute() { + setFont(null); + setBackground(null); + setForeground(null); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java new file mode 100644 index 0000000000..0642f96f4a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java @@ -0,0 +1,77 @@ +/* + * @(#)NullTristateCheckBox.java 8/11/2005 + * Modified by FineReport + * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved. + */ +package com.fr.design.gui.itree.checkboxtree; + +import javax.swing.Icon; + +/** + * This is part of the null-components. A null component doesn't have + * foreground, background or font value set. In the other words, the + * foreground, background and font value of null-component are null. + * But this doesn't mean getBackground(), getForeground() or getFont() + * will return null. According to {@link java.awt.Component#getBackground()}, + * {@link java.awt.Component#getForeground()} and {@link java.awt.Component#getFont()}, + * if the value is null, it will get the value from its parent. + * In the other words, if you add a null-component to JPanel, you can use + * JPanel to control the background, foreground and font of this null-component. + * The feature is very helpful if you want to make sure all components in a JPanel + * has the same background, foreground or font. + *

+ * We creates a few null-components. It doesn't cover all components. You can always + * create your own. All you need to do is this + *


+ * public class NullXxxComponent extends XxxComponent {
+ *     // all the constructors
+ * 

+ * public void updateUI() { + * super.updateUI(); + * clearAttribute(); + * } + *

+ * private void clearAttribute() { + * setFont(null); + * setBackground(null); + * // do not do this for UIButton since UIButton always paints button + * // content background. So it'd better to leave the foreground alone + * setForeground(null); + * } + * } + *

+ * + * @see NullPanel + * @see NullButton + * @see NullJideButton + * @see NullLabel + * @see NullRadioButton + */ +public class NullTristateCheckBox extends TristateCheckBox { + public NullTristateCheckBox() { + } + + public NullTristateCheckBox(String text) { + super(text); + } + + public NullTristateCheckBox(String text, State initial) { + super(text, initial); + } + + public NullTristateCheckBox(String text, Icon icon, State initial) { + super(text, icon, initial); + } + +// @Override + public void updateUI() { + super.updateUI(); + clearAttribute(); + } + + private void clearAttribute() { + setFont(null); + setBackground(null); + setForeground(null); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java b/designer_base/src/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java new file mode 100644 index 0000000000..09879cd98f --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java @@ -0,0 +1,307 @@ +package com.fr.design.gui.itree.checkboxtree; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.ButtonGroup; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ActionMapUIResource; + +import com.fr.design.gui.icheckbox.UICheckBox; + +/** + * Maintenance tip - There were some tricks to getting this code + * working: + *

+ * 1. You have to overwite addMouseListener() to do nothing + * 2. You have to add a mouse event on mousePressed by calling + * super.addMouseListener() + * 3. You have to replace the UIActionMap for the keyboard event + * "pressed" with your own one. + * 4. You have to remove the UIActionMap for the keyboard event + * "released". + * 5. You have to grab focus when the next state is entered, + * otherwise clicking on the component won't get the focus. + * 6. You have to make a TristateDecorator as a button model that + * wraps the original button model and does state management. + * + * @author Dr. Heinz M. Kabutz + */ +public class TristateCheckBox extends UICheckBox { + /** + * This is a type-safe enumerated type + */ + public static class State { + private State() { + } + } + + public static final State NOT_SELECTED = new State(); + public static final State SELECTED = new State(); + public static final State DONT_CARE = new State(); + + private final TristateDecorator model; + + public TristateCheckBox(String text, Icon icon, State initial) { + super(text, icon); + // Add a listener for when the mouse is pressed + super.addMouseListener(new MouseAdapter() { +// @Override + public void mousePressed(MouseEvent e) { + grabFocus(); + model.setState(getNextState(model.getState())); + } + }); + // Reset the keyboard action map + ActionMap map = new ActionMapUIResource(); + map.put("pressed", new AbstractAction() { + public void actionPerformed(ActionEvent e) { + grabFocus(); + model.setState(getNextState(model.getState())); + } + }); + map.put("released", null); + SwingUtilities.replaceUIActionMap(this, map); + // set the model to the adapted model + model = new TristateDecorator(getModel()); + setModel(model); + setState(initial); + } + + public TristateCheckBox(String text, State initial) { + this(text, null, initial); + } + + public TristateCheckBox(String text) { + this(text, DONT_CARE); + } + + public TristateCheckBox() { + this(null); + } + + /** + * No one may add mouse listeners, not even Swing! + */ +// @Override + public void addMouseListener(MouseListener l) { + } + + /** + * Set the new state to either SELECTED, NOT_SELECTED or + * DONT_CARE. If state == null, it is treated as DONT_CARE. + */ + public void setState(State state) { + model.setState(state); + } + + /** + * Return the current state, which is determined by the + * selection status of the model. + */ + public State getState() { + return model.getState(); + } + +// @Override + public void setSelected(boolean b) { + if (b) { + setState(SELECTED); + } + else { + setState(NOT_SELECTED); + } + } + + /** + * Exactly which Design Pattern is this? Is it an Adapter, + * a Proxy or a Decorator? In this case, my vote lies with the + * Decorator, because we are extending functionality and + * "decorating" the original model with a more powerful model. + */ + private class TristateDecorator implements ButtonModel { + private final ButtonModel other; + + private TristateDecorator(ButtonModel other) { + this.other = other; + } + + private void setState(State state) { + if (state == NOT_SELECTED) { + other.setArmed(false); + setPressed(false); + setSelected(false); + } + else if (state == SELECTED) { + other.setArmed(false); + setPressed(false); + setSelected(true); + } + else { // either "null" or DONT_CARE + other.setArmed(true); + setPressed(true); + setSelected(true); + } + } + + /** + * The current state is embedded in the selection / armed + * state of the model. + *

+ * We return the SELECTED state when the checkbox is selected + * but not armed, DONT_CARE state when the checkbox is + * selected and armed (grey) and NOT_SELECTED when the + * checkbox is deselected. + */ + private State getState() { + if (isSelected() && !isArmed()) { + // normal black tick + return SELECTED; + } + else if (isSelected() && isArmed()) { + // don't care grey tick + return DONT_CARE; + } + else { + // normal deselected + return NOT_SELECTED; + } + } + + /** + * Filter: No one may change the armed status except us. + */ + public void setArmed(boolean b) { + } + + /** + * We disable focusing on the component when it is not + * enabled. + */ + public void setEnabled(boolean b) { + setFocusable(b); + other.setEnabled(b); + } + + /** + * All these methods simply delegate to the "other" model + * that is being decorated. + */ + public boolean isArmed() { + return other.isArmed(); + } + + public boolean isSelected() { + return other.isSelected(); + } + + public boolean isEnabled() { + return other.isEnabled(); + } + + public boolean isPressed() { + return other.isPressed(); + } + + public boolean isRollover() { + return other.isRollover(); + } + + public void setSelected(boolean b) { + other.setSelected(b); + } + + public void setPressed(boolean b) { + other.setPressed(b); + } + + public void setRollover(boolean b) { + other.setRollover(b); + } + + public void setMnemonic(int key) { + other.setMnemonic(key); + } + + public int getMnemonic() { + return other.getMnemonic(); + } + + public void setActionCommand(String s) { + other.setActionCommand(s); + } + + public String getActionCommand() { + return other.getActionCommand(); + } + + public void setGroup(ButtonGroup group) { + other.setGroup(group); + } + + public void addActionListener(ActionListener l) { + other.addActionListener(l); + } + + public void removeActionListener(ActionListener l) { + other.removeActionListener(l); + } + + public void addItemListener(ItemListener l) { + other.addItemListener(l); + } + + public void removeItemListener(ItemListener l) { + other.removeItemListener(l); + } + + public void addChangeListener(ChangeListener l) { + other.addChangeListener(l); + } + + public void removeChangeListener(ChangeListener l) { + other.removeChangeListener(l); + } + + public Object[] getSelectedObjects() { + return other.getSelectedObjects(); + } + } + + /** + * We rotate between NOT_SELECTED, SELECTED and DONT_CARE. Subclass can + * override this method to tell the check box what next state is. Here is + * the default implementation. + *

+     *   if (current == NOT_SELECTED) {
+     *       return SELECTED;
+     *   }
+     *   else if (current == SELECTED) {
+     *       return DONT_CARE;
+     *   }
+     *   else {
+     *       return NOT_SELECTED;
+     *   }
+     * 
+ */ + protected State getNextState(State current) { + if (current == NOT_SELECTED) { + return SELECTED; + } + else if (current == SELECTED) { + return DONT_CARE; + } + else /*if (current == DONT_CARE)*/ { + return NOT_SELECTED; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/AbstractFileTree.java b/designer_base/src/com/fr/design/gui/itree/filetree/AbstractFileTree.java new file mode 100644 index 0000000000..8075202346 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/AbstractFileTree.java @@ -0,0 +1,105 @@ +package com.fr.design.gui.itree.filetree; + +import java.io.File; + +import javax.swing.JTree; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import com.fr.general.ComparatorUtils; + +/** + * 文件结构树. + */ +public abstract class AbstractFileTree extends JTree implements TreeExpansionListener { + /** + * 列出所有的FileNode. + */ + public abstract FileDirectoryNode[] listFileNodes(DefaultMutableTreeNode currentTreeNode); + + /** + * 展开TreeNode. + */ + public boolean expandTreeNode(DefaultMutableTreeNode currentTreeNode) { + if (currentTreeNode.isLeaf()) { + return false; + } + + //判断第一个孩子节点. + DefaultMutableTreeNode flag = (DefaultMutableTreeNode) currentTreeNode.getFirstChild(); + if (flag == null) { // No flag + return false; + } + Object firstChildObj = flag.getUserObject(); + if (!(firstChildObj instanceof Boolean)) { + return false; // Already expanded + } + currentTreeNode.removeAllChildren(); //删除所有的节点. + + // 列出所有的子文件夹. + FileDirectoryNode[] fileNodes = listFileNodes(currentTreeNode); + // 如果所得为空,(此时 isDirectory是true 但是拿不到子文件 所以不应该展开文件夹) + // 或者文件夹中没有文件. + if ( fileNodes == null) { + return false; + } + for (int i = 0; i < fileNodes.length; i++) { + FileDirectoryNode tmpNameNode = fileNodes[i]; + + DefaultMutableTreeNode node = new DefaultMutableTreeNode(tmpNameNode); + currentTreeNode.add(node); + + // 如果是目录,需要添加子节点. + if (tmpNameNode.isDirectory()) { + // 如果有目录但是列不出子文件 就不添加子节点. + // 或者文件夹中没有子文件的 也不添加子节点.kt + FileDirectoryNode[] childFileNode = listFileNodes(node); + if (childFileNode != null ) { + node.add(new DefaultMutableTreeNode(Boolean.TRUE)); + } + } + } + + // 重新加载parentTreeNode. + ((DefaultTreeModel) this.getModel()).reload(currentTreeNode); +// this.expandPath(GUICoreUtils.getTreePath(currentTreeNode)); + + return true; + } + + protected DefaultMutableTreeNode getMutableTreeNode(TreePath path) { + return (DefaultMutableTreeNode) (path.getLastPathComponent()); + } + + public void treeExpanded(TreeExpansionEvent event) { + DefaultMutableTreeNode currentTreeNode = getMutableTreeNode(event.getPath()); + // 判断当前文件节点所得子文件为null时 不展开节点. + FileDirectoryNode[] fileNodes = listFileNodes(currentTreeNode); + if(fileNodes != null) { + this.expandTreeNode(currentTreeNode); + } + } + + public void treeCollapsed(TreeExpansionEvent event) { + } + + /** + * 是否是父子关系的文件. + */ + public static boolean isParentFile(File parentFile, File childFile) { + while (true) { + if (ComparatorUtils.equals(parentFile, childFile)) { + return true; + } + + childFile = childFile.getParentFile(); + if (childFile == null) { + break; + } + } + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/ClassFileTree.java b/designer_base/src/com/fr/design/gui/itree/filetree/ClassFileTree.java new file mode 100644 index 0000000000..3ab3710b48 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/ClassFileTree.java @@ -0,0 +1,63 @@ +package com.fr.design.gui.itree.filetree; + +import java.io.File; + +import com.fr.file.filetree.FileNode; +import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.stable.project.ProjectConstants; + +/* + * 显示Env下的classes目录下面的所有class文件 + */ +public class ClassFileTree extends EnvFileTree { + public ClassFileTree() { + super(ProjectConstants.CLASSES_NAME, null, new IOFileNodeFilter(new String[]{"class"})); + } + + /* + * 选中class + */ + public void setSelectedClassPath(String classPath) { + if(classPath == null || !classPath.endsWith(".class")) { + return; + } + + String[] dirs = classPath.split("\\."); + + StringBuffer sb = new StringBuffer(); + for(int i = 0; i < dirs.length; i++) { + if(i == dirs.length - 1) { + sb.append('.'); + } else if (i > 0) { + sb.append(File.separatorChar); + } + + sb.append(dirs[i]); + } + + this.selectPath(sb.toString()); + } + + /* + * 返回选中的Class的路径 + */ + public String getSelectedClassPath() { + FileNode fn = this.getSelectedFileNode(); + if(fn != null && !fn.isDirectory()) { + String envPath = fn.getEnvPath(); + + if(envPath.startsWith(ProjectConstants.CLASSES_NAME)) { + String resPath = envPath.substring(ProjectConstants.CLASSES_NAME.length() + 1); + + resPath = resPath.replaceAll("[/\\\\]", "."); + //marks:去掉.class后缀 + if (resPath.toLowerCase().endsWith(".class")) { + resPath = resPath.substring(0,resPath.length() - ".class".length()); + } + return resPath; + } + } + + return null; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/EnvFileTree.java b/designer_base/src/com/fr/design/gui/itree/filetree/EnvFileTree.java new file mode 100644 index 0000000000..436ea911cf --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/EnvFileTree.java @@ -0,0 +1,366 @@ +package com.fr.design.gui.itree.filetree; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.dnd.DnDConstants; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + +import com.fr.design.constants.UIConstants; +import com.fr.design.event.TemplateTreeDragSource; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.gui.itree.refreshabletree.RefreshableJTree; +import com.fr.file.filetree.FileNode; +import com.fr.file.filetree.FileNodeFilter; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.CoreConstants; +import com.fr.stable.StableUtils; + +/* + * 文件结构树. + */ +public class EnvFileTree extends RefreshableJTree { + + protected FileNodeFilter filter; + protected Env env; + protected String treeRootPath = ""; + protected String[] subPathes; + + public EnvFileTree() { + this(null, null); + } + + public EnvFileTree(String[] subPathes, FileNodeFilter filter) { + this("", subPathes, filter); + } + + public EnvFileTree(String treeRootPath, String[] subPathes, FileNodeFilter filter) { + super(new FileNode(treeRootPath, true)); + + this.setTreeRootPath(treeRootPath); + this.setFileNodeFilter(filter); + this.setSubPathes(subPathes); + + this.init(); + } + + private void setTreeRootPath(String path) { + if (path == null) { + path = ""; + } + + this.treeRootPath = path; + } + + public void setFileNodeFilter(FileNodeFilter filter) { + this.filter = filter; + } + + protected void init() { + this.putClientProperty("JTree.lineStyle", "Angled"); + + this.setCellRenderer(fileTreeCellRenderer); + + this.setRootVisible(false); + this.setShowsRootHandles(true); + this.setEditable(false); + new TemplateTreeDragSource(this, DnDConstants.ACTION_COPY); + } + + // CellRenderer + private DefaultTreeCellRenderer fileTreeCellRenderer = new DefaultTreeCellRenderer() { + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) value; + Object userObj = treeNode.getUserObject(); + if (userObj instanceof FileNode) { + FileNode node = (FileNode) userObj; + String lock = node.getLock(); + String name = node.getName(); + if (lock != null && !node.getUserID().equals(lock)) { + name = name + Inter.getLocText("Locked"); + this.setIcon(FileTreeIcon.getIcon(node)); + }else { + this.setIcon(FileTreeIcon.getIcon(node, false)); + } + this.setText(name); + } else if (userObj == PENDING) { + this.setIcon(null); + this.setText(PENDING.toString()); + } + // 这里新建一个Label作为render是因为JTree在动态刷新的时候,节点上render画布的的宽度不会变,会使得一部分比较长的数据显示为"..." + UILabel label = new UILabel(); + label.setText(getText()); + label.setIcon(getIcon()); + this.setSize(label.getPreferredSize()); + Dimension dim = label.getPreferredSize(); + dim.height += 2; + this.setPreferredSize(dim); + this.setBackgroundNonSelectionColor(UIConstants.NORMAL_BACKGROUND); + this.setForeground(UIConstants.FONT_COLOR); + this.setBackgroundSelectionColor(UIConstants.FLESH_BLUE); + return this; + } + }; + + /* + * 在当前tree中选中currentPath + */ + public void selectPath(String currentPath) { + if (currentPath == null) { + return; + } + + DefaultTreeModel m_model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) m_model.getRoot(); + for (int i = 0, len = treeNode.getChildCount(); i < len; i++) { + // 取出当前的childTreeNode,并append到searchingPath后面 + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i); + + if (selectFilePath(childTreeNode, "", currentPath, m_model)) { + break; + } + } + + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath != null) { + this.scrollPathToVisible(selectedTreePath); + } + } + + /* + * 在currentTreeNode下找寻filePath + * + * prefix + currentTreeNode.getName() = currentTreeNode所对应的Path + * + * 返回currentTreeNode下是否找到了filePath + */ + private boolean selectFilePath(ExpandMutableTreeNode currentTreeNode, String prefix, String filePath, DefaultTreeModel m_model) { + FileNode fileNode = (FileNode) currentTreeNode.getUserObject(); + String nodePath = fileNode.getName(); + String currentTreePath = prefix + nodePath; + + // 如果equals,说明找到了,不必再找下去了 + if (ComparatorUtils.equals(new File(currentTreePath), new File(filePath))) { + this.setSelectionPath(new TreePath(m_model.getPathToRoot(currentTreeNode))); + return true; + } // 如果当前路径是currentFilePath的ParnetFile,则expandTreeNode,并继续往下找 + else if (EnvFileTree.isParentFile(currentTreePath, filePath)) { + this.loadPendingChildTreeNode(currentTreeNode); + + prefix = currentTreePath + CoreConstants.SEPARATOR; + for (int i = 0, len = currentTreeNode.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) currentTreeNode.getChildAt(i); + + if (selectFilePath(childTreeNode, prefix, filePath, m_model)) { + return true; + } + } + return false; + } + + return false; + } + + /* + * 求当前TreeNode下所有的FileNode. + */ + private FileNode[] listFileNodes(ExpandMutableTreeNode currentTreeNode) { + if (currentTreeNode == null) { + return new FileNode[0]; + } + + Object object = currentTreeNode.getUserObject(); + + if (object instanceof FileNode) { + return this.listFileNodes(((FileNode) object).getEnvPath()); + } + + return new FileNode[0]; + } + + /* + * 求filePath这个String,求其路径下面的所有的FileNode + */ + private FileNode[] listFileNodes(String filePath) { + FileNode[] res_fns = null; + + try { + res_fns = env == null ? new FileNode[0] : env.listFile(filePath); + } catch (Exception e) { + FRContext.getLogger().error(e.getMessage(), e); + } + + if (res_fns == null) { + res_fns = new FileNode[0]; + } + + // 用FileNodeFilter过滤一下 + if (filter != null) { + java.util.List t_list = new ArrayList(); + for (int i = 0; i < res_fns.length; i++) { + if (filter.accept(res_fns[i])) { + t_list.add(res_fns[i]); + } + } + + res_fns = t_list.toArray(new FileNode[t_list.size()]); + } + + Arrays.sort(res_fns, new FileNodeComparator()); + + return res_fns; + } + + /* + * 获取当前选中的FilePath的String,这个FilePath是需要拼起来的 + */ + public FileNode getSelectedFileNode() { + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath == null) { + return null; + } + + ExpandMutableTreeNode currentTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object userObject = currentTreeNode.getUserObject(); + + if (userObject instanceof FileNode) { + return (FileNode) userObject; + } + + return null; + } + + /* + * 改变Env后,根据构造函数时设置的RootPathes,重新加载 + */ + public void refreshEnv(Env env) { + this.env = env; + + DefaultTreeModel m_model = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) m_model.getRoot(); + rootTreeNode.removeAllChildren(); + + FileNode[] fns; + + // 如果rootPaths是null的话列出所有文件 + if (subPathes == null) { + fns = listFileNodes(this.treeRootPath); + } else { + // 重新加载新的FileDirectoryNode + fns = new FileNode[subPathes.length]; + for (int i = 0; i < subPathes.length; i++) { + fns[i] = new FileNode(StableUtils.pathJoin(new String[]{this.treeRootPath, subPathes[i]}), true); + } + } + + + ExpandMutableTreeNode[] sub_tree_node_array = fileNodeArray2TreeNodeArray(fns); + + for (int i = 0; i < sub_tree_node_array.length; i++) { + ExpandMutableTreeNode node = sub_tree_node_array[i]; + rootTreeNode.add(node); + } + + m_model.reload(rootTreeNode); + } + + /* + * 设置当前Tree的rootPathes + */ + private void setSubPathes(String[] subPathes) { + this.subPathes = subPathes; + } + + /** + * currentTreeNode下面如果是PENDING的节点,加载之... + */ + private void loadPendingChildTreeNode(ExpandMutableTreeNode currentTreeNode) { + if (currentTreeNode.isLeaf()) { + return; + } + + // 判断第一个孩子节点.UserObject是不是PENDING,如果是PENDING的话,需要重新加载这个TreeNode + ExpandMutableTreeNode flag = (ExpandMutableTreeNode) currentTreeNode.getFirstChild(); + if (flag == null || flag.getUserObject() != PENDING) { + return; + } + currentTreeNode.removeAllChildren(); // 删除所有的节点. + + ExpandMutableTreeNode[] children = loadChildTreeNodes(currentTreeNode); + for (ExpandMutableTreeNode c : children) { + currentTreeNode.add(c); + } + } + + /* + * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh + */ + protected boolean interceptRefresh(ExpandMutableTreeNode eTreeNode) { + Object userObject = eTreeNode.getUserObject(); + if (userObject instanceof FileNode && !((FileNode) userObject).isDirectory()) { + return true; + } + + return eTreeNode.getChildCount() == 1 && ((ExpandMutableTreeNode) eTreeNode.getFirstChild()).getUserObject() == PENDING; + } + + /* + * 得到treeNode的子节点ExpandMutableTreeNode的数组 + */ + protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode) { + FileNode[] fn_array = listFileNodes(treeNode); + + return fileNodeArray2TreeNodeArray(fn_array); + } + + /* + * 把FileNode[]转成ExpandMutableTreeNode[] + */ + private ExpandMutableTreeNode[] fileNodeArray2TreeNodeArray(FileNode[] fn_array) { + ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[fn_array.length]; + for (int i = 0; i < res.length; i++) { + FileNode fn = fn_array[i]; + res[i] = new ExpandMutableTreeNode(fn); + if (fn.isDirectory()) { + res[i].add(new ExpandMutableTreeNode()); + } + } + + return res; + } + + /* + * 是否是父子关系的文件. + */ + private static boolean isParentFile(String parentFilePath, String childFilePath) { + File parentFile = new File(parentFilePath); + File childFile = new File(childFilePath); + + while (true) { + if (ComparatorUtils.equals(parentFile, childFile)) { + return true; + } + + childFile = childFile.getParentFile(); + if (childFile == null) { + break; + } + } + + return false; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/FileComparator.java b/designer_base/src/com/fr/design/gui/itree/filetree/FileComparator.java new file mode 100644 index 0000000000..cf4e6812a0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/FileComparator.java @@ -0,0 +1,23 @@ +package com.fr.design.gui.itree.filetree; + +import java.util.Comparator; + +public class FileComparator implements Comparator { + + public int compare(java.io.File file1, java.io.File file2) { + if (file1.isDirectory()) { + if (file2.isDirectory()) { + return file1.getName().toLowerCase().compareTo(file2.getName().toLowerCase()); + } else { + return -1; + } + } else { + if (file2.isDirectory()) { + return 1; + } else { + return file1.getName().toLowerCase().compareTo(file2.getName().toLowerCase()); + } + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/FileDirectoryNode.java b/designer_base/src/com/fr/design/gui/itree/filetree/FileDirectoryNode.java new file mode 100644 index 0000000000..1cfd2d2b85 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/FileDirectoryNode.java @@ -0,0 +1,56 @@ +package com.fr.design.gui.itree.filetree; + +import java.io.File; + +/** + * 文件节点,用于存放文件的 name 和 isDirectory属性 + */ +public class FileDirectoryNode implements java.io.Serializable, Cloneable { + private String name; + private boolean isDirectory; + private boolean canRead; + + public FileDirectoryNode() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setCanRead(boolean canRead) { + this.canRead = canRead; + } + + public boolean isCanRead() { + return canRead; + } + + public boolean isDirectory() { + return isDirectory; + } + + public void setDirectory(boolean directory) { + isDirectory = directory; + } + + public String toString() { + return name; + } + + /** + * 从File产生 FileDirectoryNode. + */ + public static FileDirectoryNode createFileDirectoryNode(File file) { + FileDirectoryNode fileDirectoryNode = new FileDirectoryNode(); + + fileDirectoryNode.setName(file.getName()); + fileDirectoryNode.setDirectory(file.isDirectory()); + fileDirectoryNode.setCanRead(file.canRead()); + + return fileDirectoryNode; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/FileNodeComparator.java b/designer_base/src/com/fr/design/gui/itree/filetree/FileNodeComparator.java new file mode 100644 index 0000000000..b71afa183b --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/FileNodeComparator.java @@ -0,0 +1,78 @@ +package com.fr.design.gui.itree.filetree; + +import java.util.Comparator; + +import com.fr.dav.LocalEnv; +import com.fr.file.filetree.FileNode; + +/** + * FileTreeNode compare... + * Directory is in the first. and normal file the in the last. + */ +public class FileNodeComparator implements Comparator { + // 正序还是倒序 + private boolean isReverse = false; + + public FileNodeComparator() { + this(false); + } + + public FileNodeComparator(boolean reverse) { + this.isReverse = reverse; + } + + /** + * This method should return > 0 if v1 is greater than v2, 0 if + * v1 is equal to v2, or < 0 if v1 is less than v2. + * It must handle null values for the comparison values. + * + * @param v1 comparison value. + * @param v2 comparison value. + * @return < 0, 0, or > 0 for v1v2. + */ + public int compare(FileNode nameNode1, FileNode nameNode2) { + int returnVal; + if (nameNode1.isDirectory()) { + if (nameNode2.isDirectory()) { + returnVal = nameNode1.getName().toLowerCase().compareTo(nameNode2.getName().toLowerCase()); + } else { + returnVal = -1; + } + } else { + if (nameNode2.isDirectory()) { + returnVal = 1; + } else { + returnVal=groupByFileType(nameNode1, nameNode2, 0); + } + } + if (isReverse) { + returnVal = 0 - returnVal; + } + return returnVal; + } + + /** + * 一个简单的递归判断算法 + * @param nameNode1 + * @param nameNode2 + * @param i + * @return + */ + private int groupByFileType(FileNode nameNode1, FileNode nameNode2, + int i) { + if(i< LocalEnv.FILE_TYPE.length){ + if(nameNode1.isFileType(LocalEnv.FILE_TYPE[i])) + if(nameNode2.isFileType(LocalEnv.FILE_TYPE[i])) + return nameNode1.getName().toLowerCase().compareTo(nameNode2.getName().toLowerCase()); + else + return-1; + else + if(nameNode2.isFileType(LocalEnv.FILE_TYPE[i])) + return 1; + else{ + return groupByFileType(nameNode1, nameNode2, i+1); + } + }else + return -1; + } + } \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/FileTreeIcon.java b/designer_base/src/com/fr/design/gui/itree/filetree/FileTreeIcon.java new file mode 100644 index 0000000000..799ba0d389 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/FileTreeIcon.java @@ -0,0 +1,274 @@ +package com.fr.design.gui.itree.filetree; + +import java.io.File; + +import javax.swing.Icon; +import javax.swing.UIManager; +import javax.swing.filechooser.FileSystemView; + +import com.fr.base.BaseUtils; +import com.fr.base.FRContext; +import com.fr.dav.LocalEnv; +import com.fr.design.icon.LockIcon; +import com.fr.file.filetree.FileNode; +import com.fr.stable.StableUtils; + +public class FileTreeIcon { + private FileTreeIcon() {} + + public static final Icon BLANK_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/blank.gif"); + + public static final Icon FOLDER_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/folder.png"); + public static final Icon FILE_IMAGE_ICON = UIManager.getIcon("FileView.fileIcon"); + + public static final Icon JAVA_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/javaFile.gif"); + public static final Icon CLASS_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/classFile.gif"); + public static final Icon JSP_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/jspFile.gif"); + public static final Icon JS_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/jsFile.gif"); + public static final Icon XML_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/xmlFile.gif"); + public static final Icon HTML_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/htmlFile.gif"); + public static final Icon JAR_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/jarFile.gif"); + public static final Icon GIF_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/gifFile.gif"); + public static final Icon JPG_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/jpgFile.gif"); + public static final Icon BMP_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/bmpFile.gif"); + public static final Icon CPT_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/cptFile.png"); + public static final Icon FRM_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/frm.png"); + public static final Icon CHT_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/cht.png"); + + public static final LockIcon FOLDER_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/fold.png")); + public static final LockIcon FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/file.gif")); + + public static final LockIcon JAVA_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/javaFile.gif")); + public static final LockIcon CLASS_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/classFile.gif")); + public static final LockIcon JSP_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/jspFile.gif")); + public static final LockIcon ANT_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/antFile.gif")); + public static final LockIcon JS_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/jsFile.gif")); + public static final LockIcon XML_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/xmlFile.gif")); + public static final LockIcon HTML_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/htmlFile.gif")); + public static final LockIcon JAR_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/jarFile.gif")); + public static final LockIcon GIF_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/gifFile.gif")); + public static final LockIcon JPG_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/jpgFile.gif")); + public static final LockIcon BMP_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/bmpFile.gif")); + public static final LockIcon CPT_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/base/images/oem/cptlocked.png")); + public static final LockIcon FRM_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/frmlocked.png")); + public static final LockIcon CHT_FILE_LOCK_ICON = + new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/frmlocked.png")); + /** + * file types + */ + public static final String[] DEFAULT_ANT_FILE_TYPES = new String[]{"build.xml"}; + public static final String[] DEFAULT_JAVA_FILE_TYPES = new String[]{".java"}; + public static final String[] DEFAULT_CLASS_FILE_TYPES = new String[]{".class"}; + public static final String[] DEFAULT_JSP_FILE_TYPES = new String[]{".jsp", ".jspf", ".jsf"}; + public static final String[] DEFAULT_HTML_FILE_TYPES = new String[]{".html", ".htm"}; + public static final String[] DEFAULT_JS_FILE_TYPES = new String[]{".js"}; + public static final String[] DEFAULT_XML_FILE_TYPES = new String[]{".xml", ".xsl"}; + public static final String[] DEFAULT_TEXT_FILE_TYPES = new String[]{ + ".properties", ".txt", ".cmd", ".bat", ".sh"}; + //file types. + public final static int JAVA_FILE = 0; //.java + public final static int JSP_FILE = 1; //.jsp, .jspf, .jsf + public final static int HTML_FILE = 2; //.html, .htm + public final static int JS_FILE = 3; //.js + public final static int XML_FILE = 4; //.xml, .xsl, .dtd, .tld + public final static int TEXT_FILE = 5; //.properties, .txt, cmd, bat, sh + public final static int CLASS_FILE = 6; //.class + public final static int ZIP_FILE = 7; //.jar, .zip, .war, .ear + public final static int GIF_FILE = 8; //.gif + public final static int JPG_FILE = 9; //.jpg + public final static int BMP_FILE = 10; //.bmp + public final static int CPT_FILE = 11; //.cpt + public final static int FRM_FILE = 12; //.form .frm + public final static int CHT_FILE = 13; //.chart .cht + + public static Icon getIcon(File file) { + return FileTreeIcon.getIcon(file, false); + } + + public static Icon getIcon(File file, boolean isLocked) { + if (file.isDirectory()) { + if (isLocked) { + return FOLDER_LOCK_ICON; + } else { + return FOLDER_IMAGE_ICON; + } + } + + return FileTreeIcon.getIcon(FileTreeIcon.getFileType(file.getName()), isLocked); + } + + public static Icon getIcon(FileNode node) { + return getIcon(node, node.getLock() != null); + } + + public static Icon getIcon(FileNode node, boolean isShowLock) { + String path = StableUtils.pathJoin(new String[]{FRContext.getCurrentEnv().getPath(), node.getEnvPath()}); + if (FRContext.getCurrentEnv() instanceof LocalEnv) { + File ff = new File(path); + if (ff.exists()) { + if(node.isDirectory()){ + return FileTreeIcon.FOLDER_IMAGE_ICON; + } + return FileSystemView.getFileSystemView().getSystemIcon(new File(path)); + } + } + if(node.isDirectory()) { + return FileTreeIcon.FOLDER_IMAGE_ICON; + } else { + return FileTreeIcon.getIcon(FileTreeIcon.getFileType(node.getName()), isShowLock); + } + } + + private static Icon getIcon(int fileType, boolean isLocked) { + if (fileType == JAVA_FILE) { + if (isLocked) { + return FileTreeIcon.JAVA_FILE_LOCK_ICON; + } else { + return FileTreeIcon.JAVA_FILE_IMAGE_ICON; + } + } else if (fileType == CLASS_FILE) { + if (isLocked) { + return FileTreeIcon.CLASS_FILE_LOCK_ICON; + } else { + return FileTreeIcon.CLASS_FILE_IMAGE_ICON; + } + } else if (fileType == JSP_FILE) { + if (isLocked) { + return FileTreeIcon.JSP_FILE_LOCK_ICON; + } else { + return FileTreeIcon.JSP_FILE_IMAGE_ICON; + } + } else if (fileType == XML_FILE) { + if (isLocked) { + return FileTreeIcon.XML_FILE_LOCK_ICON; + } else { + return FileTreeIcon.XML_FILE_IMAGE_ICON; + } + } else if (fileType == HTML_FILE) { + if (isLocked) { + return FileTreeIcon.HTML_FILE_LOCK_ICON; + } else { + return FileTreeIcon.HTML_FILE_IMAGE_ICON; + } + } else if (fileType == JS_FILE) { + if (isLocked) { + return FileTreeIcon.JS_FILE_LOCK_ICON; + } else { + return FileTreeIcon.JS_FILE_IMAGE_ICON; + } + } else if (fileType == ZIP_FILE) { + if (isLocked) { + return FileTreeIcon.JAR_FILE_LOCK_ICON; + } else { + return FileTreeIcon.JAR_FILE_IMAGE_ICON; + } + } else if (fileType == GIF_FILE) { //gif + if (isLocked) { + return FileTreeIcon.GIF_FILE_LOCK_ICON; + } else { + return FileTreeIcon.GIF_FILE_IMAGE_ICON; + } + } else if (fileType == JPG_FILE) { //jpg + if (isLocked) { + return FileTreeIcon.JPG_FILE_LOCK_ICON; + } else { + return FileTreeIcon.JPG_FILE_IMAGE_ICON; + } + } else if (fileType == BMP_FILE) { //bmp + if (isLocked) { + return FileTreeIcon.BMP_FILE_LOCK_ICON; + } else { + return FileTreeIcon.BMP_FILE_IMAGE_ICON; + } + } else if (fileType == CPT_FILE) { //cpt + if (isLocked) { + return FileTreeIcon.CPT_FILE_LOCK_ICON; + } else { + return FileTreeIcon.CPT_FILE_IMAGE_ICON; + } + } else if (fileType == FRM_FILE) { //form frm + if (isLocked) { + return FileTreeIcon.FRM_FILE_LOCK_ICON; + } else { + return FileTreeIcon.FRM_FILE_IMAGE_ICON; + } + } else if (fileType == CHT_FILE) { //chart cht + if (isLocked) { + return FileTreeIcon.CHT_FILE_LOCK_ICON; + } else { + return FileTreeIcon.CHT_FILE_IMAGE_ICON; + } + } else { + if (isLocked) { + return FileTreeIcon.FILE_LOCK_ICON; + } else { + return FileTreeIcon.FILE_IMAGE_ICON; + } + } + } + + /** + * Gets file type according to file name. + */ + public static int getFileType(String fileName) { + fileName = fileName.toLowerCase(); //to lower case in the first. + for (int i = 0; i < DEFAULT_JAVA_FILE_TYPES.length; i++) { + if (fileName.endsWith(DEFAULT_JAVA_FILE_TYPES[i])) { + return JAVA_FILE; + } + } + for (int i = 0; i < DEFAULT_JSP_FILE_TYPES.length; i++) { + if (fileName.endsWith(DEFAULT_JSP_FILE_TYPES[i])) { + return JSP_FILE; + } + } + for (int i = 0; i < DEFAULT_HTML_FILE_TYPES.length; i++) { + if (fileName.endsWith(DEFAULT_HTML_FILE_TYPES[i])) { + return HTML_FILE; + } + } + for (int i = 0; i < DEFAULT_XML_FILE_TYPES.length; i++) { + if (fileName.endsWith(DEFAULT_XML_FILE_TYPES[i])) { + return XML_FILE; + } + } + if (fileName.endsWith(".class")) { + return CLASS_FILE; + } else if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) { + return ZIP_FILE; + } else if( fileName.endsWith(".ear") || fileName.endsWith(".war")){ + return ZIP_FILE; + }else if (fileName.endsWith(".gif")) { + return GIF_FILE; + } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpe")) { + return JPG_FILE; + } else if( fileName.endsWith(".jpeg")){ + return JPG_FILE; + }else if (fileName.endsWith(".bmp")) { + return BMP_FILE; + } else if (fileName.endsWith(".cpt")) { + return CPT_FILE; + } else if (fileName.endsWith(".frm") || fileName.endsWith(".form")){ + return FRM_FILE; + } else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")){ + return CHT_FILE; + } else { + return TEXT_FILE; + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/JFileTree.java b/designer_base/src/com/fr/design/gui/itree/filetree/JFileTree.java new file mode 100644 index 0000000000..ceec79d7bf --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/JFileTree.java @@ -0,0 +1,324 @@ +package com.fr.design.gui.itree.filetree; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Stack; + +import javax.swing.Icon; +import javax.swing.JTree; +import javax.swing.filechooser.FileSystemView; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import com.fr.base.BaseUtils; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.ArrayUtils; +import com.fr.stable.project.ProjectConstants; + + +/** + * File Tree. + */ +public class JFileTree extends AbstractFileTree { + protected FileFilter fileFilter ; + + public JFileTree() { + this(null); + } + + public JFileTree(FileFilter filter) { + this.init(filter); + } + + private void init(FileFilter filter) { + this.fileFilter = filter; + + DefaultTreeModel m_model = new DefaultTreeModel(new DefaultMutableTreeNode(Inter.getLocText("My_Computer"))); + this.setModel(m_model); + + this.putClientProperty("JTree.lineStyle", "Angled"); + + this.addTreeExpansionListener(this); + this.setCellRenderer(fileTreeCellRenderer); + + this.setRootVisible(false); + this.setShowsRootHandles(true); + this.setEditable(false); + } + + public void setRootFile(File rootFile) { + setRootFiles(new File[] { rootFile }); + } + + public void setRootFiles(File[] rootFiles) { + if (ArrayUtils.getLength(rootFiles) == 0) { + return; + } + + DefaultTreeModel m_model = (DefaultTreeModel) this.getModel(); + DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) m_model.getRoot(); + rootTreeNode.removeAllChildren(); + + for (int k = 0; k < rootFiles.length; k++) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(new RootFile(rootFiles[k])); + rootTreeNode.add(node); + + if (rootFiles[k].isDirectory()) { + node.add(new DefaultMutableTreeNode(Boolean.TRUE)); + } + } + // richer:不是LocalEnv根本就不会运行到这儿 + m_model.reload(rootTreeNode); + + if (rootFiles.length == 1) { + File expandFile = rootFiles[0]; + this.selectFile(expandFile); + } + } + + public FileFilter getFileFilter() { + return fileFilter; + } + + public void setFileFilter(FileFilter fileFilter) { + this.fileFilter = fileFilter; + } + + public File getSelectedFile() { + TreePath selectedTreePath = this.getSelectionPath(); + if(selectedTreePath == null) { + return null; + } + + DefaultMutableTreeNode currentTreeNode = this.getMutableTreeNode(selectedTreePath); + StringBuffer fBuf = new StringBuffer(); + while (true) { + // 如果已经到了根节点,直接退出. + if (currentTreeNode == null) { + break; + } + + Object object = currentTreeNode.getUserObject(); + if (object instanceof RootFile) { + // 当前文件. + RootFile rootFileNode = (RootFile) object; + return new File(rootFileNode.getFile() + fBuf.toString()); + } + + FileDirectoryNode nameNode = (FileDirectoryNode) object; + fBuf.insert(0, nameNode.getName()); + fBuf.insert(0, "/"); + + // 逐层返回 + currentTreeNode = (DefaultMutableTreeNode) currentTreeNode.getParent(); + } + + return null; + } + + /** + * 通过文件夹寻找展开路径 + * @param currentFile 当前文件 + */ + public void selectFile(File currentFile) { + if (currentFile == null) { + return; + } + DefaultTreeModel m_model = (DefaultTreeModel) this.getModel(); + DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) m_model.getRoot(); + int rootChildCount = rootTreeNode.getChildCount(); + for (int i = 0; i < rootChildCount; i++) { + DefaultMutableTreeNode rootChildTreeNode = (DefaultMutableTreeNode) rootTreeNode.getChildAt(i); + RootFile rootLocalFile = (RootFile) rootChildTreeNode.getUserObject(); + File rootFile = rootLocalFile.getFile(); + // 是父子关系,开始找孩子. + if (AbstractFileTree.isParentFile(rootFile, currentFile)) { + Stack nameStack = new Stack(); // 将所有的名字加入Stack. + while (true) { + if (ComparatorUtils.equals(rootFile, currentFile)) { + break; + } + nameStack.push(currentFile.getName()); + currentFile = currentFile.getParentFile(); + if (currentFile == null) { + break; + } + } + DefaultMutableTreeNode curChildTreeNode = rootChildTreeNode; + while (!nameStack.isEmpty()) { + String name = (String) nameStack.pop(); + this.expandTreeNode(curChildTreeNode); + for (int j = 0; j < curChildTreeNode.getChildCount(); j++) { + DefaultMutableTreeNode tmpChildTreeNode = + (DefaultMutableTreeNode) curChildTreeNode.getChildAt(j); + FileDirectoryNode tmpNameNode = (FileDirectoryNode) tmpChildTreeNode.getUserObject(); + if (ComparatorUtils.equals(name, tmpNameNode.getName())) { + curChildTreeNode = tmpChildTreeNode; + // 选择当前的节点. + this.setSelectionPath(new TreePath(m_model.getPathToRoot(curChildTreeNode))); + break; + } + } + } + break; + } + } + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath != null) { + this.scrollPathToVisible(selectedTreePath); + } + } + + /** + * 列出当前所有的File + * @param currentTreeNode 当前文件节点 + * @return 当前节点下的所有File + */ + public FileDirectoryNode[] listFileNodes(DefaultMutableTreeNode currentTreeNode) { + StringBuffer fBuf = new StringBuffer(); + while (true) { + // 如果已经到了根节点,直接退出. + if (currentTreeNode == null) { + break; + } + Object object = currentTreeNode.getUserObject(); + if (object instanceof RootFile) { + RootFile rootFileNode = (RootFile) object; + // 当前文件. (rootFileNode + fBuf.toString = Path  local地址) + File currentFile = new File(rootFileNode.getFile() + fBuf.toString()); + // 列出当前文件的所有子文件,要判断下是否是系统保护的文件 能否打开. 打不开的话显示为null + File[] files = currentFile.listFiles(); + // 如果文件列表为null 或者为File[0] = []返回null + if (files == null ) { + return new FileDirectoryNode[0]; + } + List fileNodeList = new ArrayList(); + for (int k = 0; k < files.length; k++) { + File tmpFile = files[k]; + // 文件属性为隐藏的话 不放入列表 + if (tmpFile.isHidden()) { + continue; + } + // 过滤只显示文件夹 并进行 名字简化 + if (fileFilter.accept(tmpFile)) { + // newNode 传递 isDirectory属性 并且只显示文件夹名字 + FileDirectoryNode newNode = FileDirectoryNode.createFileDirectoryNode(tmpFile); + fileNodeList.add(newNode); + } + } + // 节点加入列表 + FileDirectoryNode[] fileNodes = new FileDirectoryNode[fileNodeList.size()]; + fileNodeList.toArray(fileNodes); + // 对文件夹进行排序 + Arrays.sort(fileNodes, new FileNodeComparator()); + return fileNodes; + } + // 名字进行逐层反序的回加. 例: Doload ==> C:\java\Doload ,返回到文件夹的path,因为有可能是String. 所以加上instanceof + if (object instanceof FileDirectoryNode) { + FileDirectoryNode nameNode = (FileDirectoryNode)object; + fBuf.insert(0, nameNode.getName()); + fBuf.insert(0, "/"); + } + // 逐层返回 + currentTreeNode = (DefaultMutableTreeNode) currentTreeNode.getParent(); + } + return new FileDirectoryNode[0]; + } + + /** + * cellRenderer: tree中显示文件的类型图标 + */ + private DefaultTreeCellRenderer fileTreeCellRenderer = new DefaultTreeCellRenderer() { + + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean selected, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, + leaf, row, hasFocus); + + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; + StringBuffer fBuf = new StringBuffer(); + while(true) { + if (treeNode == null) { + break; + } + Object userObj = treeNode.getUserObject(); + if (userObj instanceof RootFile) { + RootFile rootFileNode = (RootFile) userObj; + // 当前文件的全部路径. (rootFileNode + fBuf.toString = Path  local地址) + File currentFile = new File(rootFileNode.getFile() + fBuf.toString()); + FileSystemView view = FileSystemView.getFileSystemView(); + // File的全部路径. + // 得到本地tree图标 + Icon tmpIcon = view.getSystemIcon(currentFile); + if (currentFile.isDirectory() && fBuf.length() > 0) { + tmpIcon=BaseUtils.readIcon("/com/fr/design/images/gui/folder.png"); + } + this.setIcon(tmpIcon); + this.setName(null); + Font oldFont = this.getFont(); + if(ComparatorUtils.equals(currentFile.getName(), ProjectConstants.WEBINF_NAME)){ + this.setForeground(Color.blue); + this.setFont(new Font(oldFont.getName(),1,oldFont.getSize())); + }else{ + this.setFont(new Font(oldFont.getName(),0,oldFont.getSize())); + } + } + // 名字进行逐层反序的回加. 例: Doload ==> C:\java\Doload + if (userObj instanceof FileDirectoryNode ) { + FileDirectoryNode nameNode = (FileDirectoryNode)userObj; + fBuf.insert(0, nameNode.getName()); + fBuf.insert(0, "/"); + } + // 逐层往上 倒退返回 + treeNode = (DefaultMutableTreeNode) treeNode.getParent(); + } + return this; + } + }; + + /** + * 对文件夹进行排序 先文件夹 然后各种类型文件 + * @author kunsnat + */ + public class FileNodeComparator implements Comparator { + /** + * This method should return > 0 if v1 is greater than v2, 0 if + * v1 is equal to v2, or < 0 if v1 is less than v2. + * It must handle null values for the comparison values. + * 如上所述 + * + * @param v1 comparison value.值1 + * @param v2 comparison value.值2 + * @return < 0, 0, or > 0 for v1v2 .值1大于值2返回大于0,相等返回0,小于和大于相反 + */ + public int compare(Object v1, Object v2) { + FileDirectoryNode nameNode1 = (FileDirectoryNode) v1; + FileDirectoryNode nameNode2 = (FileDirectoryNode) v2; + + if (nameNode1.isDirectory()) { + if (nameNode2.isDirectory()) { + return nameNode1.getName().toLowerCase().compareTo(nameNode2.getName().toLowerCase()); + } else { + return -1; + } + } else { + if (nameNode2.isDirectory()) { + return 1; + } else { + return nameNode1.getName().toLowerCase().compareTo(nameNode2.getName().toLowerCase()); + } + } + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/ReportletPane.java b/designer_base/src/com/fr/design/gui/itree/filetree/ReportletPane.java new file mode 100644 index 0000000000..f1b38009da --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/ReportletPane.java @@ -0,0 +1,136 @@ +package com.fr.design.gui.itree.filetree; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +import com.fr.base.Env; +import com.fr.base.FRContext; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.itextarea.UITextArea; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.file.filetree.IOFileNodeFilter; +import com.fr.general.Inter; +import com.fr.design.utils.gui.GUICoreUtils; + +public class ReportletPane extends BasicPane { + private TemplateFileTree templateReportletTree; + private JScrollPane t_panel; + private ClassFileTree classReportletTree; + private JScrollPane c_panel; + + private UIButton switchButton; + private CardLayout card; + private JPanel cardPane; + + public ReportletPane() { + this.setLayout(FRGUIPaneFactory.createM_BorderLayout()); + // Description + UITextArea textPane = new UITextArea(); + this.add(textPane, BorderLayout.NORTH); + textPane.setEditable(false); + textPane.setLineWrap(true); + + textPane.setFont(FRContext.getDefaultValues().getFRFont().deriveFont(Font.BOLD, 12)); + textPane.setText(Inter.getLocText("Schedule-The_selected_file_must_be_end_with_filter")); + + JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + this.add(centerPane, BorderLayout.CENTER); + + switchButton = new UIButton("switch"); + centerPane.add(GUICoreUtils.createBorderPane(switchButton, BorderLayout.WEST), BorderLayout.NORTH); + switchButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + switchCardPane(t_panel.isVisible()); + } + }); + + cardPane = FRGUIPaneFactory.createCardLayout_S_Pane(); + centerPane.add(cardPane, BorderLayout.CENTER); + cardPane.setLayout(card = new CardLayout()); + templateReportletTree = new TemplateFileTree(); + IOFileNodeFilter filter = new IOFileNodeFilter(new String[]{".cpt", ".class",".frm",".form"}); + templateReportletTree.setFileNodeFilter(filter); + cardPane.add(t_panel = new JScrollPane(templateReportletTree), "TEMPLATE"); + classReportletTree = new ClassFileTree(); + cardPane.add(c_panel = new JScrollPane(classReportletTree), "CLASS"); + + this.refreshEnv(FRContext.getCurrentEnv()); + } + + /* + * 切换CardPane + */ + private void switchCardPane(boolean switch2Class) { + if (switch2Class) { + card.show(cardPane, "CLASS"); + switchButton.setText(Inter.getLocText("Utils-Switch_To_Template_Reportlet")); + } else { + card.show(cardPane, "TEMPLATE"); + switchButton.setText(Inter.getLocText("Utils-Switch_To_Class_Reportlet")); + } + } + + /** + * 检查是否符合规范 + * + * @throws Exception 抛错 + */ + public void checkValid() throws Exception { + String path = this.getSelectedReportletPath(); + if (path == null) { + throw new Exception(Inter.getLocText("Function-The_selected_file_cannot_be_null")); + } + } + + + /** + * 刷新Env + * @param env 环境 + */ + public void refreshEnv(Env env) { + this.templateReportletTree.refreshEnv(env); + this.classReportletTree.refreshEnv(env); + } + + @Override + protected String title4PopupWindow() { + return Inter.getLocText("Reportlet"); + } + + /* + * 返回选中的Reportlet的路径 + */ + public String getSelectedReportletPath() { + if (t_panel.isVisible()) { + return templateReportletTree.getSelectedTemplatePath(); + } else if (c_panel.isVisible()) { + return classReportletTree.getSelectedClassPath(); + } + + return null; + } + + /* + * 选中某Reportlet + */ + public void setSelectedReportletPath(String reportletPath) { + if (reportletPath == null) { + return; + } + + if (reportletPath.endsWith(".class")) { + switchCardPane(true); + classReportletTree.setSelectedClassPath(reportletPath); + } else { + switchCardPane(false); + templateReportletTree.setSelectedTemplatePath(reportletPath); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/RootFile.java b/designer_base/src/com/fr/design/gui/itree/filetree/RootFile.java new file mode 100644 index 0000000000..0d80a995a0 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/RootFile.java @@ -0,0 +1,28 @@ +package com.fr.design.gui.itree.filetree; + +import java.io.File; +/** + * 用于判断是否为根目录 + * 例: C:\ + * @author kunsnat + * + */ +public class RootFile { + private File file; + + public RootFile(File file) { + this.file = file; + } + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + + public String toString() { + return file.getAbsolutePath(); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/filetree/TemplateFileTree.java b/designer_base/src/com/fr/design/gui/itree/filetree/TemplateFileTree.java new file mode 100644 index 0000000000..a66fe522af --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/filetree/TemplateFileTree.java @@ -0,0 +1,69 @@ +package com.fr.design.gui.itree.filetree; + +import java.util.ArrayList; +import java.util.List; + +import javax.swing.tree.TreePath; + +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.file.filetree.FileNode; +import com.fr.stable.ArrayUtils; +import com.fr.stable.project.ProjectConstants; + +/* + * 显示Env下的reportlets目录下面的所有cpt文件 + */ +public class TemplateFileTree extends EnvFileTree { + + + public TemplateFileTree() { + super(ProjectConstants.REPORTLETS_NAME, null, null); + } + + /* + * 选中reportPath + */ + public void setSelectedTemplatePath(String templatePath) { + this.selectPath(templatePath); + } + + /** + * 返回选中的Template的路径 + */ + public String getSelectedTemplatePath() { + FileNode fn = this.getSelectedFileNode(); + if (fn != null && !fn.isDirectory()) { + String envPath = fn.getEnvPath(); + + if (envPath.startsWith(ProjectConstants.REPORTLETS_NAME)) { + return envPath.substring(ProjectConstants.REPORTLETS_NAME.length()); + } + } + + return null; + } + + public String[] getSelectedTemplatePaths(){ + TreePath[] selectedTreePaths = this.getSelectionPaths(); + if (ArrayUtils.isEmpty(selectedTreePaths)) { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + List selectedPathList = new ArrayList(); + for(TreePath treepath : selectedTreePaths){ + ExpandMutableTreeNode currentTreeNode = (ExpandMutableTreeNode) treepath.getLastPathComponent(); + Object userObject = currentTreeNode.getUserObject(); + if (userObject instanceof FileNode) { + FileNode fn = (FileNode) userObject; + if (!fn.isDirectory()) { + String envPath = fn.getEnvPath(); + if (envPath.startsWith(ProjectConstants.REPORTLETS_NAME)) { + selectedPathList.add(envPath.substring(ProjectConstants.REPORTLETS_NAME.length())); + } + } + } + } + + + return selectedPathList.toArray(new String[0]); + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java new file mode 100644 index 0000000000..fea785380c --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java @@ -0,0 +1,78 @@ +package com.fr.design.gui.itree.refreshabletree; + +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; + +import com.fr.design.utils.gui.GUICoreUtils; + +/** + * Enhanced, expand state and get treepath from node. + */ +public class ExpandMutableTreeNode extends DefaultMutableTreeNode { + private boolean isExpanded = false; //the expend state + + //默认显示:“正在加载”,如需要显示tree,则传入相应userobject + public ExpandMutableTreeNode() { + this(RefreshableJTree.PENDING); + } + + public ExpandMutableTreeNode(Object userObject) { + this(userObject, false); + } + + public ExpandMutableTreeNode(Object userObject, boolean isExpanded) { + super(userObject); + this.setExpanded(isExpanded); + } + public boolean isExpanded() { + return this.isExpanded; + } + + public void setExpanded(boolean isExpanded) { + this.isExpanded = isExpanded; + } + + /** + * 展开所有Expanded为true的TreeNode + */ + public void expandCurrentTreeNode(JTree tree) { + if (this.isExpanded) { + tree.expandPath(GUICoreUtils.getTreePath(this)); + this.setExpanded(true); + + this.expandSubTreeNodes(tree); + } + } + + /** + * expand all children of TreeNode... + * the Tree, that node at. + */ + private void expandSubTreeNodes(JTree tree) { + if (!this.isExpanded()) { + return; + } + + //peter:扩展. + tree.expandPath(GUICoreUtils.getTreePath(this)); + this.setExpanded(true); + + int childCount = this.getChildCount(); + for (int i = 0; i < childCount; i++) { + ExpandMutableTreeNode childNode = (ExpandMutableTreeNode) this.getChildAt(i); + + if (childNode.isExpanded()) { + tree.expandPath(GUICoreUtils.getTreePath(childNode)); + childNode.setExpanded(true); + + childNode.expandSubTreeNodes(tree); + } + } + } + + public void addChildTreeNodes(ExpandMutableTreeNode[] newChildNodes) { + for (int i = 0; i < newChildNodes.length; i ++) { + this.add(newChildNodes[i]); + } + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java new file mode 100644 index 0000000000..fdf6b56ade --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java @@ -0,0 +1,281 @@ +package com.fr.design.gui.itree.refreshabletree; + +import javax.swing.*; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeWillExpandListener; +import javax.swing.tree.*; + +import com.fr.general.NameObject; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.itooltip.UIToolTip; +import com.fr.general.ComparatorUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import java.awt.*; +import java.awt.event.MouseEvent; + +public abstract class RefreshableJTree extends JTree { + private static final int WIDTH_BETWEEN_NODES = 20; //tree父子节点之间最左侧横向像素的差 + private Icon icon; + + public static final Object PENDING = new Object() { + + @Override + public String toString() { + return Inter.getLocText("Loading") + "..."; + } + }; + + public RefreshableJTree() { + this(null); + } + + public RefreshableJTree(Object rootObj) { + super(new DefaultTreeModel(new ExpandMutableTreeNode(rootObj))); + DefaultTreeModel model = (DefaultTreeModel) getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) model.getRoot(); + root.setExpanded(true); + this.setRootVisible(false); + this.setBackground(UIConstants.NORMAL_BACKGROUND); + this.addTreeExpansionListener(expansion); + this.addTreeWillExpandListener(willExpand); + } + + private TreeExpansionListener expansion = new TreeExpansionListener() { + + @Override + public void treeCollapsed(TreeExpansionEvent event) { + TreePath treePath = event.getPath(); + if (treePath == null) { + return; + } + + ExpandMutableTreeNode treeNode = ((ExpandMutableTreeNode) treePath.getLastPathComponent()); + treeNode.setExpanded(false); + } + + @Override + public void treeExpanded(TreeExpansionEvent event) { + TreePath treePath = event.getPath(); + if (treePath == null) { + return; + } + + ExpandMutableTreeNode treeNode = ((ExpandMutableTreeNode) treePath.getLastPathComponent()); + treeNode.setExpanded(true); + } + }; + private TreeWillExpandListener willExpand = new TreeWillExpandListener() { + + @Override + public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { + } + + @Override + public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { + TreePath treePath = event.getPath(); + if (treePath == null) { + return; + } + + final ExpandMutableTreeNode treeNode = ((ExpandMutableTreeNode) treePath.getLastPathComponent()); + + if (treeNode.getChildCount() == 1 && ((ExpandMutableTreeNode) treeNode.getFirstChild()).getUserObject() == PENDING) { + //如果空文件夹是只有一个默认增加的正在加载的子节点,则不显示正在加载,就是空就行了 + new SwingWorker() { + + @Override + protected Long doInBackground() throws Exception { + long startTime = System.currentTimeMillis(); + ExpandMutableTreeNode[] nodes = RefreshableJTree.this.loadChildTreeNodes(treeNode); + for (int i = 0; i < nodes.length; i++) { + treeNode.add(nodes[i]); + } + DefaultTreeModel treeModel = (DefaultTreeModel) RefreshableJTree.this.getModel(); + // 主要耗时是用在了treeUI的渲染上了,所以把这个放到工作线程里面 + if (treeNode.getChildCount() >= 1 && ((ExpandMutableTreeNode) treeNode.getFirstChild()).getUserObject() == PENDING) { + treeNode.remove(0); + } + treeModel.nodeStructureChanged(treeNode); + long usedTime = System.currentTimeMillis() - startTime; + return usedTime; + } + + @Override + protected void done() { + RefreshableJTree.this.updateUI(); + // 恢复Tree的可用性 + RefreshableJTree.this.setEnabled(true); + } + + }.execute(); + } + } + }; + + /** + * @return + */ + public boolean isTemplateShowing() { + return ((ExpandMutableTreeNode) this.getModel().getRoot()).getChildCount() == 0 ? false : true; + } + + /* + * 刷新 + */ + public void refresh() { + refresh((ExpandMutableTreeNode) this.getModel().getRoot(), StringUtils.EMPTY); + } + + public void refreshChildByName(String childName) { + refresh((ExpandMutableTreeNode) this.getModel().getRoot(), childName); + } + + /* + * 刷新expandRoot节点下所有已打开的节点的UserObject,并打开isExpanded为true的TreeNode + */ + private void refresh(ExpandMutableTreeNode expandRoot, String childName) { + if (expandRoot == null) { + return; + } + refreshTreeNode(expandRoot, childName); + + // model.reload, then do expand treenode that isExpanded is true + ((DefaultTreeModel) this.getModel()).reload(expandRoot); + + // 展开所有isExpanded为true的TreeNode + expandRoot.expandCurrentTreeNode(this); + } + + /* + * 刷新eTreeNode下面所有的已完成过取数的非叶子节点的子叶内容UserObject + */ + protected void refreshTreeNode(ExpandMutableTreeNode eTreeNode, String childName) { + // 如果eTreeNode是未取数状态,不用expand + if (interceptRefresh(eTreeNode)) { + return; + } + + // 刷新当前eTreeNode下面的子节点的UserObject的数组 + ExpandMutableTreeNode[] new_nodes = loadChildTreeNodes(eTreeNode); + + /* + * 保存下当前eTreeNode下的ChildTreeNode于childTreeNodeList 移除所有ChildTreeNode + * 根据childUserObjects与childTreeNodeList的比对,重新构建eTreeNode + */ + java.util.List childTreeNodeList = new java.util.ArrayList(); + for (int i = 0, len = eTreeNode.getChildCount(); i < len; i++) { + if (eTreeNode.getChildAt(i) instanceof ExpandMutableTreeNode) { + childTreeNodeList.add((ExpandMutableTreeNode) eTreeNode.getChildAt(i)); + } else { + childTreeNodeList.add((DefaultMutableTreeNode) eTreeNode.getChildAt(i)); + } + } + + eTreeNode.removeAllChildren(); + + for (int ci = 0; ci < new_nodes.length; ci++) { + Object cUserObject = new_nodes[ci].getUserObject(); + + for (int ni = 0, nlen = childTreeNodeList.size(); ni < nlen; ni++) { + ExpandMutableTreeNode cTreeNode = (ExpandMutableTreeNode) childTreeNodeList.get(ni); + if (ComparatorUtils.equals(cTreeNode.getUserObject(), cUserObject)) { + new_nodes[ci].setExpanded(cTreeNode.isExpanded()); + break; + } + } + + eTreeNode.add(new_nodes[ci]); + } + } + + /* + * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh + */ + protected abstract boolean interceptRefresh(ExpandMutableTreeNode eTreeNode); + + /* + * 得到treeNode的子节点ExpandMutableTreeNode的数组 + */ + protected abstract ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode); + + public NameObject getSelectedNameObject() { + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath == null) { + return null; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + + selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + return null; + } + + public String getToolTipText(MouseEvent event) { + String tip = null; + icon = new ImageIcon(); + + if (event != null) { + Point p = event.getPoint(); + int selRow = getRowForLocation(p.x, p.y); + TreeCellRenderer r = getCellRenderer(); + + if (selRow != -1 && r != null) { + int i = 0; //tree节点的级数 + TreePath path = getPathForRow(selRow); + Object lastPath = path.getLastPathComponent(); + if (lastPath instanceof TreeNode) { + TreeNode treeNode = (TreeNode) lastPath; + while (treeNode.getParent() instanceof TreeNode) { + i++; + treeNode = treeNode.getParent(); + } + } + Component rComponent = r.getTreeCellRendererComponent + (this, lastPath, isRowSelected(selRow), + isExpanded(selRow), getModel().isLeaf(lastPath), selRow, + true); + + if (rComponent instanceof JComponent && rComponent.getPreferredSize().getWidth() + i * WIDTH_BETWEEN_NODES > getVisibleRect().getWidth()) { + tip = ((DefaultTreeCellRenderer) r).getText(); + icon = ((DefaultTreeCellRenderer) r).getIcon(); + } + } + } + if (tip == null) { + tip = getToolTipText(); + } + return tip; + } + + public Point getToolTipLocation(MouseEvent event) { + if (event != null) { + Point p = event.getPoint(); + int selRow = getRowForLocation(p.x, p.y); + TreeCellRenderer r = getCellRenderer(); + if (selRow != -1 && r != null) { + TreePath path = getPathForRow(selRow); + Rectangle pathBounds = getPathBounds(path); + return new Point(pathBounds.x - 2, pathBounds.y - 1); + } + } + return null; + } + + public JToolTip createToolTip() { + UIToolTip tip = new UIToolTip(icon); + tip.setComponent(this); + tip.setOpaque(false); + return tip; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTreeTest.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTreeTest.java new file mode 100644 index 0000000000..d79004ba01 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/RefreshableJTreeTest.java @@ -0,0 +1,85 @@ +package com.fr.design.gui.itree.refreshabletree; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Random; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.WindowConstants; +import javax.swing.tree.DefaultTreeModel; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; + +public class RefreshableJTreeTest { + private static final Integer[][] ii = new Integer[][] { + new Integer[] {new Integer(0), new Integer(1), new Integer(2)}, + new Integer[] {new Integer(0), new Integer(2), new Integer(3)}, + new Integer[] {new Integer(6), new Integer(7), new Integer(1)}, + new Integer[] {new Integer(3), new Integer(4), new Integer(2)}, + new Integer[] {new Integer(4), new Integer(2), new Integer(3)} + }; + + public static void main(String[] args) { + JFrame frm = new JFrame("LOADING..."); + JPanel contentPane = (JPanel)frm.getContentPane(); + contentPane.setLayout(FRGUIPaneFactory.createBorderLayout()); + + final RefreshableJTree tree = new RefreshableJTree() { + + protected boolean interceptRefresh(ExpandMutableTreeNode eTreeNode) { + return eTreeNode.getChildCount() == 0 + || ((ExpandMutableTreeNode)eTreeNode.getFirstChild()).getUserObject() == PENDING; + } + + protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode) { + Object[] os = ii[new Random().nextInt(5)]; + ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[os.length]; + for(int i = 0; i < os.length; i++) { + res[i] = new ExpandMutableTreeNode(os[i]); + } + + return res; + } + + }; + contentPane.add(new JScrollPane(tree), BorderLayout.CENTER); + + DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode)model.getRoot(); + root.removeAllChildren(); + + ExpandMutableTreeNode node001 = new ExpandMutableTreeNode(new Integer(0)); + root.add(node001); + node001.add(new ExpandMutableTreeNode("NODE0011")); + node001.add(new ExpandMutableTreeNode("NODE0012")); + node001.add(new ExpandMutableTreeNode("NODE0013")); + + ExpandMutableTreeNode node002 = new ExpandMutableTreeNode(new Integer(1)); + root.add(node002); + node002.add(new ExpandMutableTreeNode(RefreshableJTree.PENDING)); + + ExpandMutableTreeNode node003 = new ExpandMutableTreeNode(new Integer(2)); + root.add(node003); + + model.reload(root); + + UIButton btn = new UIButton("refresh"); + contentPane.add(GUICoreUtils.createFlowPane(btn, FlowLayout.LEFT), BorderLayout.NORTH); + btn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + tree.refresh(); + } + }); + + frm.setSize(600, 400); + frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frm.setVisible(true); + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeDataCardPane.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeDataCardPane.java new file mode 100644 index 0000000000..2df4b5de32 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeDataCardPane.java @@ -0,0 +1,55 @@ +package com.fr.design.gui.itree.refreshabletree; + +import java.awt.BorderLayout; + +import com.fr.general.NameObject; +import com.fr.data.impl.TreeAttr; +import com.fr.data.impl.TreeNodeAttr; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.layout.FRGUIPaneFactory; + + +public class TreeDataCardPane extends BasicBeanPane { + private NameObject no; + private TreeNodeAttr treeNodeAttr; + private TreeNodePane treeNodePane; + + public TreeDataCardPane() { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + treeNodePane = new TreeNodePane(); + + } + + @Override + protected String title4PopupWindow() { + return "treedata"; + } + + @Override + public void populateBean(Object object) { + this.remove(treeNodePane); + if (object instanceof NameObject){ + this.no = (NameObject)object; + Object ob = this.no.getObject(); + if (ob instanceof TreeNodeAttr) { + this.treeNodeAttr = (TreeNodeAttr)ob; + this.add(treeNodePane, BorderLayout.CENTER); + treeNodePane.populateBean(treeNodeAttr); + } + } + validate(); + repaint(); + revalidate(); + } + + @Override + public Object updateBean() { + if (treeNodeAttr != null) { + if (this.isAncestorOf(treeNodePane) && treeNodePane.isVisible() && !(this.no.getObject() instanceof TreeAttr)) { + treeNodeAttr = treeNodePane.updateBean(); + this.no.setObject(treeNodeAttr); + } + } + return null; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeNodePane.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeNodePane.java new file mode 100644 index 0000000000..dfe507194a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeNodePane.java @@ -0,0 +1,46 @@ +package com.fr.design.gui.itree.refreshabletree; + +import com.fr.data.Dictionary; +import com.fr.data.impl.TreeNodeAttr; +import com.fr.design.beans.BasicBeanPane; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.present.dict.DictionaryPane; + +import java.awt.*; + +public class TreeNodePane extends BasicBeanPane { + + private DictionaryPane dataRadioPane; + + /* + * richer:树支节点数据设置面板 + */ + public TreeNodePane(){ + this.initComponents(); + } + + private void initComponents(){ + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + dataRadioPane = new DictionaryPane(); + this.add(dataRadioPane, BorderLayout.CENTER); + + } + + @Override + protected String title4PopupWindow() { + return "tree"; + } + + public void populateBean(TreeNodeAttr treeNodeAttr){ + Dictionary dict = treeNodeAttr.getDictionary(); + dataRadioPane.populateBean(dict); + } + + public TreeNodeAttr updateBean(){ + TreeNodeAttr treeNodeAttr = new TreeNodeAttr(); + Dictionary mvList = this.dataRadioPane.updateBean(); + treeNodeAttr.setDictionary(mvList); + + return treeNodeAttr; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java new file mode 100644 index 0000000000..1a1633c0b1 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/TreeRootPane.java @@ -0,0 +1,83 @@ +package com.fr.design.gui.itree.refreshabletree; + +import java.awt.Color; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import com.fr.design.gui.ilable.UILabel; +import javax.swing.JPanel; + +import com.fr.data.impl.TreeAttr; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.icombobox.UIComboBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.dialog.BasicPane; +import com.fr.general.Inter; + +public class TreeRootPane extends BasicPane { + + // 是否支持多选(checkBoxTree) + //private JCheckBox multipleSelection; + private UIComboBox checkTypeComboBox; + + // richer:加载的方式,支持异步加载和完全加载 + private UIComboBox loadTypeComboBox; + + private UICheckBox layerTypeCheckBox; + + private UICheckBox returnFullPathCheckBox ; + + public TreeRootPane() { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + JPanel checkTypePane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + checkTypePane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + checkTypePane.add(new UILabel(Inter.getLocText("Tree-Mutiple_Selection_Or_Not") + ":")); + checkTypeComboBox = new UIComboBox(new String[] {Inter.getLocText("Yes"), Inter.getLocText("No")}); + checkTypePane.add(checkTypeComboBox); + this.add(checkTypePane); + + JPanel loadTypePane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + loadTypePane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + loadTypePane.add(new UILabel(Inter.getLocText("Widget-Load_Type") + ":")); + loadTypeComboBox = new UIComboBox(new String[]{Inter.getLocText("Widget-Load_By_Async"), Inter.getLocText("Widget-Load_By_Complete")}); + loadTypePane.add(loadTypeComboBox); + this.add(loadTypePane); + + JPanel leafSelectPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + leafSelectPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + leafSelectPane.add(layerTypeCheckBox = new UICheckBox(Inter.getLocText("Tree-Select_Leaf_Only"))); + UILabel tips = new UILabel(Inter.getLocText("Tree-Select_Leaf_Only_Tips")); + tips.setForeground(new Color(147, 178, 233)); + leafSelectPane.add(tips); + this.add(leafSelectPane); + + JPanel returnFullPathPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane(); + returnFullPathPane.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + returnFullPathPane.add(returnFullPathCheckBox = new UICheckBox(Inter.getLocText("Tree-Return_Full_Path"))); + this.add(returnFullPathPane); + + } + + @Override + protected String title4PopupWindow() { + return "tree"; + } + + public void populate(TreeAttr treeAttr) { + checkTypeComboBox.setSelectedIndex(treeAttr.isMultipleSelection() ? 0 : 1); + loadTypeComboBox.setSelectedIndex(treeAttr.isAjax() ? 0 : 1); + layerTypeCheckBox.setSelected(treeAttr.isSelectLeafOnly()); + returnFullPathCheckBox.setSelected(treeAttr.isReturnFullPath()); + } + + public TreeAttr update() { + TreeAttr treeAttr = new TreeAttr(); + treeAttr.setMultipleSelection(checkTypeComboBox.getSelectedIndex() == 0); + treeAttr.setAjax(loadTypeComboBox.getSelectedIndex() == 0); + treeAttr.setSelectLeafOnly(layerTypeCheckBox.isSelected()); + treeAttr.setReturnFullPath(returnFullPathCheckBox.isSelected()); + + return treeAttr; + } +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectOP.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectOP.java new file mode 100644 index 0000000000..6e6a1eee38 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectOP.java @@ -0,0 +1,33 @@ +package com.fr.design.gui.itree.refreshabletree; + +import java.util.List; +import java.util.Map; + +import com.fr.design.gui.itree.refreshabletree.loader.ChildrenNodesLoader; + + +/** + * UserObjectRefreshJTree的操作 + * + * @editor zhou + * @since 2012-3-28下午9:49:31 + */ + +public interface UserObjectOP extends ChildrenNodesLoader { + + /* + * 初始化返回name, T键值对 + */ + public List> init(); + + /* + * ButtonEnabled intercept + */ + public boolean interceptButtonEnabled(); + + /* + * 移除名字是name的TableData + */ + public void removeAction(String name); + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectRefreshJTree.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectRefreshJTree.java new file mode 100644 index 0000000000..9bef9e6fad --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/UserObjectRefreshJTree.java @@ -0,0 +1,167 @@ +package com.fr.design.gui.itree.refreshabletree; + +import com.fr.general.NameObject; +import com.fr.design.gui.itree.refreshabletree.loader.ChildrenLoaderFactory; +import com.fr.general.ComparatorUtils; +import com.fr.design.utils.gui.GUICoreUtils; + +import javax.swing.*; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +public abstract class UserObjectRefreshJTree> extends RefreshableJTree { + private static final long serialVersionUID = 8824111110910126977L; + private TreePath[] oldPaths; + private boolean isFind; + + public UserObjectRefreshJTree() { + super(); + this.putClientProperty("JTree.lineStyle", "Angled"); + this.setShowsRootHandles(true); + this.setRootVisible(false); + + // 改变选择模式是为了能拖动多个数据列 + this.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + + // alex:选中多个节点的时候,当左键点击其中某节点时,还必须选中那多个节点 + this.addMouseListener(treeMouseListener); + } + + /* + * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh + */ + @Override + protected boolean interceptRefresh(ExpandMutableTreeNode eTreeNode) { + if (eTreeNode.getUserObject() instanceof UserObjectOP) { + return false; + } + return eTreeNode.getChildCount() == 0 || ((ExpandMutableTreeNode) eTreeNode.getFirstChild()).getUserObject() == PENDING; + } + + /** + * Populate + */ + public void populate(T userObject) { + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + root.setUserObject(userObject); + root.removeAllChildren(); + + ExpandMutableTreeNode[] children = loadChildTreeNodes(root); + for (int i = 0; i < children.length; i++) { + root.add(children[i]); + } + treeModel.reload(root); + root.expandCurrentTreeNode(this); + } + + @Override + protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode selectedTreeNode) { + Object userObj = selectedTreeNode.getUserObject(); + return ChildrenLoaderFactory.createChildNodesLoader(userObj).load(); + } + + /** + * 移掉根目录下的 + */ + public void removeNameObject(NameObject no) { + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + + for (int i = 0, len = root.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) root.getChildAt(i); + + if (ComparatorUtils.equals(childTreeNode.getUserObject(), no)) { + root.remove(childTreeNode); + treeModel.reload(root); + break; + } + } + } + + /* + * 根据NameObject取TreePath + */ + public TreePath getTreePathByNameObject(NameObject nameObject) { + if (nameObject == null) { + return null; + } + + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + + // 新建一个放着NameObject的newChildTreeNode,加到Root下面 + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + + for (int i = 0, len = root.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) root.getChildAt(i); + if (ComparatorUtils.equals(nameObject, childTreeNode.getUserObject())) { + return GUICoreUtils.getTreePath(childTreeNode); + } + } + + return null; + } + + /** + * 看一下名字是否重复 + */ + public boolean isNameRepeated(String name) { + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + + for (int i = 0, len = root.getChildCount(); i < len; i++) { + ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) root.getChildAt(i); + Object userObject = childTreeNode.getUserObject(); + if (userObject instanceof NameObject && ((NameObject) userObject).getName().endsWith(name)) { + return true; + } + + } + + + return false; + } + + public void setSelectionPath(TreePath treePath) { + if (isFind) { + return; + } + super.setSelectionPath(treePath); + } + + private MouseListener treeMouseListener = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + TreePath path = getPathForLocation(e.getX(), e.getY()); + isFind = false; + if (path != null && oldPaths != null) { + for (int i = 0; i < oldPaths.length; i++) { + if (ComparatorUtils.equals(path, oldPaths[i])) { + isFind = true; + break; + } + } + } + // marks:鼠标在上次选中的paths上,则将上次的paths设为的树的路径,否则将鼠标所在的节点设为选中的节点 + if (!(e.isShiftDown() || e.isControlDown())) { + if (isFind) { + setSelectionPaths(oldPaths); + } else { + setSelectionPath(path); + } + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + oldPaths = getSelectionPaths(); + } + } + }; +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenLoaderFactory.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenLoaderFactory.java new file mode 100644 index 0000000000..1d3cb5e411 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenLoaderFactory.java @@ -0,0 +1,17 @@ +package com.fr.design.gui.itree.refreshabletree.loader; + +import com.fr.general.NameObject; + +public abstract class ChildrenLoaderFactory { + + public static ChildrenNodesLoader createChildNodesLoader(Object obj) { + if (obj instanceof ChildrenNodesLoader) { + return (ChildrenNodesLoader) obj; + } else if (obj instanceof NameObject) { + return createChildNodesLoader(((NameObject) obj).getObject()); + } else { + return ChildrenNodesLoader.NULL; + } + } + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenNodesLoader.java b/designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenNodesLoader.java new file mode 100644 index 0000000000..d85f00b80a --- /dev/null +++ b/designer_base/src/com/fr/design/gui/itree/refreshabletree/loader/ChildrenNodesLoader.java @@ -0,0 +1,29 @@ +package com.fr.design.gui.itree.refreshabletree.loader; + +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; + + +/** + * 生成树上的子节点 + * + * @editor zhou + * @since 2012-3-28下午9:57:40 + */ +public interface ChildrenNodesLoader { + + /** + * 生成子节点 + * + * @return + */ + ExpandMutableTreeNode[] load(); + + public static ChildrenNodesLoader NULL = new ChildrenNodesLoader() { + + @Override + public ExpandMutableTreeNode[] load() { + return new ExpandMutableTreeNode[0]; + } + }; + +} \ No newline at end of file diff --git a/designer_base/src/com/fr/design/gui/style/AbstractBasicStylePane.java b/designer_base/src/com/fr/design/gui/style/AbstractBasicStylePane.java new file mode 100644 index 0000000000..6df46b46c9 --- /dev/null +++ b/designer_base/src/com/fr/design/gui/style/AbstractBasicStylePane.java @@ -0,0 +1,29 @@ +package com.fr.design.gui.style; + +import com.fr.base.Style; +import com.fr.design.beans.BasicBeanPane; + +/** + * + * @author zhou + * @since 2012-5-24下午1:42:53 + */ +public abstract class AbstractBasicStylePane extends BasicBeanPane