diff --git a/.gitattributes b/.gitattributes
index ab7f46498..75c7a0cfb 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -984,3 +984,382 @@ designer_chart/src/com/fr/design/module/FormHyperlinkGroup.java -text
designer_chart/src/com/fr/file/FILEChooserPane4Chart.java -text
designer_chart/src/com/fr/start/ChartSplashPane.java -text
designer_chart/src/com/fr/start/Designer4Chart.java -text
+designer_form/.classpath -text
+designer_form/.project -text
+designer_form/designer_form.iml -text
+designer_form/src/com/fr/design/designer/beans/AdapterBus.java -text
+designer_form/src/com/fr/design/designer/beans/ComponentAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/ConnectorCreator.java -text
+designer_form/src/com/fr/design/designer/beans/ConstraintsGroupModel.java -text
+designer_form/src/com/fr/design/designer/beans/HoverPainter.java -text
+designer_form/src/com/fr/design/designer/beans/Incremental.java -text
+designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/Painter.java -text
+designer_form/src/com/fr/design/designer/beans/actions/ChangeNameAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/ConnectionAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/CutAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/FormDeleteAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/FormEditAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/FormUndoableAction.java -text
+designer_form/src/com/fr/design/designer/beans/actions/PasteAction.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/AbsoluteLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractAnchorPainter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/DefaultLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRBorderLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRCardLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFormLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRGridLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRHorizontalLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRHorizontalSplitLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRParameterLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRScaleLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTitleLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalSplitLayoutAdapter.java -text
+designer_form/src/com/fr/design/designer/beans/events/CreatorEventListenerTable.java -text
+designer_form/src/com/fr/design/designer/beans/events/DesignerEditListener.java -text
+designer_form/src/com/fr/design/designer/beans/events/DesignerEditor.java -text
+designer_form/src/com/fr/design/designer/beans/events/DesignerEvent.java -text
+designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java -text
+designer_form/src/com/fr/design/designer/beans/location/Add.java -text
+designer_form/src/com/fr/design/designer/beans/location/Bottom.java -text
+designer_form/src/com/fr/design/designer/beans/location/Direction.java -text
+designer_form/src/com/fr/design/designer/beans/location/Inner.java -text
+designer_form/src/com/fr/design/designer/beans/location/Left.java -text
+designer_form/src/com/fr/design/designer/beans/location/LeftBottom.java -text
+designer_form/src/com/fr/design/designer/beans/location/LeftTop.java -text
+designer_form/src/com/fr/design/designer/beans/location/Location.java -text
+designer_form/src/com/fr/design/designer/beans/location/Outer.java -text
+designer_form/src/com/fr/design/designer/beans/location/Right.java -text
+designer_form/src/com/fr/design/designer/beans/location/RightBottom.java -text
+designer_form/src/com/fr/design/designer/beans/location/RightTop.java -text
+designer_form/src/com/fr/design/designer/beans/location/RootResizeDirection.java -text
+designer_form/src/com/fr/design/designer/beans/location/Top.java -text
+designer_form/src/com/fr/design/designer/beans/models/AddingModel.java -text
+designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java -text
+designer_form/src/com/fr/design/designer/beans/models/StateModel.java -text
+designer_form/src/com/fr/design/designer/beans/painters/AbstractPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRBorderLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRBoxLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRFitLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutAnchorPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRHorizontalLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRParameterLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/FRVerticalLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/NullLayoutPainter.java -text
+designer_form/src/com/fr/design/designer/beans/painters/NullPainter.java -text
+designer_form/src/com/fr/design/designer/creator/CRPropertyDescriptor.java -text
+designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java -text
+designer_form/src/com/fr/design/designer/creator/FormCardPane.java -text
+designer_form/src/com/fr/design/designer/creator/NullCreator.java -text
+designer_form/src/com/fr/design/designer/creator/XAbstractSplitLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java -text
+designer_form/src/com/fr/design/designer/creator/XButton.java -text
+designer_form/src/com/fr/design/designer/creator/XChartEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XCheckBox.java -text
+designer_form/src/com/fr/design/designer/creator/XCheckBoxGroup.java -text
+designer_form/src/com/fr/design/designer/creator/XComboBox.java -text
+designer_form/src/com/fr/design/designer/creator/XComboCheckBox.java -text
+designer_form/src/com/fr/design/designer/creator/XComponent.java -text
+designer_form/src/com/fr/design/designer/creator/XConnector.java -text
+designer_form/src/com/fr/design/designer/creator/XCreator.java -text
+designer_form/src/com/fr/design/designer/creator/XCreatorTools.java -text
+designer_form/src/com/fr/design/designer/creator/XCreatorUtils.java -text
+designer_form/src/com/fr/design/designer/creator/XCustomWriteAbleRepeatEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XDataTable.java -text
+designer_form/src/com/fr/design/designer/creator/XDateEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XDirectWriteEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XEditorHolder.java -text
+designer_form/src/com/fr/design/designer/creator/XElementCase.java -text
+designer_form/src/com/fr/design/designer/creator/XFieldEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XFileUploader.java -text
+designer_form/src/com/fr/design/designer/creator/XIframeEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XLabel.java -text
+designer_form/src/com/fr/design/designer/creator/XLayoutContainer.java -text
+designer_form/src/com/fr/design/designer/creator/XListEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XMultiFileUploader.java -text
+designer_form/src/com/fr/design/designer/creator/XNameWidget.java -text
+designer_form/src/com/fr/design/designer/creator/XNumberEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XPassword.java -text
+designer_form/src/com/fr/design/designer/creator/XRadio.java -text
+designer_form/src/com/fr/design/designer/creator/XRadioGroup.java -text
+designer_form/src/com/fr/design/designer/creator/XTableEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XTableTree.java -text
+designer_form/src/com/fr/design/designer/creator/XTextArea.java -text
+designer_form/src/com/fr/design/designer/creator/XTextEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XTreeComboBoxEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XTreeEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWBorderLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWFitLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWGridLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWHorizontalBoxLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWHorizontalSplitLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWParameterLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWScaleLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWTitleLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWVerticalBoxLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWVerticalSplitLayout.java -text
+designer_form/src/com/fr/design/designer/creator/XWidgetCreator.java -text
+designer_form/src/com/fr/design/designer/creator/XWrapperedFieldEditor.java -text
+designer_form/src/com/fr/design/designer/creator/XWriteAbleRepeatEditor.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XCardAddButton.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XCardSwitchButton.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardLayout.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardTitleLayout.java -text
+designer_form/src/com/fr/design/designer/creator/cardlayout/XWTabFitLayout.java -text
+designer_form/src/com/fr/design/designer/properties/BoundsGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/CardDefaultShowEditor.java -text
+designer_form/src/com/fr/design/designer/properties/CardDefaultShowRenderer.java -text
+designer_form/src/com/fr/design/designer/properties/CardDefaultShowWrapper.java -text
+designer_form/src/com/fr/design/designer/properties/CardLayoutConstraints.java -text
+designer_form/src/com/fr/design/designer/properties/CardLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/Decoder.java -text
+designer_form/src/com/fr/design/designer/properties/DelegateEditor.java -text
+designer_form/src/com/fr/design/designer/properties/Encoder.java -text
+designer_form/src/com/fr/design/designer/properties/EnumerationEditor.java -text
+designer_form/src/com/fr/design/designer/properties/EventPropertyTable.java -text
+designer_form/src/com/fr/design/designer/properties/FRBorderConstraintsEditor.java -text
+designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraints.java -text
+designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraintsRenderer.java -text
+designer_form/src/com/fr/design/designer/properties/FRBorderLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/FRCardConstraintsEditor.java -text
+designer_form/src/com/fr/design/designer/properties/FRFitLayoutConstraints.java -text
+designer_form/src/com/fr/design/designer/properties/FRFitLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/FRFormLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/FRGridLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/FRTabFitLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/FitStateRenderer.java -text
+designer_form/src/com/fr/design/designer/properties/FitStateWrapper.java -text
+designer_form/src/com/fr/design/designer/properties/FormWidgetAuthorityEditPane.java -text
+designer_form/src/com/fr/design/designer/properties/HVLayoutConstraints.java -text
+designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentEditor.java -text
+designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentRenderer.java -text
+designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentWrapper.java -text
+designer_form/src/com/fr/design/designer/properties/HorizontalLayoutConstraints.java -text
+designer_form/src/com/fr/design/designer/properties/HorizontalLayoutPropertiesGroupModel.java -text
+designer_form/src/com/fr/design/designer/properties/HorizontalSplitProperties.java -text
+designer_form/src/com/fr/design/designer/properties/IconCellEditor.java -text
+designer_form/src/com/fr/design/designer/properties/ItemWrapper.java -text
+designer_form/src/com/fr/design/designer/properties/LayoutConstraintsEditor.java -text
+designer_form/src/com/fr/design/designer/properties/MultiSelectionBoundsModel.java -text
+designer_form/src/com/fr/design/designer/properties/NameWithListeners.java -text
+designer_form/src/com/fr/design/designer/properties/VerticalBoxProperties.java -text
+designer_form/src/com/fr/design/designer/properties/VerticalLayoutConstraints.java -text
+designer_form/src/com/fr/design/designer/properties/VerticalSplitProperties.java -text
+designer_form/src/com/fr/design/designer/properties/WidgetPropertyTable.java -text
+designer_form/src/com/fr/design/designer/properties/items/FRBorderConstraintsItems.java -text
+designer_form/src/com/fr/design/designer/properties/items/FRFitConstraintsItems.java -text
+designer_form/src/com/fr/design/designer/properties/items/HorizontalAlignmentItems.java -text
+designer_form/src/com/fr/design/designer/properties/items/Item.java -text
+designer_form/src/com/fr/design/designer/properties/items/ItemProvider.java -text
+designer_form/src/com/fr/design/designer/properties/items/LabelHorizontalAlignmentItems.java -text
+designer_form/src/com/fr/design/designer/properties/items/LayoutIndexItems.java -text
+designer_form/src/com/fr/design/designer/properties/items/UnderlineItems.java -text
+designer_form/src/com/fr/design/designer/properties/items/WidgetDisplayPositionItems.java -text
+designer_form/src/com/fr/design/designer/treeview/ComponentTreeCellRenderer.java -text
+designer_form/src/com/fr/design/designer/treeview/ComponentTreeModel.java -text
+designer_form/src/com/fr/design/form/images/add.png -text
+designer_form/src/com/fr/design/form/images/delete_hover&click.png -text
+designer_form/src/com/fr/design/form/images/delete_normal.png -text
+designer_form/src/com/fr/design/form/javascript/FormEmailPane.java -text
+designer_form/src/com/fr/design/form/layout/FRAbsoluteLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRBorderLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRCardLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRFitLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRFlowLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRFormLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRGridLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRHorizontalLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRHorizontalSplitLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRLayoutManager.java -text
+designer_form/src/com/fr/design/form/layout/FRPolyReportLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRScaleLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRSplitLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRTitleLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRVerticalLayout.java -text
+designer_form/src/com/fr/design/form/layout/FRVerticalSplitLayout.java -text
+designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java -text
+designer_form/src/com/fr/design/form/parameter/FormParaTargetMode.java -text
+designer_form/src/com/fr/design/form/parameter/RootDesignGroupModel.java -text
+designer_form/src/com/fr/design/form/parameter/XFormSubmit.java -text
+designer_form/src/com/fr/design/form/util/XCreatorConstants.java -text
+designer_form/src/com/fr/design/gui/core/FormWidgetOption.java -text
+designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPane.java -text
+designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPreviewPane.java -text
+designer_form/src/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java -text
+designer_form/src/com/fr/design/gui/xpane/JTreeAutoBuildPane.java -text
+designer_form/src/com/fr/design/gui/xpane/LayoutBorderPane.java -text
+designer_form/src/com/fr/design/gui/xpane/LayoutBorderPreviewPane.java -text
+designer_form/src/com/fr/design/gui/xpane/ToolTipEditor.java -text
+designer_form/src/com/fr/design/gui/xtable/AbstractPropertyGroupModel.java -text
+designer_form/src/com/fr/design/gui/xtable/PropertyGroupModel.java -text
+designer_form/src/com/fr/design/gui/xtable/TableUtils.java -text
+designer_form/src/com/fr/design/mainframe/AutoScrollSource.java -text
+designer_form/src/com/fr/design/mainframe/ComponentTree.java -text
+designer_form/src/com/fr/design/mainframe/ConnectorHelper.java -text
+designer_form/src/com/fr/design/mainframe/CoverReportPane.java -text
+designer_form/src/com/fr/design/mainframe/DesignerTransferHandler.java -text
+designer_form/src/com/fr/design/mainframe/EditingMouseListener.java -text
+designer_form/src/com/fr/design/mainframe/FormArea.java -text
+designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java -text
+designer_form/src/com/fr/design/mainframe/FormDesigner.java -text
+designer_form/src/com/fr/design/mainframe/FormDesignerDropTarget.java -text
+designer_form/src/com/fr/design/mainframe/FormDesignerModeForSpecial.java -text
+designer_form/src/com/fr/design/mainframe/FormDesignerUI.java -text
+designer_form/src/com/fr/design/mainframe/FormDockView.java -text
+designer_form/src/com/fr/design/mainframe/FormEditorKeyListener.java -text
+designer_form/src/com/fr/design/mainframe/FormHierarchyTreePane.java -text
+designer_form/src/com/fr/design/mainframe/FormModelAdapter.java -text
+designer_form/src/com/fr/design/mainframe/FormParaPane.java -text
+designer_form/src/com/fr/design/mainframe/FormParaWidgetPane.java -text
+designer_form/src/com/fr/design/mainframe/FormSelection.java -text
+designer_form/src/com/fr/design/mainframe/FormSelectionUtils.java -text
+designer_form/src/com/fr/design/mainframe/FormTargetMode.java -text
+designer_form/src/com/fr/design/mainframe/FormUndoState.java -text
+designer_form/src/com/fr/design/mainframe/FormWidgetDetailPane.java -text
+designer_form/src/com/fr/design/mainframe/FormWidgetPopWindow.java -text
+designer_form/src/com/fr/design/mainframe/JForm.java -text
+designer_form/src/com/fr/design/mainframe/MobileBodyWidgetTable.java -text
+designer_form/src/com/fr/design/mainframe/MobileWidgetTable.java -text
+designer_form/src/com/fr/design/mainframe/TabChangeAction.java -text
+designer_form/src/com/fr/design/mainframe/ToolBarButton.java -text
+designer_form/src/com/fr/design/mainframe/TreeTransferHandler.java -text
+designer_form/src/com/fr/design/mainframe/WLayoutSelectionPane.java -text
+designer_form/src/com/fr/design/mainframe/WidgetPropertyPane.java -text
+designer_form/src/com/fr/design/mainframe/WidgetToolBarPane.java -text
+designer_form/src/com/fr/design/mainframe/actions/EmbeddedFormExportExportAction.java -text
+designer_form/src/com/fr/design/mainframe/actions/NewFormAction.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleBackgroundEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleCardTagWLayoutBorderStyleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleColorEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleDateEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleDictionaryEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleDimensionEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleFontEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleFormulaEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleGridWidgetEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleIconEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleImgBackgroundEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleParameterEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessiblePropertyCellEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessiblePropertyEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleRegexEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleTreeModelEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleWLayoutBorderStyleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessibleWidgetValueEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/AccessilePaddingMarginEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/BaseAccessibleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/ColorIcon.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/ColorPalette.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/RendererField.java -text
+designer_form/src/com/fr/design/mainframe/widget/accessibles/UneditableAccessibleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/AdjustModeEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/BackgroundEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/BooleanEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/BorderLayoutDirectionEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ButtonTypeEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/CardTagWLayoutBorderStyleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ColorEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ColorTextField.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ComboEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DataTableConfigPane.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DateFormatEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DateRangeEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DecorationEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DictionaryEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DimensionEditingPane.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DimensionEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/DoubleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/FitLayoutDirectionEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/FloatEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/FontEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/FormulaEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ITextComponent.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/IconEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ImgBackgroundEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/InChangeBooleanEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ItemCellEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/LongEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/NameWidgetComboboxEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/PaddingMarginEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/PaddingMarginPane.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ParameterEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/PercentageEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/RegexEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/ShortCutTextEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/SpinnerMaxNumberEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/SpinnerMinNumberEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/SpinnerNumberEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/TextField.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/TreeModelEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/WLayoutBorderStyleEditor.java -text
+designer_form/src/com/fr/design/mainframe/widget/editors/WidgetDisplayPosition.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/BackgroundRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/ColorCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/DateCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/DictionaryRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/DimensionCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/EncoderCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/FontCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/GenericCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/GridWidgetRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/HyperlinkGroupRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/IconCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/LabelHorizontalAlignmentRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/LayoutBorderStyleRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/PaddingMarginCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/ParameterRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/PointCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/PropertyCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/RectangleCellRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/RegexCellRencerer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/TreeModelRenderer.java -text
+designer_form/src/com/fr/design/mainframe/widget/renderer/WidgetDisplayPositionRender.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/BackgroundWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/ColorWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/DSColumnWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/DateWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/DictionaryWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/DimensionWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/EventHandlerWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/FontWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/FormulaWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/GridWidgetWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/HyperlinkGroupWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/IconWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/LabelHorizontalAlignmentWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/LayoutBorderStyleWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/PaddingMarginWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/ParameterWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/PointWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/RectangleWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/RegexWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/TreeModelWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/WidgetDisplayPositionWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/WrapperUtils.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/BooleanWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/ByteWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/CharWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/DoubleWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/FloatWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/IntegerWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/LongWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/ShortWrapper.java -text
+designer_form/src/com/fr/design/mainframe/widget/wrappers/primitive/StringWrapper.java -text
+designer_form/src/com/fr/design/module/FormDesignerModule.java -text
+designer_form/src/com/fr/design/parameter/FormParameterReader.java -text
+designer_form/src/com/fr/design/parameter/ParameterPropertyPane.java -text
+designer_form/src/com/fr/design/parameter/ParameterToolBarPane.java -text
+designer_form/src/com/fr/design/widget/ui/btn/FormSubmitButtonDetailPane.java -text
+designer_form/src/com/fr/start/Designer4Form.java -text
diff --git a/.gitignore b/.gitignore
index 62e272039..b5e1bcf13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
designer/bin
designer_chart/bin
+designer_form/bin
diff --git a/designer_form/.classpath b/designer_form/.classpath
new file mode 100644
index 000000000..4eb8d8868
--- /dev/null
+++ b/designer_form/.classpath
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/designer_form/.project b/designer_form/.project
new file mode 100644
index 000000000..e5f3fcc3a
--- /dev/null
+++ b/designer_form/.project
@@ -0,0 +1 @@
+
designer_form
org.eclipse.jdt.core.javabuilder
org.eclipse.jdt.core.javanature
\ No newline at end of file
diff --git a/designer_form/designer_form.iml b/designer_form/designer_form.iml
new file mode 100644
index 000000000..842981108
--- /dev/null
+++ b/designer_form/designer_form.iml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/AdapterBus.java b/designer_form/src/com/fr/design/designer/beans/AdapterBus.java
new file mode 100644
index 000000000..ae866b21d
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/AdapterBus.java
@@ -0,0 +1,78 @@
+package com.fr.design.designer.beans;
+
+import java.awt.Component;
+
+import javax.swing.JComponent;
+import javax.swing.RootPaneContainer;
+
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter;
+import com.fr.design.designer.beans.painters.NullLayoutPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.utils.ComponentUtils;
+
+/**
+ * 适配器中枢,为组件和组件适配器、布局和布局适配器。
+ */
+public class AdapterBus {
+
+ public static final String CLIENT_PROPERTIES = "component.adapter";
+
+ public static JComponent getJComponent(Component component) {
+ JComponent jcomponent;
+ if (component instanceof JComponent) {
+ jcomponent = (JComponent) component;
+ } else if (component instanceof RootPaneContainer) {
+ jcomponent = (JComponent) ((RootPaneContainer) component).getContentPane();
+ } else {
+ return null;
+ }
+ return jcomponent;
+ }
+
+ /**
+ * 获取组件类型是componentClass对应的组件适配器,如果初始映射表中没有该适配器,
+ * 则继续查找其父类对应的适配器,直至查找到Component类为止,如果还是没有查找到,
+ * 则使用缺省的组件适配器:DefaultComponentAdapter
+ *
+ * @return 该组件类所对应的组件适配器对象
+ */
+ public static ComponentAdapter getComponentAdapter(FormDesigner designer, JComponent creator) {
+ JComponent jcomponent = getJComponent(creator);
+ ComponentAdapter adapter = (ComponentAdapter) jcomponent.getClientProperty("component.adapter");
+ if (adapter == null) {
+ adapter = new CompositeComponentAdapter(designer, creator);
+ jcomponent.putClientProperty(CLIENT_PROPERTIES, adapter);
+ }
+ return adapter;
+ }
+
+ public static XCreator getFirstInvisibleParent(XCreator comp) {
+ XCreator parent = comp;
+
+ while ((parent != null) && parent.isVisible()) {
+ parent = XCreatorUtils.getParentXLayoutContainer(parent);
+ }
+
+ return parent;
+ }
+
+ public static LayoutAdapter searchLayoutAdapter(FormDesigner designer, XCreator comp) {
+ if (ComponentUtils.isRootComponent(comp)) {
+ return null;
+ }
+ return XCreatorUtils.getParentXLayoutContainer(comp).getLayoutAdapter();
+ }
+
+ public static HoverPainter getContainerPainter(FormDesigner designer, XLayoutContainer container) {
+ // 容器组件的适配器
+ LayoutAdapter containerAdapter = container.getLayoutAdapter();
+ HoverPainter painter = containerAdapter.getPainter();
+ if (painter != null) {
+ return painter;
+ }
+ return new NullLayoutPainter(container);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/ComponentAdapter.java b/designer_form/src/com/fr/design/designer/beans/ComponentAdapter.java
new file mode 100644
index 000000000..58a5206c2
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/ComponentAdapter.java
@@ -0,0 +1,54 @@
+package com.fr.design.designer.beans;
+
+import java.awt.Graphics;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.JComponent;
+import javax.swing.JPopupMenu;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.beans.events.DesignerEditor;
+
+/**
+ * 组件适配器接口
+ * 主要目的是为具体组件提供特殊设计行为
+ */
+public interface ComponentAdapter {
+
+ /**
+ * 在组件选择面板上选择了组件类型后,在设计界面上跟随鼠标移动用来代表当前要添加组件的图形
+ * 一般使用组件自身的图形代替。
+ *
+ * @param component 要添加的组件
+ * @param g 当前设计器的图形上下文对象
+ */
+ void paintComponentMascot(Graphics g);
+
+ /**
+ * 当鼠标在此设计组件上右键点击时,该方法根据上下文和组件类型提供弹出响应的菜单
+ *
+ * @param 引发弹出菜单的鼠标事件
+ *
+ * @return 弹出菜单
+ */
+ JPopupMenu getContextPopupMenu(MouseEvent e);
+
+ /**
+ * 为当前组件创建描述属性表的model, 分组返回
+ * @return BeanPropertyModel
+ */
+ ArrayList getXCreatorPropertyModel();
+
+ /**
+ * 提供双击设计器的编辑器
+ * @param bean 鼠标双击的被设计组件
+ * @return 被设计的编辑器
+ */
+ public DesignerEditor extends JComponent> getDesignerEditor();
+
+ /**
+ * 实例化组件的适配器后,在这儿进行初始化
+ */
+ void initialize();
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/ConnectorCreator.java b/designer_form/src/com/fr/design/designer/beans/ConnectorCreator.java
new file mode 100644
index 000000000..2bfc0bf3f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/ConnectorCreator.java
@@ -0,0 +1,215 @@
+package com.fr.design.designer.beans;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.PriorityQueue;
+
+import com.fr.form.ui.container.WLayout;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+
+
+public class ConnectorCreator {
+
+ public static final int UNIT = 10;
+ public static final int SIDE = 2;
+ public static final int CORNER_LOSS = 20;
+ public static final int vector[][] = { { UNIT, 0 }, { -UNIT, 0 }, { 0, UNIT }, { 0, -UNIT } };
+
+ private long timeOut = 200;
+ private boolean beyond;
+ private WLayout container;
+ private BoundsWidget IgnoreLayout;
+ private Point startPoint;
+ private Point endPoint;
+ private PriorityQueue open = new PriorityQueue();
+ private PriorityQueue close = new PriorityQueue();
+
+ public ConnectorCreator(WLayout container, Point startPoint, Point endPoint) {
+ this.container =container;
+ this.startPoint = startPoint;
+ this.endPoint = endPoint;
+ if (getNearWidget(this.endPoint, SIDE * UNIT - 1) != null) {
+ if ((IgnoreLayout = getNearWidget(this.endPoint, -1)) == null) {
+ beyond = true;
+ }
+ }
+ }
+
+ private static int difference(int x, int y) {
+ int p;
+ if (x < y) {
+ p = x;
+ x = y;
+ y = p;
+ }
+ return x - y;
+ }
+
+ public static int getMinimumDistance(Point A, Point B) {
+ return difference(A.x, B.x) + difference(A.y, B.y) + (A.x == B.x || A.y == B.y ? 0 : CORNER_LOSS);
+ }
+
+ private BoundsWidget getNearWidget(Point endPoint, int l) {
+ Rectangle[] r = new Rectangle[container.getWidgetCount()];
+ Rectangle temp = new Rectangle();
+ BoundsWidget widget;
+ for (int i = 0, size = r.length; i < size; i++) {
+ widget = ((BoundsWidget) container.getWidget(i));
+ if (widget.isVisible()) {
+ r[i] = widget.getBounds();
+ temp.setBounds(r[i]);
+ temp.grow(l, l);
+ if (inside(endPoint, temp)) {
+ return widget;
+ }
+ }
+ }
+ return null;
+ }
+
+ private boolean arrive(Point p1, Point p2) {
+ if (!beyond) {
+ return p1.x - p2.x < UNIT && p2.x - p1.x < UNIT && p1.y - p2.y < UNIT && p2.y - p1.y < UNIT;
+ } else {
+ return p1.x - p2.x < (SIDE +1)* UNIT && p2.x - p1.x < (SIDE +1) * UNIT && p1.y - p2.y < (SIDE +1)* UNIT && p2.y - p1.y < (SIDE +1) * UNIT;
+ }
+ }
+
+ private boolean inside(Point p, Rectangle r) {
+ return p.x >= r.x && p.x <= r.x + r.width && p.y >= r.y && p.y <= r.y + r.height;
+ }
+
+ private boolean check(Point p) {
+ if (p.x <= 0 || p.y <= 0) {
+ return false;
+ }
+
+ BoundsWidget bw = getNearWidget(p, SIDE * UNIT - 1);
+ return bw == IgnoreLayout || bw ==null;
+ }
+
+ public ArrayList createPointList() {
+ ArrayList l = new ArrayList();
+ AssessedPoint pst = new AssessedPoint(startPoint,null,false);
+ AssessedPoint temp ;
+ long startTime = System.currentTimeMillis();
+ open.add(pst);
+ while ((temp = open.poll()) != null || (checkClose() && (temp = open.poll()) != null)) {
+ if (arrive(temp.p, endPoint)) {
+ temp.getS();
+ l.addAll(temp.pointList);
+ return l;
+ } else {
+ close.add(temp);
+ temp.pushInto();
+ }
+ if (System.currentTimeMillis() - startTime > timeOut) {
+ break;
+ }
+ }
+ l.add(startPoint);
+ l.add(new Point(startPoint.x,endPoint.y));
+ l.add(endPoint);
+ return l;
+ }
+
+ private boolean checkClose() {
+ if(close.size() == 1) {
+ AssessedPoint p = close.poll();
+ return p.reCheck();
+ }
+ return false;
+ }
+
+ class AssessedPoint implements Comparable{
+ ArrayList pointList;
+ Point p;
+ Point parent;
+ int distance;
+ int g;
+
+ AssessedPoint(Point p, AssessedPoint parent, boolean loss) {
+ this.p = p;
+ pointList = new ArrayList();
+ if (parent != null) {
+ this.g = parent.g + (loss ? CORNER_LOSS : UNIT);
+ this.parent = parent.p;
+ pointList.addAll(parent.pointList);
+ if (loss) {
+ pointList.add(parent.p);
+ }
+ } else {
+ pointList.add(p);
+ g = 0;
+ }
+ this.distance = getMinimumDistance(p, endPoint) + g;
+ }
+
+ public void getS() {
+ int size = pointList.size();
+ if(size > 1) {
+ Point p1 = pointList.get(size - 1);
+ if(p1.x == p.x) {
+ if(endPoint.x != p1.x) {
+ if(beyond) {
+ pointList.add(new Point(p1.x,endPoint.y));
+ } else {
+ p1.x = p.x = endPoint.x;
+ }
+
+ }
+ } else if(p1.y == p.y) {
+ if(endPoint.y != p1.y) {
+ if(beyond) {
+ pointList.add(new Point(endPoint.x,p1.y));
+ } else {
+ p1.y = p.y = endPoint.y;
+ }
+ }
+ }
+ } else if (size == 1 && (startPoint.x != endPoint.x || startPoint.y != endPoint.y)) {
+ pointList.add(new Point(startPoint.x, endPoint.y));
+ }
+ pointList.add(endPoint);
+ }
+
+ public int compareTo(AssessedPoint o) {
+ return distance - o.distance;
+ }
+
+ void pushInto() {
+ for (int i = 0; i < vector.length; i++) {
+ Point temp = new Point(p.x + vector[i][0], p.y + vector[i][1]);
+ if (parent != null && parent.x == temp.x && parent.y == temp.y) {
+ continue;
+ }
+ AssessedPoint ap = new AssessedPoint(temp, this, loss(temp));
+ if (check(temp) && !open.contains(ap) && !close.contains(ap)) {
+ open.add(ap);
+ }
+ }
+ }
+
+ boolean reCheck() {
+ for (int i = 0; i < vector.length; i++) {
+ Point temp = new Point(p.x + SIDE * vector[i][0], p.y + SIDE * vector[i][1]);
+ AssessedPoint ap = new AssessedPoint(temp, this, loss(temp));
+ if (check(temp)) {
+ open.add(ap);
+ }
+ }
+ return open.size() != 0;
+ }
+
+ private boolean loss(Point temp) {
+ return (parent != null && ((p.x == parent.x && temp.x != p.x) || (p.y == parent.y && temp.y != p.y)));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof AssessedPoint && ((AssessedPoint) o).p.x == p.x && ((AssessedPoint) o).p.y == p.y;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/ConstraintsGroupModel.java b/designer_form/src/com/fr/design/designer/beans/ConstraintsGroupModel.java
new file mode 100644
index 000000000..d7816eafe
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/ConstraintsGroupModel.java
@@ -0,0 +1,7 @@
+package com.fr.design.designer.beans;
+
+import com.fr.design.beans.GroupModel;
+
+public interface ConstraintsGroupModel extends GroupModel {
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/HoverPainter.java b/designer_form/src/com/fr/design/designer/beans/HoverPainter.java
new file mode 100644
index 000000000..0233e3270
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/HoverPainter.java
@@ -0,0 +1,23 @@
+package com.fr.design.designer.beans;
+
+import java.awt.Point;
+
+import com.fr.design.designer.creator.XCreator;
+
+/**
+ * 渲染器,目的是为组件或者布局管理器提供额外的渲染入口。
+ * @since 6.5.3
+ */
+public interface HoverPainter extends Painter {
+ /**
+ * 当前焦点热点,即鼠标所在点
+ * @param p 焦点位置
+ */
+ void setHotspot(Point p);
+
+ /**
+ * 当前要放置的组件
+ * @param creator 组件
+ */
+ void setCreator(XCreator creator);
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/Incremental.java b/designer_form/src/com/fr/design/designer/beans/Incremental.java
new file mode 100644
index 000000000..0ee8558ca
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/Incremental.java
@@ -0,0 +1,29 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package com.fr.design.designer.beans;
+
+/**
+ * 编辑器的增量,包括上下左右4个方向的增量
+ * @author richer
+ * @since 6.5.3
+ */
+public class Incremental {
+ public int top = 0;
+ public int left = 0;
+ public int bottom = 0;
+ public int right = 0;
+
+ public Incremental() {
+ this(0, 0, 0, 0);
+ }
+
+ public Incremental(int top, int left, int bottom, int right) {
+ this.top = top;
+ this.left = left;
+ this.bottom = bottom;
+ this.right = right;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java
new file mode 100644
index 000000000..fffc1c587
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/LayoutAdapter.java
@@ -0,0 +1,85 @@
+package com.fr.design.designer.beans;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.creator.XCreator;
+
+/**
+ * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类,
+ * 对于界面设计工具来说还需一些特殊的行为。
+ * @since 6.5.3
+ */
+public interface LayoutAdapter {
+
+ /**
+ * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局
+ * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比
+ * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以
+ * 放置。
+ *@param creator 组件
+ *@param x 添加的位置x,该位置是相对于container的
+ *@param y 添加的位置y,该位置是相对于container的
+ *@return 是否可以放置
+ */
+ boolean accept(XCreator creator, int x, int y);
+
+ /**
+ * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下
+ * @param creator 组件
+ */
+ void fix(XCreator creator);
+
+ /**
+ * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的
+ * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。
+ * @param creator 被添加的新组件
+ * @param x 添加的位置x,该位置是相对于container的
+ * @param y 添加的位置y,该位置是相对于container的
+ * @return 是否添加成功,成功返回true,否则false
+ */
+ boolean addBean(XCreator creator, int x, int y);
+
+ /**
+ * 返回该布局管理适配器的Painter,为容器提供放置位置的标识。
+ */
+ HoverPainter getPainter();
+
+ /**
+ * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况
+ * @param child 组件
+ */
+ void showComponent(XCreator child);
+
+ void addNextComponent(XCreator dragged);
+
+ /**
+ * 组件叠放顺序前插入
+ * @param target 目标组件
+ * @param added 插入组件
+ */
+ void addBefore(XCreator target, XCreator added);
+
+ /**
+ * 组件叠放顺序后插入
+ * @param target 目标组件
+ * @param added 放置组件
+ */
+ void addAfter(XCreator target, XCreator added);
+
+ /**
+ * 能否放置更多组件
+ * @return 能则返回true
+ */
+ boolean canAcceptMoreComponent();
+
+ ConstraintsGroupModel getLayoutConstraints(XCreator creator);
+
+ GroupModel getLayoutProperties();
+
+ /**
+ * 删除组件
+ * @param creator 组件
+ * @param initWidth 组件之前宽度
+ * @param initHeight 组件之前高度
+ */
+ void removeBean(XCreator creator, int initWidth, int initHeight);
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/Painter.java b/designer_form/src/com/fr/design/designer/beans/Painter.java
new file mode 100644
index 000000000..0674272b9
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/Painter.java
@@ -0,0 +1,12 @@
+package com.fr.design.designer.beans;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+public interface Painter {
+ //当前焦点区域,即所在容器的边界
+ void setRenderingBounds(Rectangle rect);
+
+ //渲染入口,由FormDesigner调用来外成额外渲染
+ void paint(Graphics g, int startX, int startY);
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/ChangeNameAction.java b/designer_form/src/com/fr/design/designer/beans/actions/ChangeNameAction.java
new file mode 100644
index 000000000..06ae1cca1
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/ChangeNameAction.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.actions;
+
+import com.fr.base.BaseUtils;
+import com.fr.general.Inter;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.creator.XWidgetCreator;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class ChangeNameAction extends FormUndoableAction {
+
+ public ChangeNameAction(FormDesigner t) {
+ super(t);
+
+ this.setName(Inter.getLocText("Form-Change_Widget_Name"));
+ this.setMnemonic('G');
+ this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png"));
+ }
+
+ /**
+ * 重命名
+ *
+ * @return 是否重命名成功
+ *
+ */
+ @Override
+ public boolean executeActionReturnUndoRecordNeeded() {
+ FormDesigner designer = getEditingComponent();
+ if (designer == null) {
+ return false;
+ }
+
+ // 如果选中了多个也只改变选中的第一个控件的名字
+ XWidgetCreator creator = (XWidgetCreator) designer.getSelectionModel().getSelection().getSelectedCreator();
+ if(creator == null) {
+ return false;
+ }
+ creator.ChangeCreatorName(designer, creator);
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/ConnectionAction.java b/designer_form/src/com/fr/design/designer/beans/actions/ConnectionAction.java
new file mode 100644
index 000000000..d7ec04189
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/ConnectionAction.java
@@ -0,0 +1,34 @@
+package com.fr.design.designer.beans.actions;
+
+import java.awt.event.ActionEvent;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.actions.ToggleButtonUpdateAction;
+import com.fr.design.actions.UpdateAction;
+import com.fr.design.gui.ibutton.UIToggleButton;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.general.Inter;
+import com.fr.design.utils.gui.GUICoreUtils;
+
+//marro : 连接线按钮,目前用不到,但是类先留着。2012-3-26
+public class ConnectionAction extends UpdateAction implements ToggleButtonUpdateAction {
+ private FormDesigner fd;
+
+ public ConnectionAction(FormDesigner fd) {
+ this.fd = fd;
+ this.setName(Inter.getLocText("Connectionline"));
+ this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/toolbarbtn/connector.png"));
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ UIToggleButton toggleButton = this.createToolBarComponent();
+ fd.setDrawLineMode(toggleButton.isSelected());
+ }
+
+ @Override
+ public UIToggleButton createToolBarComponent() {
+ return GUICoreUtils.createToolBarComponent(this);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java b/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java
new file mode 100644
index 000000000..e32ece18e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/CopyAction.java
@@ -0,0 +1,31 @@
+package com.fr.design.designer.beans.actions;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.KeyStroke;
+
+import com.fr.base.BaseUtils;
+import com.fr.general.Inter;
+import com.fr.design.mainframe.FormDesigner;
+
+public class CopyAction extends FormEditAction {
+
+ public CopyAction(FormDesigner 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, InputEvent.CTRL_MASK));
+ }
+
+ @Override
+ public boolean executeActionReturnUndoRecordNeeded() {
+ FormDesigner tc = getEditingComponent();
+ if (tc != null) {
+ tc.copy();
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/CutAction.java b/designer_form/src/com/fr/design/designer/beans/actions/CutAction.java
new file mode 100644
index 000000000..9acb26148
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/CutAction.java
@@ -0,0 +1,31 @@
+package com.fr.design.designer.beans.actions;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.KeyStroke;
+
+import com.fr.base.BaseUtils;
+import com.fr.general.Inter;
+import com.fr.design.mainframe.FormDesigner;
+
+public class CutAction extends FormEditAction {
+
+ public CutAction(FormDesigner 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, InputEvent.CTRL_MASK));
+ }
+
+ @Override
+ public boolean executeActionReturnUndoRecordNeeded() {
+ FormDesigner editPane = getEditingComponent();
+ if (editPane == null) {
+ return false;
+ }
+ return editPane.cut();
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/FormDeleteAction.java b/designer_form/src/com/fr/design/designer/beans/actions/FormDeleteAction.java
new file mode 100644
index 000000000..58c30543c
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/FormDeleteAction.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.actions;
+
+import java.awt.event.KeyEvent;
+
+import javax.swing.KeyStroke;
+
+import com.fr.base.BaseUtils;
+import com.fr.general.Inter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormSelection;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FormDeleteAction extends FormUndoableAction {
+
+ public FormDeleteAction(FormDesigner t) {
+ super(t);
+
+ this.setName(Inter.getLocText("M_Edit-Delete"));
+ this.setMnemonic('D');
+ // Richie:删除菜单图标
+ this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_report/delete.png"));
+ this.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
+ }
+
+ /**
+ * 删除
+ *
+ * @return 是否删除成功
+ */
+ @Override
+ public boolean executeActionReturnUndoRecordNeeded() {
+ FormDesigner designer = getEditingComponent();
+ if (designer == null) {
+ return false;
+ }
+ FormSelection selection = designer.getSelectionModel().getSelection();
+ XCreator creator = selection.getSelectedCreator();
+ designer.getSelectionModel().deleteSelection();
+
+ creator.deleteRelatedComponent(creator, designer);
+ return false;
+ }
+
+ @Override
+ public void update() {
+// FormDesigner f = this.getEditingComponent();
+// if (f == null) {
+// this.setEnabled(false);
+// return;
+// }
+// SelectionModel selection = f.getSelectionModel();
+// this.setEnabled(selection.hasSelectionComponent());
+ this.setEnabled(true);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/FormEditAction.java b/designer_form/src/com/fr/design/designer/beans/actions/FormEditAction.java
new file mode 100644
index 000000000..da7847fda
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/FormEditAction.java
@@ -0,0 +1,17 @@
+package com.fr.design.designer.beans.actions;
+
+import com.fr.design.actions.TemplateComponentAction;
+import com.fr.design.mainframe.FormDesigner;
+
+public abstract class FormEditAction extends TemplateComponentAction {
+
+ protected FormEditAction(FormDesigner t) {
+ super(t);
+ }
+
+ @Override
+ public void update() {
+ this.setEnabled(true);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/FormUndoableAction.java b/designer_form/src/com/fr/design/designer/beans/actions/FormUndoableAction.java
new file mode 100644
index 000000000..9f70fa518
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/FormUndoableAction.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.actions;
+
+import com.fr.design.actions.TemplateComponentAction;
+import com.fr.design.mainframe.FormDesigner;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class FormUndoableAction extends TemplateComponentAction {
+ protected FormUndoableAction(FormDesigner t) {
+ super(t);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/actions/PasteAction.java b/designer_form/src/com/fr/design/designer/beans/actions/PasteAction.java
new file mode 100644
index 000000000..85ce1d6ed
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/actions/PasteAction.java
@@ -0,0 +1,35 @@
+package com.fr.design.designer.beans.actions;
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.KeyStroke;
+
+import com.fr.base.BaseUtils;
+import com.fr.general.Inter;
+import com.fr.design.mainframe.FormDesigner;
+
+public class PasteAction extends FormEditAction {
+
+ public PasteAction(FormDesigner 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, InputEvent.CTRL_MASK));
+ }
+
+ @Override
+ public boolean executeActionReturnUndoRecordNeeded() {
+ FormDesigner tc = getEditingComponent();
+ if (tc == null) {
+ return false;
+ }
+ return tc.paste();
+ }
+ @Override
+ public void update() {
+ this.setEnabled(true);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java
new file mode 100644
index 000000000..82c939060
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java
@@ -0,0 +1,167 @@
+package com.fr.design.designer.beans.adapters.component;
+
+import java.awt.AlphaComposite;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.event.MouseEvent;
+import java.beans.IntrospectionException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JPopupMenu;
+
+import com.fr.base.FRContext;
+import com.fr.design.actions.UpdateAction;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.gui.xtable.PropertyGroupModel;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.actions.ChangeNameAction;
+import com.fr.design.designer.beans.events.DesignerEditor;
+import com.fr.design.designer.creator.CRPropertyDescriptor;
+import com.fr.design.designer.creator.XButton;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.form.ui.Button;
+import com.fr.form.ui.Widget;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.stable.StringUtils;
+import com.fr.stable.core.PropertyChangeAdapter;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class CompositeComponentAdapter implements ComponentAdapter {
+
+ protected FormDesigner designer;
+ protected DesignerEditor extends JComponent> editorComponent;
+ protected XCreator xCreator;
+
+ public CompositeComponentAdapter(FormDesigner designer, Component c) {
+ this.designer = designer;
+ this.xCreator = (XCreator) c;
+ }
+ /**
+ * 实例化组件的适配器后,在这儿进行初始化
+ */
+ public void initialize() {
+ initButtonText();
+ Dimension initialSize = xCreator.getPreferredSize();
+ xCreator.setSize(initialSize);
+ LayoutUtils.layoutContainer(xCreator);
+ }
+
+ private void initButtonText() {
+ Widget widget = xCreator.toData();
+ if (xCreator instanceof XButton && StringUtils.isEmpty(((Button) widget).getText())) {
+ ((Button) xCreator.toData()).setText(widget.getWidgetName());
+ ((XButton) xCreator).setButtonText(widget.getWidgetName());
+ }
+ }
+
+ @Override
+ public void paintComponentMascot(Graphics g) {
+ //自适应交叉点渲染有点问题,拖拽的控件设置成半透明
+ Graphics2D g2d = (Graphics2D) g;
+ AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.5f);
+ g2d.setComposite(composite);
+ xCreator.paint(g2d);
+ g.setColor(XCreatorConstants.RESIZE_BOX_BORDER_COLOR);
+ g.drawRect(0, 0, xCreator.getWidth() - 1, xCreator.getHeight() - 1);
+ }
+
+ @Override
+ public JPopupMenu getContextPopupMenu(MouseEvent e) {
+ JPopupMenu popupMenu = new JPopupMenu();
+ if (changeVarNameAction == null) {
+ changeVarNameAction = new ChangeNameAction(designer);
+ }
+ //底层布局或者是自适应布局都不能删除
+ boolean isRootComponent = ComponentUtils.isRootComponent(xCreator) || designer.isRoot(xCreator);
+ changeVarNameAction.setEnabled(!isRootComponent);
+ popupMenu.add(changeVarNameAction);
+
+ Action[] actions = designer.getActions();
+ for (Action action : actions) {
+ action.setEnabled(!designer.isRootRelatedAction(((UpdateAction)action).getName()) || !isRootComponent);
+ popupMenu.add(action);
+ }
+ return popupMenu;
+ }
+
+ private ChangeNameAction changeVarNameAction;
+
+ private ArrayList createPropertyGroupModels(CRPropertyDescriptor[] properties) {
+ HashMap> maps = new HashMap>();
+ ArrayList groupNames = new ArrayList();
+ for (CRPropertyDescriptor property : properties) {
+ String groupName = (String) property.getValue(XCreatorConstants.PROPERTY_CATEGORY);
+ if (StringUtils.isEmpty(groupName)) {
+ groupName = XCreatorConstants.DEFAULT_GROUP_NAME;
+ }
+ ArrayList groupProperties = maps.get(groupName);
+ if (groupProperties == null) {
+ groupProperties = new ArrayList();
+ maps.put(groupName, groupProperties);
+ groupNames.add(groupName);
+ }
+ groupProperties.add(property);
+ }
+ ArrayList groups = new ArrayList();
+ for (String groupName : groupNames) {
+ ArrayList groupProperties = maps.get(groupName);
+ PropertyGroupModel groupModel = new PropertyGroupModel(groupName, xCreator, groupProperties
+ .toArray(new CRPropertyDescriptor[0]), designer);
+ groups.add(groupModel);
+ }
+ return groups;
+ }
+
+ @Override
+ public ArrayList getXCreatorPropertyModel() {
+ ArrayList groupModels = new ArrayList();
+ CRPropertyDescriptor[] properties;
+ properties = getCalculateCreatorProperties();
+ ArrayList groups = createPropertyGroupModels(properties);
+ Collections.sort(groups);
+ groupModels.addAll(groups);
+ return groupModels;
+ }
+
+ /**
+ * 自适应布局中放置文本框等用的scaleLayout和报表块、图表块支持的标题控件用的titleLayout时
+ * 控件树处只显示父容器,但是控件属性还是为自身的
+ * @return
+ */
+ private CRPropertyDescriptor[] getCalculateCreatorProperties() {
+ try {
+ return xCreator.getPropertyDescriptorCreator().supportedDescriptor();
+ } catch (IntrospectionException ex) {
+ FRContext.getLogger().error(ex.getMessage(), ex);
+ return new CRPropertyDescriptor[0];
+ }
+ }
+
+ @Override
+ public DesignerEditor extends JComponent> getDesignerEditor() {
+ if (editorComponent == null) {
+ editorComponent = xCreator.getDesignerEditor();
+ if (editorComponent != null) {
+ editorComponent.addPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ designer.fireTargetModified();
+ }
+ });
+ }
+ }
+ if (editorComponent != null) {
+ editorComponent.reset();
+ }
+ return editorComponent;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbsoluteLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbsoluteLayoutAdapter.java
new file mode 100644
index 000000000..16d8a3147
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbsoluteLayoutAdapter.java
@@ -0,0 +1,33 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class AbsoluteLayoutAdapter extends AbstractLayoutAdapter {
+
+ public AbsoluteLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return true;
+ }
+
+ @Override
+ public void addComp(XCreator creator, int x, int y) {
+ int w = creator.getWidth() / 2;
+ int h = creator.getHeight() / 2;
+ creator.setLocation(x - w, y - h);
+ container.add(creator);
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ @Override
+ public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractAnchorPainter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractAnchorPainter.java
new file mode 100644
index 000000000..89f2a91e0
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractAnchorPainter.java
@@ -0,0 +1,41 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+
+import com.fr.design.designer.beans.Painter;
+import com.fr.design.form.util.XCreatorConstants;
+
+public abstract class AbstractAnchorPainter implements Painter {
+
+ protected Container container;
+ protected Rectangle hotspot;
+
+ public AbstractAnchorPainter(Container container) {
+ this.container = container;
+ }
+
+ @Override
+ public void setRenderingBounds(Rectangle rect) {
+ this.hotspot = rect;
+ }
+
+ protected void drawHotspot(Graphics g, Rectangle box, Color bColor) {
+ drawHotspot(g, box.x, box.y, box.width, box.height, bColor);
+ }
+
+ protected void drawHotspot(Graphics g, int x, int y, int width, int height, Color bColor) {
+ Graphics2D g2d = (Graphics2D) g;
+ Stroke backup = g2d.getStroke();
+ g2d.setStroke(XCreatorConstants.STROKE);
+ Color color = g2d.getColor();
+ g2d.setColor(bColor);
+ g2d.drawRect(x, y, width, height);
+ g2d.setColor(color);
+ g2d.setStroke(backup);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java
new file mode 100644
index 000000000..d5232d26a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java
@@ -0,0 +1,174 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.LayoutManager;
+
+import com.fr.general.ComparatorUtils;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.painters.NullPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public abstract class AbstractLayoutAdapter implements LayoutAdapter {
+
+ protected XLayoutContainer container;
+ protected LayoutManager layout;
+
+ public AbstractLayoutAdapter(XLayoutContainer container) {
+ this.container = container;
+ this.layout = container.getLayout();
+ }
+
+ /**
+ * 是否使用控件备份大小
+ * @param xCreator 控件
+ * @return 所在容器相同,且支持备份的话返回true
+ */
+ public boolean whetherUseBackupSize(XCreator xCreator) {
+ Class clazz = container.getClass();
+ Class bkClazz = null;
+ if(xCreator.getBackupParent() != null) {
+ bkClazz = xCreator.getBackupParent().getClass();
+ }
+ return ComparatorUtils.equals(bkClazz, clazz)
+ && supportBackupSize();
+ }
+
+ /**
+ * 是否支持用备份大小
+ * @return 否
+ */
+ public boolean supportBackupSize() {
+ return false;
+ }
+
+ /**
+ * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下
+ * @param creator 组件
+ */
+ public void fix(XCreator creator) {
+ }
+
+ /**
+ * 显示parent的字组件child,解决CardLayout中显示某个非显示组件的特殊情况
+ * @param child 组件
+ */
+ @Override
+ public void showComponent(XCreator child) {
+ child.setVisible(true);
+ }
+
+ /**
+ * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的
+ * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。
+ * @param creator 被添加的新组件
+ * @param x 添加的位置x,该位置是相对于container的
+ * @param y 添加的位置y,该位置是相对于container的
+ * @return 是否添加成功,成功返回true,否则false
+ */
+ @Override
+ public boolean addBean(XCreator creator, int x, int y) {
+ if (!accept(creator, x, y)) {
+ return false;
+ }
+ addComp(creator, x, y);
+ ((XWidgetCreator) creator).recalculateChildrenSize();
+ return true;
+ }
+
+ /**
+ * 删除组件
+ * @param creator 组件
+ * @param initWidth 组件之前宽度
+ * @param initHeight 组件之前高度
+ */
+ public void removeBean(XCreator creator, int creatorWidth, int creatorHeight) {
+ delete(creator, creatorWidth, creatorHeight);
+ }
+
+ protected void delete(XCreator creator, int creatorWidth, int creatorHeight) {
+ }
+
+ protected abstract void addComp(XCreator creator, int x, int y);
+
+ /**
+ * 增加下一个组件
+ * @param dragged 组件
+ */
+ @Override
+ public void addNextComponent(XCreator dragged) {
+ container.add(dragged);
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 目标控件位置插入组件
+ * @param target 目标
+ * @param added 增加组件
+ */
+ @Override
+ public void addBefore(XCreator target, XCreator added) {
+ int index = ComponentUtils.indexOfComponent(container, target);
+
+ if (index == -1) {
+ container.add(added, 0);
+ } else {
+ container.add(added, index);
+ }
+
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 插在目标组件后面
+ * @param target 目标
+ * @param added 增加组件
+ */
+ @Override
+ public void addAfter(XCreator target, XCreator added) {
+ int index = ComponentUtils.indexOfComponent(container, target);
+
+ if (index == -1) {
+ container.add(added);
+ } else {
+ index++;
+
+ if (index >= container.getComponentCount()) {
+ container.add(added);
+ } else {
+ container.add(added, index);
+ }
+ }
+
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ @Override
+ public HoverPainter getPainter() {
+ return new NullPainter(container);
+ }
+
+ /**
+ * 是否能接收更多的组件
+ * @return 能则返回true
+ */
+ @Override
+ public boolean canAcceptMoreComponent() {
+ return true;
+ }
+
+ @Override
+ public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
+ return null;
+ }
+
+ @Override
+ public GroupModel getLayoutProperties() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/DefaultLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/DefaultLayoutAdapter.java
new file mode 100644
index 000000000..bbf4b250c
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/DefaultLayoutAdapter.java
@@ -0,0 +1,29 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+
+public class DefaultLayoutAdapter extends AbstractLayoutAdapter {
+
+ public DefaultLayoutAdapter(FormDesigner designer, XLayoutContainer c) {
+ super(c);
+ }
+
+ @Override
+ public HoverPainter getPainter() {
+ return null;
+ }
+
+ @Override
+ public void addComp(XCreator child, int x, int y) {
+
+ }
+
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java
new file mode 100644
index 000000000..dadfed504
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java
@@ -0,0 +1,90 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.Rectangle;
+
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWAbsoluteLayout;
+import com.fr.design.designer.properties.BoundsGroupModel;
+import com.fr.form.ui.container.WAbsoluteLayout;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class FRAbsoluteLayoutAdapter extends AbstractLayoutAdapter {
+
+ public FRAbsoluteLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 是否能在指定位置添加组件
+ * @param creator 组件
+ * @param x 坐标x
+ * @param y 坐标y
+ * @return 能则返回true
+ */
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return x >= 0 && y >= 0 && creator.getHeight() <= container.getHeight()
+ && creator.getWidth() <= container.getWidth();
+ }
+
+ @Override
+ protected void addComp(XCreator creator, int x, int y) {
+ if (XCreatorUtils.getParentXLayoutContainer(creator) != null) {
+ Rectangle r = ComponentUtils.getRelativeBounds(container);
+ Rectangle creatorRectangle = ComponentUtils.getRelativeBounds(creator);
+ x = creatorRectangle.x - r.x;
+ y = creatorRectangle.y - r.y;
+ } else {
+ int w = creator.getWidth() / 2;
+ int h = creator.getHeight() / 2;
+ x = x - w;
+ y = y - h;
+ }
+
+ fix(creator, x, y);
+ container.add(creator);
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 组件拖拽后调整大小
+ * @param creator 组件
+ */
+ @Override
+ public void fix(XCreator creator) {
+ WAbsoluteLayout wabs = (WAbsoluteLayout)container.toData();
+ fix(creator,creator.getX(),creator.getY());
+ wabs.setBounds(creator.toData(),creator.getBounds());
+ }
+
+ /**
+ * 调整组件大小到合适尺寸位置
+ * @param creator 组件
+ * @param x 坐标x
+ * @param y 坐标y
+ */
+ public void fix(XCreator creator ,int x, int y) {
+ if (x < 0) {
+ x = 0;
+ } else if (x + creator.getWidth() > container.getWidth()) {
+ x = container.getWidth() - creator.getWidth();
+ }
+
+ if (y < 0) {
+ y = 0;
+ } else if (y + creator.getHeight() > container.getHeight()) {
+ y = container.getHeight() - creator.getHeight();
+ }
+
+ creator.setLocation(x, y);
+ }
+
+ @Override
+ public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
+ return new BoundsGroupModel((XWAbsoluteLayout)container, creator);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRBorderLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRBorderLayoutAdapter.java
new file mode 100644
index 000000000..a819090ff
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRBorderLayoutAdapter.java
@@ -0,0 +1,188 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+
+import com.fr.general.ComparatorUtils;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.painters.FRBorderLayoutPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.designer.properties.FRBorderLayoutConstraints;
+import com.fr.design.form.layout.FRBorderLayout;
+import com.fr.form.ui.container.WBorderLayout;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class FRBorderLayoutAdapter extends AbstractLayoutAdapter {
+
+ private HoverPainter painter;
+
+ public FRBorderLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ painter = new FRBorderLayoutPainter(container);
+ }
+
+ @Override
+ public HoverPainter getPainter() {
+ return painter;
+ }
+
+ /**
+ * 有的控件在拖拽调整大小后需要根据自身内容重新计算下当前的尺寸是否合适,如果不合适,就需要重新fix一下
+ * @param creator 组件
+ */
+ public void fix(XCreator creator) {
+ FRBorderLayout layout = (FRBorderLayout)container.getFRLayout();
+ Object constraints = layout.getConstraints(creator);
+ if (ComparatorUtils.equals(constraints, BorderLayout.NORTH)) {
+ ((XWBorderLayout)container).toData().setNorthSize(creator.getHeight());
+ } else if (ComparatorUtils.equals(constraints, BorderLayout.SOUTH)) {
+ ((XWBorderLayout)container).toData().setSouthSize(creator.getHeight());
+ } else if (ComparatorUtils.equals(constraints, BorderLayout.EAST)) {
+ ((XWBorderLayout)container).toData().setEastSize(creator.getWidth());
+ } else if (ComparatorUtils.equals(constraints, BorderLayout.WEST)) {
+ ((XWBorderLayout)container).toData().setWestSize(creator.getWidth());
+ } else {
+ return;
+ }
+ container.recalculateChildrenPreferredSize();
+ }
+
+ /**
+ * 增加组件
+ * @param child 组件
+ * @param x 横坐标
+ * @param y 纵坐标
+ */
+ public void addComp(XCreator child, int x, int y) {
+ String placement = getPlacement(child, x, y);
+ container.add(child, placement);
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 在添加组件状态时,当鼠标移动到某个容器上方时,如果该容器有布局管理器,则会调用该布局
+ * 管理适配器的accept来决定当前位置是否可以放置,并提供特殊的标识,比如红色区域标识。比
+ * 如在BorderLayout中,如果某个方位已经放置了组件,则此时应该返回false标识该区域不可以
+ * 放置。
+ *@param creator 组件
+ *@param x 添加的位置x,该位置是相对于container的
+ *@param y 添加的位置y,该位置是相对于container的
+ *@return 是否可以放置
+ */
+ public boolean accept(XCreator creator, int x, int y) {
+ String placement = getPlacement(creator, x, y);
+ FRBorderLayout blayout = (FRBorderLayout) container.getLayout();
+ Component comp = blayout.getLayoutComponent(placement);
+ return comp == null;
+ }
+
+ public Dimension getPreferredSize(XCreator creator) {
+ int hw = container.getWidth();
+ int hh = container.getHeight();
+
+ Dimension prefSize = creator.getSize();
+
+ if (prefSize.width > (hw / 3)) {
+ prefSize.width = hw / 3;
+ }
+
+ if (prefSize.height > (hh / 3)) {
+ prefSize.height = hh / 3;
+ }
+
+ return prefSize;
+ }
+
+ private String getPlacement(XCreator creator, int x, int y) {
+ int width = container.getWidth();
+ int height = container.getHeight();
+ WBorderLayout wLayout = ((XWBorderLayout)container).toData();
+ int northSize = wLayout.getNorthSize();
+ int southSize = wLayout.getSouthSize();
+ int eastSize = wLayout.getEastSize();
+ int westSize = wLayout.getWestSize();
+ if (y < northSize) {
+ return BorderLayout.NORTH;
+ } else if ((y >= northSize) && (y < (height - southSize))) {
+ if (x < westSize) {
+ return BorderLayout.WEST;
+ } else if ((x >= westSize) && (x < (width - eastSize))) {
+ return BorderLayout.CENTER;
+ } else {
+ return BorderLayout.EAST;
+ }
+ } else {
+ return BorderLayout.SOUTH;
+ }
+ }
+
+ /**
+ * 增加下一个组件
+ * @param dragged 组件
+ */
+ public void addNextComponent(XCreator dragged) {
+ FRBorderLayout layout = (FRBorderLayout) container.getLayout();
+ Component north = layout.getLayoutComponent(BorderLayout.NORTH);
+ Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
+ Component west = layout.getLayoutComponent(BorderLayout.WEST);
+ Component east = layout.getLayoutComponent(BorderLayout.EAST);
+ Component center = layout.getLayoutComponent(BorderLayout.CENTER);
+
+ if (north == null) {
+ container.add(dragged, BorderLayout.NORTH);
+ } else if (south == null) {
+ container.add(dragged, BorderLayout.SOUTH);
+ } else if (west == null) {
+ container.add(dragged, BorderLayout.WEST);
+ } else if (east == null) {
+ container.add(dragged, BorderLayout.EAST);
+ } else if (center == null) {
+ container.add(dragged, BorderLayout.CENTER);
+ }
+
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 目标控件位置插入组件
+ * @param target 目标
+ * @param added 增加组件
+ */
+ public void addBefore(XCreator target, XCreator added) {
+ addNextComponent(added);
+ }
+
+ /**
+ * 插在目标组件后面
+ * @param target 目标
+ * @param added 增加组件
+ */
+ public void addAfter(XCreator target, XCreator added) {
+ addNextComponent(added);
+ }
+
+ /**
+ * 是否能接收更多的组件
+ * @return 能则返回true
+ */
+ public boolean canAcceptMoreComponent() {
+ FRBorderLayout layout = (FRBorderLayout) container.getLayout();
+ Component north = layout.getLayoutComponent(BorderLayout.NORTH);
+ Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
+ Component west = layout.getLayoutComponent(BorderLayout.WEST);
+ Component east = layout.getLayoutComponent(BorderLayout.EAST);
+ Component center = layout.getLayoutComponent(BorderLayout.CENTER);
+
+ return (north == null) || (south == null) || (west == null) || (east == null) || (center == null);
+ }
+
+ @Override
+ public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
+ return new FRBorderLayoutConstraints(container, creator);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRCardLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRCardLayoutAdapter.java
new file mode 100644
index 000000000..031b933ad
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRCardLayoutAdapter.java
@@ -0,0 +1,141 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.CardLayout;
+import java.awt.LayoutManager;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+import com.fr.design.designer.properties.CardLayoutConstraints;
+import com.fr.design.designer.properties.CardLayoutPropertiesGroupModel;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class FRCardLayoutAdapter extends AbstractLayoutAdapter {
+
+ public FRCardLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 当前容器是否接受组件creator
+ *
+ * @param creator 拖入的组件
+ * @param x 坐标x
+ * @param y 坐标y
+ *
+ * @return 是否接受
+ *
+ *
+ * @date 2014-12-30-下午5:13:28
+ *
+ */
+ public boolean accept(XCreator creator, int x, int y) {
+ return true;
+ }
+
+ /**
+ * 将指定组件添加到当前布局
+ *
+ * @param creator 待添加组件
+ * @param x x坐标
+ * @param y y坐标
+ *
+ *
+ * @date 2014-12-30-下午5:17:46
+ *
+ */
+ public void addComp(XCreator creator, int x, int y) {
+ container.add(creator, creator.toData().getWidgetName());
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 将指定组件添加到当前布局
+ *
+ * @param dragged 待添加组件
+ *
+ *
+ * @date 2014-12-30-下午5:17:46
+ *
+ */
+ public void addNextComponent(XCreator dragged) {
+ addComp(dragged, -1, -1);
+ }
+
+ /**
+ * 将指定组件添加到目标组件前面
+ *
+ * @param target 目标组件
+ * @param added 待添加组件
+ *
+ *
+ * @date 2014-12-30-下午5:17:46
+ *
+ */
+ public void addBefore(XCreator target, XCreator added) {
+ int index = ComponentUtils.indexOfComponent(container, target);
+
+ if (index == -1) {
+ container.add(added, added.toData().getWidgetName(), 0);
+ } else {
+ container.add(added, added.toData().getWidgetName(), index);
+ }
+
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 将指定组件添加到目标组件后面
+ *
+ * @param target 目标组件
+ * @param added 待添加组件
+ *
+ *
+ * @date 2014-12-30-下午5:17:46
+ *
+ */
+ public void addAfter(XCreator target, XCreator added) {
+ int index = ComponentUtils.indexOfComponent(container, target);
+
+ if (index == -1) {
+ container.add(added, added.toData().getWidgetName());
+ } else {
+ index++;
+
+ if (index >= container.getComponentCount()) {
+ container.add(added, added.toData().getWidgetName());
+ } else {
+ container.add(added, added.toData().getWidgetName(), index);
+ }
+ }
+
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ /**
+ * 展示组件
+ *
+ * @param child 需要展示的组件
+ *
+ *
+ * @date 2014-12-30-下午5:17:13
+ *
+ */
+ public void showComponent(XCreator child) {
+ LayoutManager layout = container.getLayout();
+ CardLayout cardLayout = (CardLayout) layout;
+ cardLayout.show(container, child.toData().getWidgetName());
+ }
+
+ @Override
+ public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
+ return new CardLayoutConstraints((XWCardLayout) container, creator);
+ }
+ @Override
+ public GroupModel getLayoutProperties() {
+ return new CardLayoutPropertiesGroupModel((XWCardLayout) container);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java
new file mode 100644
index 000000000..1e052ba6d
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java
@@ -0,0 +1,2129 @@
+/**
+ *
+ */
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.painters.FRFitLayoutPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWFitLayout;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
+import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
+import com.fr.design.designer.properties.FRFitLayoutConstraints;
+import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel;
+import com.fr.design.file.HistoryTemplateListPane;
+import com.fr.design.mainframe.JForm;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.form.ui.LayoutBorderStyle;
+import com.fr.form.ui.PaddingMargin;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+import com.fr.form.ui.container.WLayout;
+import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
+import com.fr.general.ComparatorUtils;
+
+/**
+ * 自适应布局的容器适配器
+ *
+ * @author jim
+ * @date 2014-6-24
+ */
+public class FRFitLayoutAdapter extends AbstractLayoutAdapter {
+
+ public static final String WIDGETPANEICONPATH="/com/fr/web/images/form/resources/layout_absolute.png";
+
+ private static final double TOP_HALF = 0.25;
+ private static final double BOTTOM_HALF = 0.75;
+ private static final int DEFAULT_AREA_LENGTH = 5; //判断交叉区域范围的默认长度
+ private static final int BORDER_PROPORTION = 10; //边界三等分或交叉区域大小取组件1/10和默认大小
+ private static final int COMP_TOP = 1;
+ private static final int COMP_BOTTOM = 2;
+ private static final int COMP_LEFT = 3;
+ private static final int COMP_RIGHT = 4;
+ private static final int COMP_LEFT_TOP = 5;
+ private static final int COMP_LEFT_BOTTOM = 6;
+ private static final int COMP_RIGHT_TOP = 7;
+ private static final int COMP_RIGHT_BOTTOM = 8;
+ private static final int INDEX_ZERO = 0;
+
+ private static final int DEPENDING_SCOPE = 3;
+
+ private int trisectAreaDirect = 0;
+ private int crossPointAreaDirect = 0;
+ // 增加删除拉伸控件用的临时list
+ private List rightComps;
+ private List leftComps;
+ private List downComps;
+ private List upComps;
+ // 三等分时计算对应侧的组件
+ private boolean isFindRelatedComps = false;
+ // 渲染时只计算对应的bounds而不调整
+ private boolean isCalculateChildPos = false;
+ private int[] childPosition = null; //painter用的位置
+ private HoverPainter painter;
+ private int minWidth = 0; // 最小尺寸,由于屏幕百分比里不同,显示的最小大小也不同
+ private int minHeight = 0;
+ private int actualVal = 0; // 存在间隔时,add move drag 判断对齐等都要考虑
+ private PaddingMargin margin; // 布局容器边距
+
+ /**
+ * 构造函数
+ * @param container XWFitLayout容器
+ */
+ public FRFitLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ painter = new FRFitLayoutPainter(container);
+ initMinSize();
+ }
+
+ private void initMinSize() {
+ XWFitLayout layout = (XWFitLayout) container;
+ minWidth = layout.getActualMinWidth();
+ minHeight = layout.getActualMinHeight();
+ actualVal = layout.getAcualInterval();
+ margin = layout.toData().getMargin();
+ }
+
+ @Override
+ public HoverPainter getPainter() {
+ return painter;
+ }
+
+ /**
+ * 返回布局自身属性,方便一些特有设置在layout刷新时处理
+ */
+ @Override
+ public GroupModel getLayoutProperties() {
+ XWFitLayout xfl = (XWFitLayout) container;
+ return new FRFitLayoutPropertiesGroupModel(xfl);
+ }
+
+ /**
+ * 添加组件
+ *
+ * @param child 待添加的组件
+ *@param x 坐标x
+ *@param y 坐标y
+ */
+ @Override
+ public void addComp(XCreator child, int x, int y) {
+ if (ComparatorUtils.equals(child.getIconPath(), WIDGETPANEICONPATH)) {
+ return;
+ }
+ fix(child, x, y);
+ if (child.shouldScaleCreator() || child.hasTitleStyle()) {
+ addParentCreator(child);
+ } else {
+ container.add(child, child.toData().getWidgetName());
+ }
+ XWFitLayout layout = (XWFitLayout) container;
+ // 更新对应的BoundsWidget
+ layout.updateBoundsWidget();
+ updateCreatorBackBound();
+ }
+
+ private void updateCreatorBackBound() {
+ for (int i=0,size=container.getComponentCount(); i= minWidth * 2 + actualVal;
+ boolean verticalValid = componentHeight >= minHeight * 2 + actualVal;
+ return y > upHeight && y < downHeight ? horizonValid : verticalValid;
+ }
+
+ // 间隔区域
+ private boolean checkInterval(Component comp){
+ return container.getComponentCount()>0 && comp == container;
+ }
+
+ /**
+ * 是否在组件边缘
+ * @param x 横坐标
+ * @param y 纵坐标
+ * @return 是否在组件边缘
+ */
+ public boolean matchEdge(int x, int y){
+ if(intersectsEdge(x, y,container)){
+ //寻找最近的fit, 在边缘地段添加的控件, 将其送给该fit
+ XLayoutContainer parent = container.findNearestFit();
+ container = parent != null ? parent : container;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 是否在组件边缘
+ * @param x 横坐标
+ * @param y 纵坐标
+ * @param container 参照组件
+ * @return 是否在组件边缘
+ */
+ //是否包含于边缘地段, 按顺序上, 下, 左, 右检测
+ public boolean intersectsEdge(int x, int y,XLayoutContainer container) {
+ int containerX = container.getX();
+ int containerY = container.getY();
+ int containerWidth = container.getWidth();
+ int containerHeight = container.getHeight();
+
+ // 当前坐标点
+ Rectangle currentXY = new Rectangle(x, y, 1, 1);
+ // 上边缘
+ Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION);
+ if(upEdge.intersects(currentXY)){
+ return true;
+ }
+
+ int bottomY = containerY + containerHeight - BORDER_PROPORTION;
+ // 下边缘
+ Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION);
+ if(bottomEdge.intersects(currentXY)){
+ return true;
+ }
+
+ //左右边缘的高度 -10*2 是为了不和上下边缘重合
+ int verticalHeight = containerHeight - BORDER_PROPORTION * 2;
+ int leftY = containerY + BORDER_PROPORTION;
+ // 左边缘
+ Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight);
+ if(leftEdge.intersects(currentXY)){
+ return true;
+ }
+
+ int rightY = containerY + BORDER_PROPORTION;
+ int rightX = containerX + containerWidth - BORDER_PROPORTION;
+ // 右边缘
+ Rectangle rightEdge = new Rectangle(rightX, rightY, BORDER_PROPORTION, verticalHeight);
+ return rightEdge.intersects(currentXY);
+ }
+
+ /**
+ * 交叉点区域时,能否对应位置放入组件
+ */
+ private boolean canAcceptWhileCrossPoint(Component comp, int x, int y) {
+ int cX = comp.getX(), cY = comp.getY(), cH = comp.getHeight(), cW = comp.getWidth();
+ Component topComp = container.getTopComp(cX, cY);
+ Component bottomComp = container.getBottomComp(cX, cY, cH);
+ Component rightComp = container.getRightComp(cX, cY, cW);
+ Component leftComp = container.getLeftComp(cX, cY);
+ int minLength = 0, min = minHeight*2;
+ boolean isNotDefaultArea = false;
+ if (ComparatorUtils.equals(crossPointAreaDirect, COMP_LEFT_TOP)) {
+ isNotDefaultArea = topComp==null || topComp.getX() != cX;
+ minLength = isNotDefaultArea ? Math.min(cH, leftComp.getHeight()) : Math.min(cW, topComp.getWidth());
+ min = isNotDefaultArea ? min : minWidth*2;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_RIGHT_BOTTOM)) {
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ isNotDefaultArea = bottomComp==null || (bottomComp.getX()+bottomComp.getWidth() != cX+cW) ;
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ minLength = isNotDefaultArea ? Math.min(cH, rightComp.getHeight()) : Math.min(cW, bottomComp.getWidth());
+ min = isNotDefaultArea ? min : minWidth*2;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_LEFT_BOTTOM)) {
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ isNotDefaultArea = leftComp==null || (leftComp.getY()+leftComp.getHeight() != cY+cH);
+ minLength = isNotDefaultArea ? Math.min(cW, bottomComp.getWidth()) : Math.min(cH, leftComp.getHeight());
+ min = isNotDefaultArea ? minWidth*2 : min ;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_RIGHT_TOP)) {
+ isNotDefaultArea = rightComp==null || (rightComp.getY() != cY) ;
+ topComp = container.getRightTopComp(cX, cY, cW);
+ minLength = isNotDefaultArea ? Math.min(cW, topComp.getWidth()) : Math.min(cH, rightComp.getWidth());
+ min = isNotDefaultArea ? minWidth*2 : min ;
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_TOP)) {
+ minLength= Math.min(rightComp.getHeight(), Math.min(cH, leftComp.getHeight()));
+ } else if (ComparatorUtils.equals(crossPointAreaDirect, COMP_BOTTOM)) {
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ minLength= Math.min(rightComp.getHeight(), Math.min(cH, leftComp.getHeight()));
+ } else {
+ if (ComparatorUtils.equals(crossPointAreaDirect, COMP_RIGHT)) {
+ topComp = container.getRightTopComp(cX, cY, cW);
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ }
+ minLength = Math.min(topComp.getWidth(), Math.min(cW, bottomComp.getWidth()));
+ min = minWidth*2;
+ }
+ // 有间隔的话,要考虑容纳间隔
+ return minLength >= min+actualVal;
+ }
+
+ private boolean canAcceptWhileTrisection(Component comp, int x, int y) {
+ //符合三等分,实际区域不满足三等分的大小
+ int cX = comp.getX(), cY = comp.getY(), cH = comp.getHeight(), cW = comp.getWidth();
+ int upMinHeight = 0, downMinHeight = 0, leftMinWidth = 0, rightMinWidth = 0;
+ if (ComparatorUtils.equals(trisectAreaDirect, COMP_TOP)) {
+ upMinHeight = getUpMinHeightComp(cY, x);
+ downMinHeight = getDownMinHeightComp(comp, y);
+ return upMinHeight==0 ? downMinHeight>= minHeight*2+actualVal : (upMinHeight+downMinHeight)>= minHeight*3+actualVal;
+ } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_BOTTOM)) {
+ upMinHeight = getUpMinHeightComp(cY+cH+actualVal, x);
+ if (cY+cH+DEFAULT_AREA_LENGTH>container.getHeight() - margin.getBottom()){
+ downMinHeight = 0;
+ } else {
+ Component targetComp = container.getBottomComp(x, cY, cH);
+ downMinHeight = getDownMinHeightComp(targetComp, cY+cH+DEFAULT_AREA_LENGTH+actualVal);
+ }
+ return downMinHeight == 0 ? upMinHeight>= minHeight*2+actualVal : (upMinHeight+downMinHeight)>= minHeight*3+actualVal;
+ } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_LEFT)) {
+ rightMinWidth = getMinRightWidth(cX, 0, y);
+ if(cX-DEFAULT_AREA_LENGTH < margin.getLeft()) {
+ leftMinWidth = 0;
+ } else {
+ Component targetRightComp = container.getLeftComp(cX, y);
+ leftMinWidth = getMinLeftWidth(targetRightComp, cX-DEFAULT_AREA_LENGTH - actualVal);
+ }
+ return leftMinWidth==0 ? rightMinWidth>=minWidth*2+actualVal : (leftMinWidth+rightMinWidth)>= minWidth*3+actualVal;
+ } else if(ComparatorUtils.equals(trisectAreaDirect, COMP_RIGHT)) {
+ leftMinWidth = getMinLeftWidth(comp, x);
+ rightMinWidth = getMinRightWidth(cX, cW, y);
+ return rightMinWidth==0 ? leftMinWidth>=minWidth*2+actualVal : (leftMinWidth+rightMinWidth)>= minWidth*3+actualVal;
+ }
+ return false;
+ }
+
+ /**
+ * 返回当前组件所在y值上方的所有组件中最小高度,且保证这些控件是相邻不隔断的
+ * 判断对齐时考虑间隔
+ */
+ private int getUpMinHeightComp(int cY, int x) {
+ if (cY == margin.getTop()) {
+ return 0;
+ }
+ int max=container.getWidth() - margin.getRight();
+ int mouseX = x;
+ int minHeight = cY;
+ int bott = 0;
+ if (isFindRelatedComps) {
+ upComps = new ArrayList();
+ }
+ for(; mouseX margin.getLeft()) {
+ Component comp = container.getTopComp(mouseX, cY);
+ bott = comp.getHeight()+comp.getY()+actualVal;
+ if (bott == cY) {
+ if (comp.getHeight() < minHeight) {
+ minHeight = comp.getHeight();
+ }
+ mouseX = comp.getX()-DEFAULT_AREA_LENGTH-actualVal;
+ if (isFindRelatedComps) {
+ upComps.add(comp);
+ }
+ } else{
+ break;
+ }
+ }
+ return minHeight;
+ }
+
+ /**
+ * 返回和当前组件相同y坐标的所有组件中最小高度,且保证这些控件是相邻不隔断的
+ * 判断对齐时考虑间隔
+ */
+ private int getDownMinHeightComp(Component currentcomp, int y) {
+ int cX = currentcomp.getX();
+ int cY = currentcomp.getY();
+ int minHeight = currentcomp.getHeight();
+ int max=container.getWidth() - margin.getRight();
+ if (isFindRelatedComps) {
+ downComps = new ArrayList();
+ }
+ int mouseX = cX + DEFAULT_AREA_LENGTH;
+ while (mouseX < max) {
+ Component comp = container.getComponentAt(mouseX, y);
+ if (comp.getY()==cY) {
+ if (comp.getHeight() < minHeight) {
+ minHeight = comp.getHeight();
+ }
+ mouseX = comp.getX()+comp.getWidth()+DEFAULT_AREA_LENGTH + actualVal;
+ if (isFindRelatedComps) {
+ downComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ mouseX = cX - DEFAULT_AREA_LENGTH-actualVal;
+ while(mouseX > margin.getLeft()) {
+ Component comp = container.getComponentAt(mouseX, y);
+ if (comp.getY()==cY) {
+ if (comp.getHeight() < minHeight) {
+ minHeight = comp.getHeight();
+ }
+ mouseX = comp.getX() - DEFAULT_AREA_LENGTH - actualVal;
+ if (isFindRelatedComps) {
+ downComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ return minHeight;
+ }
+
+ /**
+ * 返回当前组件右侧相同x的所有组件中最小宽度,且保证这些控件是相邻不隔断的
+ * 判断对齐时考虑间隔
+ */
+ private int getMinRightWidth(int cX, int cW, int y) {
+ int xL = cX+DEFAULT_AREA_LENGTH ;
+ xL = cW==0 ? xL : xL+cW+actualVal;
+ if (xL>container.getWidth() - margin.getRight()){
+ return 0;
+ }
+ // 以当前组件紧挨着右侧的组件为基准,在y轴方向查找符合条件的组件
+ Component targetComp = container.getComponentAt(xL, y);
+ int minWidth = targetComp.getWidth();
+ int max=container.getHeight() - margin.getBottom();
+ if (isFindRelatedComps) {
+ rightComps = new ArrayList();
+ }
+ int mouseY = targetComp.getY() + DEFAULT_AREA_LENGTH;
+ while (mouseYmargin.getTop()) {
+ Component comp = container.getComponentAt(xL, mouseY);
+ if (comp.getX()==targetComp.getX()) {
+ if (comp.getWidth() < minWidth) {
+ minWidth = comp.getWidth();
+ }
+ mouseY = comp.getY() - DEFAULT_AREA_LENGTH - actualVal;
+ if (isFindRelatedComps) {
+ rightComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ return minWidth;
+ }
+
+ /**
+ * 返回当前组件垂直方向同侧的组件(组件右边界相连)中最小宽度
+ * 判断对齐时考虑间隔
+ */
+ private int getMinLeftWidth(Component currentComp, int x) {
+ int minWidth = currentComp.getWidth();
+ int compRightLength = currentComp.getX()+currentComp.getWidth();
+ int max=container.getHeight() - margin.getBottom();
+ if (isFindRelatedComps) {
+ leftComps = new ArrayList();
+ }
+ int rightx = 0;
+ int mouseY = currentComp.getY()+DEFAULT_AREA_LENGTH;
+ while(mouseYmargin.getTop()) {
+ Component comp = container.getComponentAt(x, mouseY);
+ rightx = comp.getX()+comp.getWidth();
+ if (rightx == compRightLength) {
+ if (comp.getWidth() < minWidth) {
+ minWidth = comp.getWidth();
+ }
+ mouseY = comp.getY() - DEFAULT_AREA_LENGTH - actualVal;
+ if (isFindRelatedComps) {
+ leftComps.add(comp);
+ }
+ }else{
+ break;
+ }
+ }
+ return minWidth;
+ }
+
+ /**
+ * 判断是否鼠标在组件的三等分区域,如果组件在布局管理器中间,上下左右都可能会三等分
+ * @param parentComp 鼠标所在区域的组件
+ * @param x 坐标x
+ * @param y 坐标y
+ * @return 是则返回true
+ */
+ public boolean isTrisectionArea(Component parentComp, int x, int y) {
+ XCreator creator = (XCreator)parentComp;
+ if (container.getComponentCount()<=1) {
+ return false;
+ }
+ int maxWidth = parentComp.getWidth();
+ int maxHeight = parentComp.getHeight();
+ int xL = parentComp.getX();
+ int yL = parentComp.getY();
+ // 组件宽高的十分之一和默认值取大
+ int minRangeWidth = Math.max(maxWidth/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
+ int minRangeHeight = Math.max(maxHeight/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
+ if(yyL+maxHeight-minRangeHeight) {
+ // 在组件下侧三等分
+ trisectAreaDirect = COMP_BOTTOM;
+ } else if (xxL+maxWidth-minRangeWidth) {
+ // 在组件右侧三等分
+ trisectAreaDirect = COMP_RIGHT;
+ }
+ // tab布局的边界特殊处理,不进行三等分
+ if(!creator.getTargetChildrenList().isEmpty()){
+ return false;
+ }
+
+ return !ComparatorUtils.equals(trisectAreaDirect, 0);
+ }
+
+ /**
+ * 是否为组件交叉点区域 或者是相邻三组建中间点
+ * @param currentComp 当前组件
+ * @param x 坐标x
+ * @param y 坐标y
+ * @return 是则返回true
+ */
+ public boolean isCrossPointArea(Component currentComp, int x, int y) {
+ // 3个及以上都会出现交叉点区域(包括边界处的)
+ if(currentComp == null || container.getComponentCount() <= 2){
+ return false;
+ }
+ int cX = currentComp.getX();
+ int cY = currentComp.getY();
+ int cW = currentComp.getWidth();
+ int cH = currentComp.getHeight();
+ int areaWidth = Math.max(cW/BORDER_PROPORTION ,DEFAULT_AREA_LENGTH);
+ int areaHeight = Math.max(cH/BORDER_PROPORTION, DEFAULT_AREA_LENGTH);
+ int rx = cX + cW;
+ int by = cY + cH;
+ int objX = cX + areaWidth;
+ int objY = cY + areaHeight;
+ int containerW = container.getWidth() - margin.getRight();
+ int containerH = container.getHeight() - margin.getBottom();
+ if (x margin.getTop() || cX > margin.getLeft() ? COMP_LEFT_TOP : 0;
+ } else if (yrx-areaWidth){
+ //右上角
+ crossPointAreaDirect = cY>margin.getTop() || rx < containerW ? COMP_RIGHT_TOP : 0;
+ } else if (xby-areaHeight) {
+ //左下角
+ crossPointAreaDirect = cX>margin.getLeft() || byrx-areaWidth && y>by-areaHeight) {
+ //右下角
+ crossPointAreaDirect = bycX+cW/2-areaWidth && x cY + cH - areaHeight) {
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ if (leftComp!=null && rightComp!=null) {
+ isCrosspoint = leftComp.getY()+leftComp.getHeight() == cY + cH && rightComp.getY()+rightComp.getHeight()== cY + cH;
+ }
+ crossPointAreaDirect = isCrosspoint ? COMP_BOTTOM : 0;
+ }
+ } else if (y>cY+cH/2-areaHeight && y cX+cW-areaWidth) {
+ topComp = container.getRightTopComp(cX, cY, cW);
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ if (topComp!=null && bottomComp!=null) {
+ isCrosspoint = topComp.getX()+topComp.getWidth()==cX+cW && bottomComp.getX()+bottomComp.getWidth()== cX+cW;
+ }
+ crossPointAreaDirect = isCrosspoint ? COMP_RIGHT : 0;
+ }
+ }
+ }
+
+ private void initCompsList() {
+ rightComps = new ArrayList();
+ leftComps = new ArrayList();
+ upComps = new ArrayList();
+ downComps = new ArrayList();
+ }
+
+ private void clearCompsList() {
+ rightComps = null;
+ leftComps = null;
+ upComps = null;
+ downComps = null;
+ }
+ private Rectangle adjustBackupBound(Rectangle backupBound,XWCardMainBorderLayout mainLayout){
+ // 参数界面高度对纵坐标产生的影响
+ JForm jform = (JForm)(HistoryTemplateListPane.getInstance().getCurrentEditingTemplate());
+ if(jform.getFormDesign().getParaComponent()!= null){
+ backupBound.y -= jform.getFormDesign().getParaHeight();
+ }
+
+ Rectangle rec = mainLayout.getBounds();
+ // XWTabLayout里面的横纵坐标收到外层XWCardMainBorderLayout的横纵坐标影响
+ // 减掉之后可以按照它原来的逻辑执行
+ backupBound.x -= rec.x;
+ backupBound.y -= rec.y;
+ XWCardLayout cardLayout = mainLayout.getCardPart();
+ LayoutBorderStyle style = cardLayout.toData().getBorderStyle();
+ // 当tab布局为标题样式时,才需要处理标题栏高度产生的影响
+ if(ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)){
+ backupBound.y -= WCardMainBorderLayout.TAB_HEIGHT;
+ }
+ return backupBound;
+ }
+
+ /**
+ * 拖拽控件边框后,根据控件的大小尺寸,进行相关组件的调整
+ * @param creator 组件
+ */
+ @Override
+ public void fix(XCreator creator) {
+ //拖拽组件原大小、位置
+ Rectangle backupBound = creator.getBackupBound();
+ backupBound.x -= container.getX();
+ backupBound.y -= container.getY();
+ //当前拖拽组件的位置
+ int x = creator.getX();
+ int y = creator.getY();
+
+ // 获取容器所有内部组件横坐标
+ int[] posXs = container.getHors();
+ // 获取容器所有内部组件纵坐标
+ int[] posYs = container.getVeris();
+
+ XLayoutContainer outerLayout = container.getOuterLayout();
+ if(!ComparatorUtils.equals(outerLayout, container.getBackupParent())){
+ XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout)outerLayout;
+ backupBound = adjustBackupBound(backupBound, mainLayout);
+ }
+
+ //拖拽组件拖拽以后的大小
+ int w = creator.getWidth();
+ int h = creator.getHeight();
+ initCompsList();
+ creator.setBounds(backupBound);
+ int difference = 0;
+ if (x!=backupBound.x) {
+ dealLeft(backupBound, x, posXs, difference, creator);
+ } else if(w!=backupBound.width) {
+ dealRight(backupBound, x, w, posXs, difference, creator);
+ } else if (y!=backupBound.y) {
+ dealTop(backupBound, y, posYs, difference, creator);
+ } else if (h!=backupBound.height) {
+ dealButtom(backupBound, y, h, posYs, difference, creator);
+ }
+ clearCompsList();
+ XWFitLayout layout = (XWFitLayout) container;
+ layout.updateBoundsWidget(); // 更新对应的BoundsWidget
+ updateCreatorBackBound();
+ }
+
+ private void dealLeft(Rectangle backupBound,int x,int[] posXs,int difference,XCreator creator){
+ if (backupBound.x == margin.getLeft()) {
+ return;
+ }
+ x = adjustCoordinateByDependingLine(x,posXs);
+ difference = x-backupBound.x;
+ dealDirectionAtLeft(backupBound, difference, creator);
+ }
+
+ private void dealRight(Rectangle backupBound,int x,int w,int[] posXs,int difference,XCreator creator){
+ if (backupBound.width+backupBound.x== container.getWidth() - margin.getRight()) {
+ return;
+ }
+ w = adjustDiffByDependingLine(x, posXs, w);
+ difference = w-backupBound.width; //拖拽长度
+ dealDirectionAtRight(backupBound, difference, creator);
+ }
+
+ private void dealTop(Rectangle backupBound,int y,int[] posYs,int difference,XCreator creator){
+ if (backupBound.y== margin.getTop()) {
+ return;
+ }
+ y = adjustCoordinateByDependingLine(y, posYs);
+ difference = y-backupBound.y;
+ dealDirectionAtTop(backupBound, difference, creator);
+ }
+
+ private void dealButtom(Rectangle backupBound,int y,int h,int[] posYs,int difference,XCreator creator){
+ if (backupBound.y+backupBound.height==container.getHeight() - margin.getBottom()) {
+ return;
+ }
+ h = adjustDiffByDependingLine(y, posYs, h);
+ difference = h-backupBound.height;
+ dealDirectionABottom(backupBound, difference, creator);
+ }
+
+ // 根据需要依附的位置调整拖拽的坐标值
+ private int adjustCoordinateByDependingLine(int coordinate,int[] coordinates){
+ for(int i=0; i coordinates[i]-DEPENDING_SCOPE && coordinate < coordinates[i] + DEPENDING_SCOPE){
+ coordinate = coordinates[i];
+ break;
+ }
+ }
+ return coordinate;
+ }
+
+ // 根据需要依附的位置调整拖拽的距离
+ private int adjustDiffByDependingLine(int coordinate,int[] coordinates,int diff){
+ for(int i=0; i coordinates[i]-DEPENDING_SCOPE && coordinate+diff < coordinates[i] + DEPENDING_SCOPE){
+ diff = coordinates[i] - coordinate;
+ break;
+ }
+ }
+ return diff;
+ }
+
+ // 左侧边框拉伸,循环找出对齐的两侧控件
+ private void dealDirectionAtLeft(Rectangle backupBound, int difference, Component creator) {
+ rightComps.add(creator);
+ Component rightComp = null;
+ int leftx = backupBound.x-DEFAULT_AREA_LENGTH - actualVal;
+ // 取左侧边框右面的组件x值
+ int rightx = backupBound.x+DEFAULT_AREA_LENGTH;
+ Component leftComp = container.getLeftComp(backupBound.x, backupBound.y);
+ leftComps.add(leftComp);
+ //先找上侧对齐时(y相等)的左右两边组件
+ int ry = backupBound.y;
+ int ly = leftComp.getY();
+ int min = margin.getTop();
+ int max = container.getHeight() - margin.getBottom();
+ while (ry>= min && ly>= min) {
+ if (ry == ly) {
+ break;
+ } else {
+ if (ry>ly) {
+ rightComp = container.getTopComp(rightx, ry);
+ ry = rightComp.getY();
+ rightComps.add(rightComp);
+ } else {
+ leftComp = container.getTopComp(leftx, ly);
+ ly = leftComp.getY();
+ leftComps.add(leftComp);
+ }
+ }
+ }
+ // 下侧对齐时(y+h相等)两边组件
+ ry = backupBound.y + backupBound.height ;
+ ly = leftComps.get(0).getY() + leftComps.get(0).getHeight();
+ while(ry<= max && ly<= max) {
+ if (ry==ly) {
+ break;
+ } else {
+ if (ry>ly) {
+ leftComp = container.getComponentAt(leftx, ly+DEFAULT_AREA_LENGTH+actualVal);
+ ly = leftComp.getY() + leftComp.getHeight();
+ leftComps.add(leftComp);
+ } else {
+ rightComp = container.getComponentAt(rightx, ry+DEFAULT_AREA_LENGTH+actualVal);
+ ry = rightComp.getY() + rightComp.getHeight();
+ rightComps.add(rightComp);
+ }
+ }
+ }
+ dealHorDirection(backupBound.x, difference);
+ }
+
+ // 右侧边框拉伸,循环找出对齐的两侧控件
+ private void dealDirectionAtRight(Rectangle backupBound, int difference, Component creator) {
+ leftComps.add(creator);
+ Component leftComp = null;
+ int leftx = backupBound.x+backupBound.width-DEFAULT_AREA_LENGTH;
+ // 取右侧边框右面的组件x值
+ int rightx = backupBound.x+backupBound.width+DEFAULT_AREA_LENGTH+actualVal;
+ Component rightComp = container.getRightComp(backupBound.x, backupBound.y, backupBound.width);
+ rightComps.add(rightComp);
+ int ly = backupBound.y, ry = rightComp.getY();
+ int min = margin.getTop();
+ int max = container.getHeight() - margin.getBottom();
+ while (ry>= min && ly>= min) {
+ if (ry == ly) {
+ break;
+ } else {
+ if (ry>ly) {
+ rightComp = container.getTopComp(rightx, ry);
+ ry = rightComp.getY();
+ rightComps.add(rightComp);
+ } else {
+ leftComp = container.getTopComp(leftx, ly);
+ ly = leftComp.getY();
+ leftComps.add(leftComp);
+ }
+ }
+ }
+ ly = backupBound.y + backupBound.height;
+ ry = rightComps.get(0).getY() + rightComps.get(0).getHeight();
+ while(ry<= max && ly<= max) {
+ if (ry==ly) {
+ break;
+ } else {
+ if (ry>ly) {
+ leftComp = container.getComponentAt(leftx, ly+DEFAULT_AREA_LENGTH+actualVal);
+ ly = leftComp.getY() + leftComp.getHeight();
+ leftComps.add(leftComp);
+ } else {
+ rightComp = container.getComponentAt(rightx, ry+DEFAULT_AREA_LENGTH+actualVal);
+ ry = rightComp.getY() + rightComp.getHeight();
+ rightComps.add(rightComp);
+ }
+ }
+ }
+ dealHorDirection(backupBound.x+backupBound.width+actualVal, difference);
+ }
+
+ /**
+ * 水平方向上拉伸边框的处理
+ */
+ private void dealHorDirection(int objx, int difference) {
+ if (difference>0) {
+ difference = Math.min(getMinWidth(rightComps)-minWidth, difference);
+ } else {
+ difference = Math.max(difference, minWidth-getMinWidth(leftComps));
+ }
+ //重新计算左右两侧组件size、point
+ if(CalculateLefttRelatComponent(difference)){
+ CalculateRightRelatComponent(objx+difference, -difference);
+ }
+ }
+
+ // 上侧边框拉伸,循环找出对齐的两侧控件
+ private void dealDirectionAtTop(Rectangle backupBound, int difference, Component creator) {
+ downComps.add(creator);
+ // 取上侧边框上面的组件用的y值
+ int topy = backupBound.y-DEFAULT_AREA_LENGTH - actualVal;
+ // 上侧边框下面的组件y值
+ int bottomy = backupBound.y+DEFAULT_AREA_LENGTH;
+ Component topComp = container.getTopComp(backupBound.x, backupBound.y);
+ upComps.add(topComp);
+ Component bottomComp = null;
+ int min = margin.getLeft();
+ int max = container.getWidth() - margin.getRight();
+ //先找左侧侧对齐时(x相等)的上下两边组件
+ int ux = topComp.getX();
+ int dx = backupBound.x;
+ while(ux>= min && dx>=min) {
+ if (ux == dx) {
+ break;
+ } else {
+ if (ux= min && dx>= min) {
+ if (ux == dx) {
+ break;
+ } else {
+ if (ux0) {
+ difference = Math.min(getMinHeight(downComps) - minHeight, difference);
+ } else {
+ difference = Math.max(difference, minHeight - getMinHeight(upComps));
+ }
+ //重新计算上下两侧组件size、point
+ if(CalculateUpRelatComponent(difference)){
+ CalculateDownRelatComponent(objY+difference, -difference);
+ };
+ }
+
+ /**
+ * 新拖入组件时,计算调整其他关联组件位置大小
+ * @param child 新拖入的组件
+ * @param x 鼠标所在x坐标
+ * @param y 鼠标所在y坐标
+ */
+ public void fix(XCreator child, int x, int y) {
+ Component parentComp = container.getComponentAt(x, y);
+ if (container.getComponentCount()==0){
+ child.setLocation(0, 0);
+ child.setSize(parentComp.getWidth(), parentComp.getHeight());
+ } else if(isCrossPointArea(parentComp, x, y)){
+ //交叉区域插入组件时,根据具体位置进行上下或者左右或者相邻三个组件的位置大小插入
+ fixCrossPointArea(parentComp, child, x, y);
+ return;
+ } else if (isTrisectionArea(parentComp, x, y)) {
+ // 在边界三等分区域,就不再和组件二等分了
+ fixTrisect(parentComp, child, x, y);
+ return;
+ } else{
+ fixHalve(parentComp, child, x, y);
+ }
+ }
+
+ /**
+ * 平分,正常情况拖入组件时,按照上1/4区域、下1/4区域为上下平分,中左侧1/2区域、中右侧1/2区域为左右平分
+ */
+ private void fixHalve(Component currentComp, XCreator child, int x, int y) {
+ XCreator creator = (XCreator)currentComp;
+ if(!creator.getTargetChildrenList().isEmpty()){
+ fixHalveOfTab(creator,child,x,y);
+ return;
+ }
+ int maxWidth = currentComp.getWidth();
+ int maxHeight = currentComp.getHeight();
+ int xL = currentComp.getX();
+ int yL = currentComp.getY();
+ Dimension dim = new Dimension();
+ boolean isDividUp = y - yL<=maxHeight*TOP_HALF;
+ boolean isDividDown = y - yL>=maxHeight*BOTTOM_HALF;
+ boolean isDividLeft = x -xL margin.getLeft()) {
+ Component targetRightComp = container.getLeftComp(cX, y);
+ minLeftW = getMinLeftWidth(targetRightComp, cX-DEFAULT_AREA_LENGTH);
+ }
+ dealTrisectAtRight(child, minLeftW, minRightW);
+ }
+ crossPointAreaDirect = 0;
+ clearCompsList();
+ }
+
+ /**
+ * 当前组件上边界区域三等分
+ */
+ private void dealTrisectAtTop(XCreator child, int minUH, int minDH) {
+ // 三等分有间隔时,实际是两侧都要减去半个间隔大小
+ int averageH = (minUH+minDH - actualVal)/3;
+ int dLength = 0;
+ int uLength = 0;
+ if (minDH==0) {
+ dLength = 0;
+ uLength = minUH/2;
+ calculateTopComps(uLength, child, uLength);
+ return;
+ } else if(minUH==0){
+ dLength = minDH/2;
+ int witdh = container.getWidth() - margin.getLeft() - margin.getRight();
+ if (!isCalculateChildPos) {
+ calculateBottomComps(dLength);
+ child.setLocation(margin.getLeft(), margin.getRight());
+ child.setSize(witdh, dLength - actualVal/2);
+ } else {
+ childPosition = new int[] {margin.getLeft(), margin.getRight(), witdh, dLength - actualVal/2};
+ }
+ return;
+ } else if (minUH >= minDH) {
+ minDH -= actualVal/2;
+ if ((minDH*2/3)=minLW) {
+ minLW -= actualVal/2;
+ if(minLW*2/3 INDEX_ZERO){
+ childY = upComps.get(INDEX_ZERO).getY()+upComps.get(INDEX_ZERO).getHeight()-length;
+ }
+ for (int i=0,num=upComps.size(); i INDEX_ZERO){
+ childX = leftComps.get(INDEX_ZERO).getX()+leftComps.get(INDEX_ZERO).getWidth()-length;
+ }
+ int childY = container.getHeight() - margin.getBottom();
+ for (int i=0,num=leftComps.size(); i comps) {
+ if (comps.isEmpty()) {
+ return 0;
+ }
+ int minWidth =container.getWidth() - margin.getLeft() - margin.getRight();
+ for (int i=0, size=comps.size(); icomps.get(i).getWidth() ? comps.get(i).getWidth() : minWidth;
+ }
+ return minWidth;
+ }
+
+ private int getMinHeight(List comps) {
+ if (comps.isEmpty()) {
+ return 0;
+ }
+ int minH =container.getHeight() - margin.getTop() - margin.getBottom();
+ for (int i=0, size=comps.size(); icomps.get(i).getHeight() ? comps.get(i).getHeight() : minH;
+ }
+ return minH;
+ }
+
+ // 删除时计算待删除组件上下侧的组件是否何其对齐
+ private int getAllHeight(List comps) {
+ int allHeight = 0;
+ if (comps.isEmpty()) {
+ return allHeight;
+ }
+ int n=comps.size();
+ for (int i=0; i comps) {
+ int allWidth = 0;
+ if (comps.isEmpty()) {
+ return allWidth;
+ }
+ int n=comps.size();
+ for (int i=0; i=0 && objHeight>=(rheight+verti);
+ boolean isVerti = hori>=0 && objWidth>=(rwidth+hori);
+ if (isHori && (objX+objWidth+actualVal)==rx) {
+ rightComps.add(relatComp);
+ } else if(isHori && objX==(rx+rwidth+actualVal)) {
+ leftComps.add(relatComp);
+ } else if(isVerti && (objY+objHeight+actualVal)==ry) {
+ downComps.add(relatComp);
+ } else if(isVerti && objY==(ry+rheight+actualVal)) {
+ upComps.add(relatComp);
+ }
+ }
+ }
+
+ /**
+ * 拖拽组件时遍历某一侧组件得到该侧组件能够缩放的最小宽度,tab布局最小宽度 = 内部组件数 * 单个组件最小宽度
+ * @param list 某一侧组件的集合 如:leftComps
+ * @return int 最小宽度
+ *
+ */
+ private int getCompsMinWidth(List> list){
+ return getMaxCompsNum(list, true) * WLayout.MIN_WIDTH;
+ }
+
+ /**
+ * 拖拽组件遍历某一侧得到该侧组件能够缩放的最小高度,tab布局最小高度 = 内部组件数 * 单个组件最小高度 + 标题高度
+ * @param list 某一侧组件集合
+ * @return int 最小高度
+ *
+ */
+ private int getCompsMinHeight(List> list){
+ for(int i=0;i childrenList = creator.getTargetChildrenList();
+ if(!childrenList.isEmpty()){
+ return getMaxCompsNum(list,false) * WLayout.MIN_HEIGHT + WCardMainBorderLayout.TAB_HEIGHT;
+ }
+ }
+ return WLayout.MIN_HEIGHT;
+ }
+
+ /**
+ * 根据子组件的横(纵)坐标获取某一侧组件的最大内部组件数
+ * @param list 某一侧组件集合
+ * @param isHor 是否以横坐标为准
+ * @return int 最大内部组件数
+ *
+ */
+ private int getMaxCompsNum(List> list,boolean isHor){
+ int maxCompNums = 1;
+ for(int i=0,size=list.size();i childrenList = creator.getTargetChildrenList();
+ int count = childrenList.size();
+ if(count > 0){
+ for(int j=0;j childrenList = creator.getTargetChildrenList();
+ int size = childrenList.size();
+ if(size > 0){
+ for(int j=0;j compsList){
+ int compMinWidth = getCompsMinWidth(compsList);
+ for(int i=0;i (creator.getWidth() - compMinWidth)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 删除或拉伸控件左边框时 调整左侧的组件位置大小;
+ */
+ protected boolean CalculateLefttRelatComponent(int objWidth){
+ if(isBeyondAdjustWidthScope(objWidth)){
+ return false;
+ }
+ int count = leftComps.size();
+ for(int i=0; i compsList){
+ int minHeight = getCompsMinHeight(compsList);
+ for(int i=0;i (creator.getHeight() - minHeight)){
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * 删除或拉伸上边框 调整上方的组件位置大小
+ */
+ protected boolean CalculateUpRelatComponent(int objHeight){
+ if(isBeyondAdjustHeightScope(objHeight)){
+ return false;
+ }
+ int count = upComps.size();
+ for(int i=0; i asideSize) {
+ return FRSplitLayout.CENTER;
+ } else {
+ return FRSplitLayout.ASIDE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRParameterLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRParameterLayoutAdapter.java
new file mode 100644
index 000000000..65858c299
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRParameterLayoutAdapter.java
@@ -0,0 +1,43 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.painters.FRParameterLayoutPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.design.form.parameter.RootDesignGroupModel;
+import com.fr.form.ui.container.WParameterLayout;
+
+/**
+ * 表单参数界面的监听器
+ */
+public class FRParameterLayoutAdapter extends FRAbsoluteLayoutAdapter {
+
+ private HoverPainter painter;
+
+ public FRParameterLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ painter = new FRParameterLayoutPainter(container);
+ }
+
+ public HoverPainter getPainter() {
+ return painter;
+ }
+
+ public GroupModel getLayoutProperties() {
+ return new RootDesignGroupModel((XWParameterLayout)container);
+ }
+
+ /**
+ * 待说明
+ * @param creator 组件
+ */
+ public void fix(XCreator creator) {
+ super.fix(creator);
+
+ WParameterLayout wabs = (WParameterLayout)container.toData();
+ wabs.refreshTagList();
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRScaleLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRScaleLayoutAdapter.java
new file mode 100644
index 000000000..c626f58d9
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRScaleLayoutAdapter.java
@@ -0,0 +1,57 @@
+/**
+ *
+ */
+package com.fr.design.designer.beans.adapters.layout;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+
+/**
+ * @author jim
+ * @date 2014-8-5
+ */
+public class FRScaleLayoutAdapter extends AbstractLayoutAdapter {
+
+ /**
+ * 构造函数
+ *
+ * @param container
+ * 布局容器
+ */
+ public FRScaleLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 能否对应位置放置当前组件
+ *
+ * @param creator
+ * 组件
+ * @param x
+ * 添加的位置x,该位置是相对于container的
+ * @param y
+ * 添加的位置y,该位置是相对于container的
+ * @return 是否可以放置
+ */
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return false;
+ }
+
+ /**
+ *
+ * @see com.fr.design.designer.beans.adapters.layout.AbstractLayoutAdapter#addComp(com.fr.design.designer.creator.XCreator,
+ * int, int)
+ */
+ @Override
+ protected void addComp(XCreator creator, int x, int y) {
+ return;
+ }
+
+ @Override
+ public GroupModel getLayoutProperties() {
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java
new file mode 100644
index 000000000..8c67a44ab
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTabFitLayoutAdapter.java
@@ -0,0 +1,94 @@
+/**
+ *
+ */
+package com.fr.design.designer.beans.adapters.layout;
+
+
+import java.awt.Rectangle;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
+import com.fr.design.designer.properties.FRTabFitLayoutPropertiesGroupModel;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.form.ui.LayoutBorderStyle;
+import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
+import com.fr.general.ComparatorUtils;
+
+/**
+ * tab布局tabFit适配器
+ *
+ * @author focus
+ * @date 2014-6-24
+ */
+public class FRTabFitLayoutAdapter extends FRFitLayoutAdapter {
+ //标题栏高度对tab布局内部组件的y坐标造成了偏移
+ private static int TAB_HEIGHT = 40;
+
+ /**
+ * 构造函数
+ * @param container XWTabFitLayout容器
+ */
+ public FRTabFitLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 返回布局自身属性,方便一些特有设置在layout刷新时处理
+ */
+ @Override
+ public GroupModel getLayoutProperties() {
+ XWTabFitLayout xfl = (XWTabFitLayout) container;
+ return new FRTabFitLayoutPropertiesGroupModel(xfl);
+ }
+
+ /**
+ * 组件的ComponentAdapter在添加组件时,如果发现布局管理器不为空,会继而调用该布局管理器的
+ * addComp方法来完成组件的具体添加。在该方法内,布局管理器可以提供额外的功能。
+ * @param creator 被添加的新组件
+ * @param x 添加的位置x,该位置是相对于container的
+ * @param y 添加的位置y,该位置是相对于container的
+ * @return 是否添加成功,成功返回true,否则false
+ */
+ @Override
+ public boolean addBean(XCreator creator, int x, int y) {
+ // 经过accept判断后,container会被改变,先备份
+ XLayoutContainer backUpContainer = container;
+ Rectangle rect = ComponentUtils.getRelativeBounds(container);
+
+ int posX = x - rect.x;
+ int posY = y - rect.y;
+ if (!accept(creator, posX, posY)) {
+ return false;
+ }
+ // posX,posY是新拖入组件相对于容器的位置,若在tab布局的边缘,则需要把新组件添加到
+ // 父层自适应布局中,这时候的添加位置就是tab布局所在的位置
+ if(this.intersectsEdge(posX, posY, backUpContainer)){
+ if(!ComparatorUtils.equals(backUpContainer.getOuterLayout(), backUpContainer.getBackupParent())){
+ XWTabFitLayout tabLayout = (XWTabFitLayout)backUpContainer;
+ y = adjustY(y,tabLayout);
+ }
+ addComp(creator, x, y);
+ ((XWidgetCreator) creator).recalculateChildrenSize();
+ return true;
+ }
+ // 如果不在边缘,容器为本自适应布局,增加组件的位置就是相对于容器的位置
+ addComp(creator, posX, posY);
+ ((XWidgetCreator) creator).recalculateChildrenSize();
+ return true;
+ }
+
+ // tab布局的纵坐标受到tab高度的影响,判断的上边界取得是里面XWTabFitLayout的上边界,
+ // 实际计算的时候的纵坐标用了外层的CardMainBorerLayout,需要将tab高度减掉
+ private int adjustY(int y,XWTabFitLayout tabLayout){
+ XWCardLayout cardLayout = (XWCardLayout) tabLayout.getBackupParent();
+ LayoutBorderStyle style = cardLayout.toData().getBorderStyle();
+ if(ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)){
+ y -= WCardMainBorderLayout.TAB_HEIGHT;
+ }
+ return y;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTitleLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTitleLayoutAdapter.java
new file mode 100644
index 000000000..d50004b84
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRTitleLayoutAdapter.java
@@ -0,0 +1,52 @@
+/**
+ *
+ */
+package com.fr.design.designer.beans.adapters.layout;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+
+/**
+ * @author jim
+ * @date 2014-9-25
+ */
+public class FRTitleLayoutAdapter extends AbstractLayoutAdapter{
+
+ /**
+ * 构造函数
+ *
+ * @param container 布局容器
+ */
+ public FRTitleLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 能否对应位置放置当前组件
+ *
+ * @param creator 组件
+ * @param x 添加的位置x,该位置是相对于container的
+ * @param y 添加的位置y,该位置是相对于container的
+ * @return 是否可以放置
+ */
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return false;
+ }
+
+ /**
+ *
+ * @see com.fr.design.designer.beans.adapters.layout.AbstractLayoutAdapter#addComp(com.fr.design.designer.creator.XCreator,nt, int)
+ */
+ @Override
+ protected void addComp(XCreator creator, int x, int y) {
+ return;
+ }
+
+ @Override
+ public GroupModel getLayoutProperties() {
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalLayoutAdapter.java
new file mode 100644
index 000000000..ceded745c
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalLayoutAdapter.java
@@ -0,0 +1,84 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.painters.FRVerticalLayoutPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWVerticalBoxLayout;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.design.designer.properties.VerticalBoxProperties;
+import com.fr.design.designer.properties.VerticalLayoutConstraints;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WVerticalBoxLayout;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class FRVerticalLayoutAdapter extends AbstractLayoutAdapter {
+
+ public FRVerticalLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ return true;
+ }
+
+ @Override
+ protected void addComp(XCreator creator, int x, int y) {
+ if(whetherUseBackupSize(creator)) {
+ creator.useBackupSize();
+ }
+ container.add(creator, getPlaceIndex(y));
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ @Override
+ public boolean supportBackupSize() {
+ return true;
+ }
+
+ private int getPlaceIndex(int y) {
+ int place = -1;
+ int count = container.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ Rectangle bounds = container.getComponent(i).getBounds();
+ if (y < bounds.y) {
+ return i;
+ }
+ }
+ if (place == -1) {
+ return count;
+ }
+ return place;
+ }
+
+ @Override
+ public void fix(XCreator creator) {
+ WVerticalBoxLayout layout = ((XWVerticalBoxLayout) container).toData();
+ Widget widget = ((XWidgetCreator) creator).toData();
+ creator.setPreferredSize(new Dimension(0, creator.getHeight()));
+ layout.setHeightAtWidget(widget, creator.getHeight());
+ }
+
+ @Override
+ public HoverPainter getPainter() {
+ return new FRVerticalLayoutPainter(container);
+ }
+
+ @Override
+ public ConstraintsGroupModel getLayoutConstraints(XCreator creator) {
+ return new VerticalLayoutConstraints(container, creator);
+ }
+
+ @Override
+ public GroupModel getLayoutProperties() {
+ XWVerticalBoxLayout xbl = (XWVerticalBoxLayout) container;
+ return new VerticalBoxProperties(xbl);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalSplitLayoutAdapter.java b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalSplitLayoutAdapter.java
new file mode 100644
index 000000000..92298b1a7
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/adapters/layout/FRVerticalSplitLayoutAdapter.java
@@ -0,0 +1,52 @@
+package com.fr.design.designer.beans.adapters.layout;
+
+import java.awt.Component;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.designer.creator.XAbstractSplitLayout;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWVerticalSplitLayout;
+import com.fr.design.designer.properties.HorizontalSplitProperties;
+import com.fr.design.form.layout.FRSplitLayout;
+import com.fr.form.ui.container.WVerticalSplitLayout;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class FRVerticalSplitLayoutAdapter extends AbstractLayoutAdapter {
+
+ public FRVerticalSplitLayoutAdapter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public boolean accept(XCreator creator, int x, int y) {
+ String place = getPlacement(creator, x, y);
+ FRSplitLayout layout = (FRSplitLayout) container.getLayout();
+ Component comp = layout.getLayoutComponent(place);
+ return comp == null;
+ }
+
+ @Override
+ protected void addComp(XCreator creator, int x, int y) {
+ String placement = getPlacement(creator, x, y);
+ container.add(creator, placement);
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ @Override
+ public GroupModel getLayoutProperties() {
+ XAbstractSplitLayout xbl = (XAbstractSplitLayout) container;
+ return new HorizontalSplitProperties(xbl.toData());
+ }
+
+ protected String getPlacement(XCreator creator, int x, int y) {
+ int height = container.getHeight();
+ WVerticalSplitLayout wLayout = ((XWVerticalSplitLayout) container).toData();
+ int asideSize = (int) (height * wLayout.getRatio());
+ if (y > asideSize) {
+ return FRSplitLayout.CENTER;
+ } else {
+ return FRSplitLayout.ASIDE;
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/events/CreatorEventListenerTable.java b/designer_form/src/com/fr/design/designer/beans/events/CreatorEventListenerTable.java
new file mode 100644
index 000000000..94665c02b
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/events/CreatorEventListenerTable.java
@@ -0,0 +1,44 @@
+package com.fr.design.designer.beans.events;
+
+import java.util.ArrayList;
+
+import com.fr.design.designer.creator.XComponent;
+import com.fr.general.ComparatorUtils;
+
+public class CreatorEventListenerTable {
+
+ protected ArrayList listeners;
+
+ public CreatorEventListenerTable() {
+ listeners = new ArrayList();
+ }
+
+ public void addListener(DesignerEditListener listener) {
+ if (listener == null) {
+ return;
+ }
+ for (int i = 0; i < listeners.size(); i++) {
+ if (ComparatorUtils.equals(listener,listeners.get(i))) {
+ listeners.set(i, listener);
+ return;
+ }
+ }
+ listeners.add(listener);
+ }
+
+ private void fireCreatorModified(DesignerEvent evt) {
+ for (int i = 0; i < listeners.size(); i++) {
+ DesignerEditListener listener = listeners.get(i);
+ listener.fireCreatorModified(evt);
+ }
+ }
+
+ public void fireCreatorModified(XComponent creator, int eventID) {
+ DesignerEvent evt = new DesignerEvent(eventID, creator);
+ fireCreatorModified(evt);
+ }
+
+ public void fireCreatorModified(int eventID) {
+ fireCreatorModified(null, eventID);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/events/DesignerEditListener.java b/designer_form/src/com/fr/design/designer/beans/events/DesignerEditListener.java
new file mode 100644
index 000000000..728e22681
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/events/DesignerEditListener.java
@@ -0,0 +1,14 @@
+package com.fr.design.designer.beans.events;
+
+import java.util.EventListener;
+
+/**
+ * 界面设计组件触发的编辑处理器接口
+ * @since 6.5.4
+ * @author richer
+ */
+public interface DesignerEditListener extends EventListener {
+
+ void fireCreatorModified(DesignerEvent evt);
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/events/DesignerEditor.java b/designer_form/src/com/fr/design/designer/beans/events/DesignerEditor.java
new file mode 100644
index 000000000..78eca3f04
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/events/DesignerEditor.java
@@ -0,0 +1,82 @@
+package com.fr.design.designer.beans.events;
+
+import com.fr.stable.core.PropertyChangeAdapter;
+import com.fr.stable.core.PropertyChangeListener;
+import com.fr.design.utils.gui.LayoutUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+
+public class DesignerEditor implements PropertyChangeListener {
+
+ private ArrayList propertyChangeListenerList = new ArrayList();
+ private ArrayList stopEditListenerList = new ArrayList();
+ private T comp;
+ private boolean changed;
+
+ public DesignerEditor(T comp) {
+ this.comp = comp;
+ }
+
+ public void addStopEditingListener(PropertyChangeAdapter l) {
+ int index = stopEditListenerList.indexOf(l);
+ if (index == -1) {
+ stopEditListenerList.add(l);
+ } else {
+ stopEditListenerList.set(index, l);
+ }
+ }
+
+ public void fireEditStoped() {
+ if (changed) {
+ for (PropertyChangeAdapter l : stopEditListenerList) {
+ l.propertyChange();
+ }
+ changed = false;
+ }
+ }
+
+ public void addPropertyChangeListener(PropertyChangeAdapter l) {
+ int index = propertyChangeListenerList.indexOf(l);
+ if (index == -1) {
+ propertyChangeListenerList.add(l);
+ } else {
+ propertyChangeListenerList.set(index, l);
+ }
+ }
+
+ public void propertyChange() {
+ for (PropertyChangeAdapter l : propertyChangeListenerList) {
+ l.propertyChange();
+ }
+ changed = true;
+ }
+
+ @Override
+ public void propertyChange(T mark) {
+
+ }
+
+ @Override
+ public void propertyChange(T... marks) {
+
+ }
+
+ public void reset() {
+ changed = false;
+ }
+
+ public void paintEditor(Graphics g, Dimension size) {
+ if (this.comp != null) {
+ comp.setSize(new Dimension(size.width - 2, size.height - 2));
+ LayoutUtils.layoutContainer(comp);
+ Graphics clipg = g.create(1, 1, size.width, size.height);
+ this.comp.paint(clipg);
+ }
+ }
+
+ public T getEditorTarget() {
+ return comp;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/events/DesignerEvent.java b/designer_form/src/com/fr/design/designer/beans/events/DesignerEvent.java
new file mode 100644
index 000000000..715f6e3e7
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/events/DesignerEvent.java
@@ -0,0 +1,41 @@
+package com.fr.design.designer.beans.events;
+
+import com.fr.design.designer.creator.XComponent;
+
+/**
+ * 设计事件
+ */
+public class DesignerEvent {
+
+ public static final int CREATOR_ADDED = 1;
+
+ public static final int CREATOR_DELETED = 2;
+
+ public static final int CREATOR_CUTED = 3;
+
+ public static final int CREATOR_PASTED = 4;
+
+ public static final int CREATOR_EDITED = 5;
+
+ public static final int CREATOR_RESIZED = 6;
+
+ public static final int CREATOR_SELECTED = 7;
+
+ public static final int CREATOR_RENAMED = 8;
+
+ private int eventID;
+ private XComponent affectedXCreator;
+
+ DesignerEvent(int eventID, XComponent comp) {
+ this.eventID = eventID;
+ this.affectedXCreator = comp;
+ }
+
+ public int getCreatorEventID() {
+ return eventID;
+ }
+
+ public XComponent getAffectedCreator() {
+ return affectedXCreator;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java b/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java
new file mode 100644
index 000000000..a5758639b
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/AccessDirection.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import com.fr.design.beans.location.Absorptionline;
+import com.fr.design.beans.location.MoveUtils;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormSelection;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.form.ui.container.WAbsoluteLayout;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class AccessDirection implements Direction {
+ private static final int MINHEIGHT = 21;
+ private static final int MINWIDTH = 36;
+ private int ymin;
+ private int xmin;
+
+ abstract int getCursor();
+
+ protected abstract Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds);
+
+ protected int[] sorption(int x, int y,Rectangle current_bounds, FormDesigner designer) {
+ // 自适应布局不需要吸附线,但需要对齐线,对齐线后面处理
+ if (!designer.hasWAbsoluteLayout()) {
+ return new int[] { x, y };
+ } else {
+ int posy = current_bounds.y;
+ if (posy >= designer.getParaHeight() && !designer.isFormParaDesigner()) {
+ return new int[] { x, y };
+ }
+
+ Point relativePoint = getRelativePoint(x, y, current_bounds,designer);
+ sorptionPoint(relativePoint,current_bounds, designer);
+ return new int[] { relativePoint.x, relativePoint.y };
+ }
+
+ }
+
+ protected Point getRelativePoint(int x, int y, Rectangle current_bounds,FormDesigner designer) {
+ if (x < 0) {
+ x = 0;
+ } else if (x > designer.getRootComponent().getWidth() && designer.getSelectionModel().hasSelectionComponent()) {
+ x = designer.getRootComponent().getWidth();
+ }
+ //参数面板可以无下限拉长
+ if (y < 0) {
+ y = 0;
+ } else if (y > designer.getRootComponent().getHeight() && designer.getSelectionModel().hasSelectionComponent()
+ && !designer.getSelectionModel().getSelection().getSelectedCreator().acceptType(XWParameterLayout.class)) {
+ y = designer.getRootComponent().getHeight();
+ }
+ return new Point(x, y);
+ }
+
+ protected void sorptionPoint(Point point, Rectangle current_bounds,FormDesigner designer) {
+ boolean findInX = current_bounds.getWidth() <= MoveUtils.SORPTION_UNIT ? true : false;
+ boolean findInY = current_bounds.getHeight() <= MoveUtils.SORPTION_UNIT ? true : false;
+
+ WAbsoluteLayout layout =getLayout(designer);
+ FormSelection selection = designer.getSelectionModel().getSelection();
+ for (int i = 0, count = layout.getWidgetCount(); i < count; i++) {
+ BoundsWidget temp = (BoundsWidget) layout.getWidget(i);
+ if (!temp.isVisible() || selection.contains(temp.getWidget())) {
+ continue;
+ }
+ Rectangle bounds = temp.getBounds();
+ if (!findInX) {
+ int x1 = bounds.x;
+ if (Math.abs(x1 - point.x) <= MoveUtils.SORPTION_UNIT) {
+ point.x = x1;
+ findInX = true;
+ }
+ int x2 = bounds.x + bounds.width;
+ if (Math.abs(x2 - point.x) <= MoveUtils.SORPTION_UNIT) {
+ point.x = x2;
+ findInX = true;
+ }
+ }
+ if (!findInY) {
+ int y1 = bounds.y;
+ if (Math.abs(y1 - point.y) <= MoveUtils.SORPTION_UNIT) {
+ point.y = y1;
+ findInY = true;
+ }
+ int y2 = bounds.y + bounds.height;
+ if (Math.abs(y2 - point.y) <= MoveUtils.SORPTION_UNIT) {
+ point.y = y2;
+ findInY = true;
+ }
+
+ }
+ if (findInX && findInY) {
+ break;
+ }
+ }
+
+ designer.getStateModel().setXAbsorptionline(findInX && current_bounds.getWidth() > MoveUtils.SORPTION_UNIT ? Absorptionline.createXAbsorptionline(point.x) : null);
+ designer.getStateModel().setYAbsorptionline(findInY && current_bounds.getHeight() > MoveUtils.SORPTION_UNIT ? Absorptionline.createYAbsorptionline(point.y) : null);
+ }
+
+ private WAbsoluteLayout getLayout(final FormDesigner designer){
+ XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(
+ designer.getTarget().getContainer());
+ WAbsoluteLayout layout;
+ if (formLayoutContainer.acceptType(XWBorderLayout.class)){
+ layout = (WAbsoluteLayout) designer.getParaComponent().toData();
+ } else{
+ layout = (WAbsoluteLayout) designer.getTarget().getContainer();
+ }
+ return layout;
+ }
+
+ /**
+ * 拖拽
+ * @param dx 坐标x
+ * @param dy 坐标y
+ * @param designer 设计界面
+ */
+ public void drag(int dx, int dy, FormDesigner designer) {
+ Rectangle rec = getDraggedBounds(dx, dy, designer.getSelectionModel().getSelection().getRelativeBounds(), designer, designer.getSelectionModel().getSelection().getBackupBounds());
+ //设定控件最小高度21,因每次拖曳至少移动1,防止控件高度等于21时,拖曳导致rec.y的变化使得控件不停的向上或向下移动。
+ if(rec.height == MINHEIGHT){
+ ymin = rec.y;
+ }
+ if(rec.height == MINHEIGHT - 1){
+ ymin = ymin == rec.y ? rec.y : rec.y - 1;
+ }
+ if(rec.height < MINHEIGHT){
+ rec.height = MINHEIGHT;
+ rec.y = ymin;
+ }
+ // 增加下宽度也设最小为21
+ if (rec.width == MINWIDTH) {
+ xmin = rec.x;
+ }
+ if(rec.width == MINWIDTH - 1){
+ xmin = xmin == rec.x ? rec.x : rec.x - 1;
+ }
+ if (rec.width < MINWIDTH) {
+ rec.width = MINWIDTH;
+ rec.x = xmin;
+ }
+ if(rec != null) {
+ designer.getSelectionModel().getSelection().setSelectionBounds(rec, designer);
+ }
+ }
+
+ /**
+ * 更新鼠标指针形状
+ * @param formEditor 设计界面组件
+ */
+ public void updateCursor(FormDesigner formEditor) {
+
+ // 调用位置枚举的多态方法getCursor获取鼠标形状
+ int type = getCursor();
+
+ if (type != formEditor.getCursor().getType()) {
+ // 设置当前形状
+ formEditor.setCursor(Cursor.getPredefinedCursor(type));
+ }
+ }
+
+ /**
+ * 生成组件备用的bound
+ * @param formEditor 设计界面组件
+ */
+ public void backupBounds(FormDesigner formEditor) {
+ formEditor.getSelectionModel().getSelection().backupBounds();
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Add.java b/designer_form/src/com/fr/design/designer/beans/location/Add.java
new file mode 100644
index 000000000..349833f9d
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Add.java
@@ -0,0 +1,19 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.Toolkit;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.mainframe.FormDesigner;
+
+public class Add extends Outer {
+
+ private Cursor addCursor = Toolkit.getDefaultToolkit().createCustomCursor(
+ BaseUtils.readImage("/com/fr/design/images/form/designer/cursor/add.png"), new Point(0, 0),
+ "add");
+
+ public void updateCursor(FormDesigner formEditor) {
+ formEditor.setCursor(addCursor);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Bottom.java b/designer_form/src/com/fr/design/designer/beans/location/Bottom.java
new file mode 100644
index 000000000..f50bb7655
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Bottom.java
@@ -0,0 +1,30 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class Bottom extends AccessDirection {
+
+ public Bottom() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ current_bounds.height = sorption(0, oldbounds.height + dy + oldbounds.y, current_bounds, designer)[1]
+ - oldbounds.y;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.S_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.BOTTOM;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Direction.java b/designer_form/src/com/fr/design/designer/beans/location/Direction.java
new file mode 100644
index 000000000..0031c8aae
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Direction.java
@@ -0,0 +1,45 @@
+package com.fr.design.designer.beans.location;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public interface Direction {
+
+ /**
+ * 拖拽组件
+ * @param dx 水平方向位移
+ * @param dy 垂直方向位移
+ * @param designer 设计器
+ */
+ void drag(int dx, int dy, FormDesigner designer);
+
+ /**
+ * 更新鼠标样式
+ * @param formEditor : 设计器
+ */
+ void updateCursor(FormDesigner formEditor);
+
+ /**
+ * Direction的位置标示,top = 1,bottom = 2等
+ */
+ int getActual();
+
+ /**
+ * 拖拽前先备份原始位置,拖拽过程中用于比较位移跟原始位置从而确定新位置大小
+ * @param formEditor 设计器
+ */
+ void backupBounds(FormDesigner formEditor);
+
+ public static final int TOP = 1;
+ public static final int BOTTOM = 2;
+ public static final int LEFT = 3;
+ public static final int RIGHT = 4;
+ public static final int LEFT_TOP = 5;
+ public static final int LEFT_BOTTOM = 6;
+ public static final int RIGHT_TOP = 7;
+ public static final int RIGHT_BOTTOM = 8;
+ public static final int INNER = 0;
+ public static final int OUTER = -1;
+
+ public static final int[] ALL = new int[]{TOP, BOTTOM, LEFT, RIGHT, LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM, INNER};
+ public static final int[] TOP_BOTTOM_LEFT_RIGHT= new int[]{TOP, BOTTOM, LEFT, RIGHT};
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Inner.java b/designer_form/src/com/fr/design/designer/beans/location/Inner.java
new file mode 100644
index 000000000..68db5241e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Inner.java
@@ -0,0 +1,138 @@
+package com.fr.design.designer.beans.location;
+
+import com.fr.design.beans.location.Absorptionline;
+import com.fr.design.beans.location.MoveUtils;
+import com.fr.design.beans.location.MoveUtils.RectangleDesigner;
+import com.fr.design.beans.location.MoveUtils.RectangleIterator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormSelection;
+import com.fr.form.ui.container.WAbsoluteLayout;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+import com.fr.stable.ArrayUtils;
+
+import java.awt.*;
+
+public class Inner extends AccessDirection {
+
+ public Inner() {
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.MOVE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.INNER;
+ }
+
+ protected Point getRelativePoint(int x, int y, Rectangle current_bounds, FormDesigner designer) {
+ if (x < 0) {
+ x = 0;
+ } else if (x + current_bounds.getWidth() > designer.getRootComponent().getWidth()
+ && designer.getSelectionModel().hasSelectionComponent()) {
+ x = designer.getRootComponent().getWidth() - current_bounds.width;
+ }
+ if (y < 0) {
+ y = 0;
+ } else if (y + current_bounds.getHeight() > designer.getRootComponent().getHeight()
+ && designer.getSelectionModel().hasSelectionComponent()) {
+ y = designer.getRootComponent().getHeight() - current_bounds.height;
+ }
+ return new Point(x, y);
+ }
+
+ @Override
+ protected void sorptionPoint(Point point, Rectangle current_bounds, final FormDesigner designer) {
+ RectangleDesigner rd = new RectangleDesigner() {
+ public void setXAbsorptionline(Absorptionline line) {
+ designer.getStateModel().setXAbsorptionline(line);
+ }
+ public void setYAbsorptionline(Absorptionline line) {
+ designer.getStateModel().setYAbsorptionline(line);
+ }
+
+ /**
+ * 获取当前选中块的水平线数组
+ *
+ * @return 块的水平线数组
+ *
+ */
+ public int[] getHorizontalLine(){
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+
+ /**
+ * 获取当前选中块的垂直线数组
+ *
+ * @return 块的垂直线数组
+ *
+ */
+ public int[] getVerticalLine(){
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+ public RectangleIterator createRectangleIterator() {
+ return getRectangleIterator(designer);
+ }
+ };
+ point.setLocation(MoveUtils.sorption(point.x, point.y, current_bounds.width, current_bounds.height, rd));
+ }
+
+ private RectangleIterator getRectangleIterator(final FormDesigner designer){
+ return new RectangleIterator() {
+ private int i;
+ private WAbsoluteLayout layout = getLayout(designer);
+ private int count = layout.getWidgetCount();
+ private FormSelection selection = designer.getSelectionModel().getSelection();
+
+ public boolean hasNext() {
+ if (i >= count) {
+ return false;
+ }
+ BoundsWidget temp = (BoundsWidget) layout.getWidget(i);
+ while (!temp.isVisible() || selection.contains(temp.getWidget())) {
+ if (++i >= count) {
+ return false;
+ }
+ temp = (BoundsWidget) layout.getWidget(i);
+ }
+ return true;
+ }
+ public int[] getHorizontalLine(){
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+ public int[] getVerticalLine(){
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+ public Rectangle nextRectangle() {
+ BoundsWidget temp = (BoundsWidget) layout.getWidget(i++);
+ return temp.getBounds();
+ }
+ };
+ }
+
+ private WAbsoluteLayout getLayout(final FormDesigner designer){
+ XLayoutContainer formLayoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(
+ designer.getTarget().getContainer());
+ WAbsoluteLayout layout;
+ if (formLayoutContainer.acceptType(XWBorderLayout.class)){
+ layout = (WAbsoluteLayout) designer.getParaComponent().toData();
+ } else{
+ layout = (WAbsoluteLayout) designer.getTarget().getContainer();
+ }
+ return layout;
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ int[] xy = sorption(oldbounds.x + dx, oldbounds.y + dy, current_bounds, designer);
+ current_bounds.x = xy[0];
+ current_bounds.y = xy[1];
+ return current_bounds;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Left.java b/designer_form/src/com/fr/design/designer/beans/location/Left.java
new file mode 100644
index 000000000..23e2c1659
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Left.java
@@ -0,0 +1,30 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class Left extends AccessDirection {
+
+ public Left() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ current_bounds.x = sorption(oldbounds.x + dx, 0, current_bounds, designer)[0];
+ current_bounds.width = oldbounds.width - current_bounds.x + oldbounds.x;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.W_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.LEFT;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/LeftBottom.java b/designer_form/src/com/fr/design/designer/beans/location/LeftBottom.java
new file mode 100644
index 000000000..3ba5fd4cf
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/LeftBottom.java
@@ -0,0 +1,32 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class LeftBottom extends AccessDirection {
+
+ public LeftBottom() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ int[] xy = sorption(oldbounds.x + dx, oldbounds.y + dy + oldbounds.height, current_bounds, designer);
+ current_bounds.x = xy[0];
+ current_bounds.width = oldbounds.width - current_bounds.x + oldbounds.x;
+ current_bounds.height = xy[1] - oldbounds.y;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.SW_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.LEFT_BOTTOM;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/LeftTop.java b/designer_form/src/com/fr/design/designer/beans/location/LeftTop.java
new file mode 100644
index 000000000..254191ce7
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/LeftTop.java
@@ -0,0 +1,32 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class LeftTop extends AccessDirection {
+ public LeftTop() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ int[] xy = sorption(oldbounds.x + dx, oldbounds.y + dy, current_bounds, designer);
+ current_bounds.x = xy[0];
+ current_bounds.y = xy[1];
+ current_bounds.width = oldbounds.width - current_bounds.x + oldbounds.x;
+ current_bounds.height = oldbounds.height - current_bounds.y + oldbounds.y;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.NW_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.LEFT_TOP;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Location.java b/designer_form/src/com/fr/design/designer/beans/location/Location.java
new file mode 100644
index 000000000..5332d9452
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Location.java
@@ -0,0 +1,35 @@
+package com.fr.design.designer.beans.location;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public enum Location implements Direction{
+ // 枚举里面定义10个位置
+ outer(new Outer()), add(new Add()), inner(new Inner()),
+ left_top(new LeftTop()), top(new Top()), right_top(new RightTop()),
+ right(new Right()), right_bottom(new RightBottom()),
+ bottom(new Bottom()),left_bottom(new LeftBottom()), left(new Left());
+
+ private Direction direction;
+
+ private Location(Direction l) {
+ direction = l;
+ }
+
+ public void drag(int dx, int dy, FormDesigner desinger) {
+ direction.drag(dx, dy, desinger);
+ }
+
+ public int getActual() {
+ return direction.getActual();
+ }
+
+ @Override
+ public void updateCursor(FormDesigner formEditor) {
+ direction.updateCursor(formEditor);
+ }
+
+ @Override
+ public void backupBounds(FormDesigner formEditor) {
+ direction.backupBounds(formEditor);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Outer.java b/designer_form/src/com/fr/design/designer/beans/location/Outer.java
new file mode 100644
index 000000000..c29caab37
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Outer.java
@@ -0,0 +1,27 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class Outer extends AccessDirection {
+
+ public Outer() {
+ }
+
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ return null;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.DEFAULT_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.OUTER;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Right.java b/designer_form/src/com/fr/design/designer/beans/location/Right.java
new file mode 100644
index 000000000..29071f691
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Right.java
@@ -0,0 +1,30 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class Right extends AccessDirection {
+
+ public Right() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ current_bounds.width = sorption(oldbounds.x + dx + oldbounds.width, 0, current_bounds, designer)[0]
+ - oldbounds.x;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.E_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.RIGHT;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/RightBottom.java b/designer_form/src/com/fr/design/designer/beans/location/RightBottom.java
new file mode 100644
index 000000000..6ec7e8e88
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/RightBottom.java
@@ -0,0 +1,31 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class RightBottom extends AccessDirection {
+
+ public RightBottom() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ int[] xy = sorption(oldbounds.x + dx + oldbounds.width, oldbounds.height + dy + oldbounds.y, current_bounds, designer);
+ current_bounds.width = xy[0] - oldbounds.x;
+ current_bounds.height = xy[1] - oldbounds.y;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.SE_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.RIGHT_BOTTOM;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/RightTop.java b/designer_form/src/com/fr/design/designer/beans/location/RightTop.java
new file mode 100644
index 000000000..6e2ef7ffc
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/RightTop.java
@@ -0,0 +1,31 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class RightTop extends AccessDirection {
+
+ public RightTop() {
+ }
+
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ int[] xy = sorption(oldbounds.x + dx + oldbounds.width, dy + oldbounds.y, current_bounds, designer);
+ current_bounds.y = xy[1];
+ current_bounds.height = oldbounds.height - current_bounds.y + oldbounds.y;
+ current_bounds.width = xy[0] - oldbounds.x;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.NE_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.RIGHT_TOP;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/RootResizeDirection.java b/designer_form/src/com/fr/design/designer/beans/location/RootResizeDirection.java
new file mode 100644
index 000000000..1fef47cf3
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/RootResizeDirection.java
@@ -0,0 +1,96 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.utils.gui.LayoutUtils;
+
+/**
+ * 这个类用可以用来拖拽表单最底层容器的大小。目前只用于参数界面
+ */
+public abstract class RootResizeDirection implements Direction {
+
+ public static RootResizeDirection BOTTOM_RESIZE = new RootResizeDirection(Direction.BOTTOM) {
+
+ @Override
+ public Cursor getCursor() {
+ return Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
+ }
+
+ @Override
+ public void resizeRootBounds(Rectangle rec, int dx, int dy) {
+ rec.height += dy;
+ }
+
+ };
+ public static RootResizeDirection RIGHT_RESIZE = new RootResizeDirection(Direction.RIGHT) {
+
+ @Override
+ public Cursor getCursor() {
+ return Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
+ }
+
+ @Override
+ public void resizeRootBounds(Rectangle rec, int dx, int dy) {
+ rec.width += dx;
+ }
+
+ };
+ public static RootResizeDirection RIGHT_BOTTOM_RESIZE = new RootResizeDirection(Direction.RIGHT_BOTTOM) {
+
+ @Override
+ public Cursor getCursor() {
+ return Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
+ }
+
+ @Override
+ public void resizeRootBounds(Rectangle rec, int dx, int dy) {
+ rec.height += dy;
+ rec.width += dx;
+ }
+
+ };
+
+ private int actual;
+ private Rectangle oldBounds;
+
+ private RootResizeDirection(int actual) {
+ this.actual = actual;
+ }
+
+ @Override
+ public void drag(int dx, int dy, FormDesigner designer) {
+ Rectangle rec = new Rectangle(oldBounds);
+ if (actual == Direction.BOTTOM) {
+ rec.height += dy;
+ } else if (actual == Direction.RIGHT) {
+ rec.width += dx;
+ } else if (actual == Direction.RIGHT_BOTTOM) {
+ rec.height += dy;
+ rec.width += dx;
+ }
+ designer.getRootComponent().setBounds(rec);
+ designer.populateRootSize();
+ LayoutUtils.layoutRootContainer(designer.getRootComponent());
+ }
+
+ protected abstract void resizeRootBounds(Rectangle rec, int dx, int dy);
+
+ protected abstract Cursor getCursor();
+
+ @Override
+ public int getActual() {
+ return actual;
+ }
+
+ @Override
+ public void updateCursor(FormDesigner formEditor) {
+ formEditor.setCursor(getCursor());
+ }
+
+ @Override
+ public void backupBounds(FormDesigner designer) {
+ oldBounds = designer.getRootComponent().getBounds();
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/location/Top.java b/designer_form/src/com/fr/design/designer/beans/location/Top.java
new file mode 100644
index 000000000..ab9d8ce10
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/location/Top.java
@@ -0,0 +1,30 @@
+package com.fr.design.designer.beans.location;
+
+import java.awt.Cursor;
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+
+public class Top extends AccessDirection {
+
+ public Top() {
+ }
+
+ @Override
+ public Rectangle getDraggedBounds(int dx, int dy, Rectangle current_bounds, FormDesigner designer,
+ Rectangle oldbounds) {
+ current_bounds.y = sorption(0, dy + oldbounds.y, current_bounds, designer)[1];
+ current_bounds.height = oldbounds.height - current_bounds.y + oldbounds.y;
+ return current_bounds;
+ }
+
+ @Override
+ public int getCursor() {
+ return Cursor.N_RESIZE_CURSOR;
+ }
+
+ @Override
+ public int getActual() {
+ return Direction.TOP;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java b/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java
new file mode 100644
index 000000000..21c68f605
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/models/AddingModel.java
@@ -0,0 +1,126 @@
+package com.fr.design.designer.beans.models;
+
+import java.awt.Rectangle;
+
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.general.ComparatorUtils;
+
+/**
+ * 添加状态下的model
+ */
+public class AddingModel {
+
+ // 当前要添加的组件
+ private XCreator creator;
+ // 记录当前鼠标的位置信息
+ private int current_x;
+ private int current_y;
+ private boolean added;
+
+ public AddingModel(FormDesigner designer, XCreator xCreator) {
+ String creatorName = getXCreatorName(designer, xCreator);
+ this.creator = xCreator;
+ instantiateCreator(designer, creatorName);
+ // 初始的时候隐藏该组件的图标
+ current_x = -this.creator.getWidth();
+ current_y = -this.creator.getHeight();
+ }
+
+ /**
+ * 待说明
+ * @param designer 设计器
+ * @param creatorName 组件名
+ */
+ public void instantiateCreator(FormDesigner designer, String creatorName) {
+ creator.toData().setWidgetName(creatorName);
+ ComponentAdapter adapter = new CompositeComponentAdapter(designer, creator);
+ adapter.initialize();
+ creator.addNotify();
+ creator.putClientProperty(AdapterBus.CLIENT_PROPERTIES, adapter);
+ }
+
+ public AddingModel(XCreator xCreator, int x, int y) {
+ this.creator = xCreator;
+ this.creator.backupCurrentSize();
+ this.creator.backupParent();
+ this.creator.setSize(xCreator.initEditorSize());
+ current_x = x - (xCreator.getWidth() / 2);
+ current_y = y - (xCreator.getHeight() / 2);
+ }
+
+ /**
+ * 隐藏当前组件的图标
+ */
+ public void reset() {
+ current_x = -this.creator.getWidth();
+ current_y = -this.creator.getHeight();
+ }
+
+ public String getXCreatorName(FormDesigner designer,XCreator x){
+ String def= x.createDefaultName();
+ if (x.acceptType(XWParameterLayout.class)) {
+ return def;
+ }
+ int i = 0;
+ while (designer.getTarget().isNameExist(def + i)) {
+ i++;
+ }
+ return def+i;
+ }
+
+ public int getCurrentX() {
+ return current_x;
+ }
+
+ public int getCurrentY() {
+ return current_y;
+ }
+
+
+ /**
+ * 移动组件图标到鼠标事件发生的位置
+ * @param x 坐标
+ * @param y 坐标
+ */
+ public void moveTo(int x, int y) {
+ current_x = x - (this.creator.getWidth() / 2);
+ current_y = y - (this.creator.getHeight() / 2);
+ }
+
+ public XCreator getXCreator() {
+ return this.creator;
+ }
+
+ /**
+ * 当前组件是否已经添加到某个容器中
+ * @return 是返回true
+ */
+ public boolean isCreatorAdded() {
+ return added;
+ }
+
+ /**
+ * 加入容器
+ * @param designer 设计器
+ * @param container 容器
+ * @param x 坐标
+ * @param y 坐标
+ * @return 成功返回true
+ */
+ public boolean add2Container(FormDesigner designer, XLayoutContainer container, int x, int y) {
+ Rectangle rect = ComponentUtils.getRelativeBounds(container);
+ if(!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())){
+ return added = container.getLayoutAdapter().addBean(creator,x,y);
+ }
+ return added = container.getLayoutAdapter().addBean(creator,
+ x + designer.getArea().getHorizontalValue() - rect.x,
+ y + designer.getArea().getVerticalValue() - rect.y);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java b/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java
new file mode 100644
index 000000000..fd2b48a73
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/models/SelectionModel.java
@@ -0,0 +1,321 @@
+package com.fr.design.designer.beans.models;
+
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.designer.beans.location.Location;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWFitLayout;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormSelection;
+import com.fr.design.mainframe.FormSelectionUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * 该model保存当前选择的组件和剪切版信息
+ */
+public class SelectionModel {
+ private static final int DELTA_X_Y = 20; //粘贴时候的偏移距离
+ private static FormSelection CLIP_BOARD = new FormSelection();
+ private FormDesigner designer;
+ private FormSelection selection;
+ private Rectangle hotspot_bounds;
+
+ public SelectionModel(FormDesigner designer) {
+ this.designer = designer;
+ selection = new FormSelection();
+ }
+
+ /**
+ * 重置。清空formSelction以及选择区域
+ */
+ public void reset() {
+ selection.reset();
+ hotspot_bounds = null;
+ }
+
+ /**
+ * formSelction是否为空
+ * @return 是否为空
+ */
+ public static boolean isEmpty(){
+ return CLIP_BOARD.isEmpty();
+ }
+
+ /**
+ * 鼠标点击一下,所选中的单个组件。按下Ctrl或者shift键时鼠标可以进行多选
+ * @param e 鼠标事件
+ */
+ public void selectACreatorAtMouseEvent(MouseEvent e) {
+ if (!e.isControlDown() && !e.isShiftDown()) {
+ // 如果Ctrl或者Shift键盘没有按下,则清除已经选择的组件
+ selection.reset();
+ }
+
+ // 获取e所在的组件
+ XCreator comp = designer.getComponentAt(e);
+ // 如果父层是scale和title两个专属容器,返回其父层,组件本身是不让被选中的
+ if (comp != designer.getRootComponent() && comp != designer.getParaComponent()) {
+ XCreator parentContainer = (XCreator) comp.getParent();
+ comp = parentContainer.isDedicateContainer() ? parentContainer : comp;
+ }
+ if (selection.removeSelectedCreator(comp) || selection.addSelectedCreator(comp)) {
+ designer.getEditListenerTable().fireCreatorModified(comp, DesignerEvent.CREATOR_SELECTED);
+ designer.repaint();
+ }
+ }
+
+ /**
+ * 将所选组件剪切到剪切板上
+ */
+ public void cutSelectedCreator2ClipBoard() {
+ if (hasSelectionComponent()) {
+ selection.cut2ClipBoard(CLIP_BOARD);
+ designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED);
+ designer.repaint();
+ }
+ }
+
+ /**
+ * 复制当前选中的组件到剪切板
+ */
+ public void copySelectedCreator2ClipBoard() {
+ if (!selection.isEmpty()) {
+ selection.copy2ClipBoard(CLIP_BOARD);
+ }
+ }
+
+ /**
+ * 从剪切板粘帖组件
+ * @return 否
+ */
+ public boolean pasteFromClipBoard() {
+ if (!CLIP_BOARD.isEmpty()) {
+ XLayoutContainer parent = null;
+ if (!hasSelectionComponent()) {
+ FormSelectionUtils.paste2Container(designer, designer.getRootComponent(),CLIP_BOARD, DELTA_X_Y, DELTA_X_Y);
+ } else {
+ parent = XCreatorUtils.getParentXLayoutContainer(selection.getSelectedCreator());
+ if (parent != null) {
+ Rectangle rec = selection.getSelctionBounds();
+ FormSelectionUtils.paste2Container(designer, parent,CLIP_BOARD, rec.x + DELTA_X_Y, rec.y + DELTA_X_Y);
+ }
+ }
+ } else {
+ Toolkit.getDefaultToolkit().beep();
+ }
+ return false;
+ }
+
+ public FormSelection getSelection() {
+ return selection;
+ }
+
+ /**
+ * 删除当前所有选择的组件
+ */
+ public void deleteSelection() {
+ XCreator[] roots = selection.getSelectedCreators();
+
+ if (roots.length > 0) {
+ for (XCreator creator : roots) {
+ if(creator.acceptType(XWParameterLayout.class)){
+ designer.removeParaComponent();
+ }
+
+ removeCreatorFromContainer(creator, creator.getWidth(), creator.getHeight());
+ creator.removeAll();
+ // 清除被选中的组件
+ selection.reset();
+ }
+ setSelectedCreator(designer.getRootComponent());
+ // 触发事件
+ designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_DELETED);
+ designer.repaint();
+ }
+ }
+
+ /**
+ * 从选择组件中删除某组件
+ *
+ * @param creator 组件
+ * @param creatorWidth 组件之前宽度
+ * @param creatorHeight 组件之前高度
+ */
+ public void removeCreator(XCreator creator, int creatorWidth, int creatorHeight) {
+ selection.removeCreator(creator);
+ removeCreatorFromContainer(creator, creatorWidth, creatorHeight);
+ designer.repaint();
+ }
+
+ /**
+ * 设置选择区域
+ */
+ public void setHotspotBounds(Rectangle rect) {
+ hotspot_bounds = rect;
+ }
+
+ /**
+ * 获得当前选择区域
+ */
+ public Rectangle getHotspotBounds() {
+ return hotspot_bounds;
+ }
+
+ private void removeCreatorFromContainer(XCreator creator, int creatorWidth, int creatorHeight) {
+ XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator);
+ if (parent == null) {
+ return;
+ }
+ boolean changeCreator = creator.shouldScaleCreator() || creator.hasTitleStyle();
+ if (parent.acceptType(XWFitLayout.class) && changeCreator) {
+ creator = (XCreator) creator.getParent();
+ }
+ parent.getLayoutAdapter().removeBean(creator, creatorWidth, creatorHeight);
+ // 删除其根组件,同时就删除了同时被选择的叶子组件
+ parent.remove(creator);
+ LayoutManager layout = parent.getLayout();
+
+ if (layout != null) {
+ // 刷新组件容器的布局
+ LayoutUtils.layoutContainer(parent);
+ }
+ }
+
+ /**
+ * 是否有组件被选择。如果所选组件是最底层容器,也视为无选择
+ * @return 是则返回true
+ */
+ public boolean hasSelectionComponent() {
+ return !selection.isEmpty() && selection.getSelectedCreator().getParent() != null;
+ }
+
+ /**
+ * 移动组件至指定位置
+ * @param x 坐标x
+ * @param y 坐标y
+ */
+ public void move(int x, int y) {
+ for (XCreator creator : selection.getSelectedCreators()) {
+ creator.setLocation(creator.getX() + x, creator.getY() + y);
+ LayoutAdapter layoutAdapter = AdapterBus.searchLayoutAdapter(designer, creator);
+ if (layoutAdapter != null) {
+ layoutAdapter.fix(creator);
+ }
+ }
+ designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
+ DesignerEvent.CREATOR_SELECTED);
+ }
+
+ /**
+ * 释放捕获
+ */
+ public void releaseDragging() {
+ designer.setPainter(null);
+ selection.fixCreator(designer);
+ designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
+ DesignerEvent.CREATOR_RESIZED);
+ }
+
+ public Direction getDirectionAt(MouseEvent e) {
+ Direction dir;
+ if (e.isControlDown() || e.isShiftDown()) {
+ XCreator creator = designer.getComponentAt(e.getX(), e.getY(), selection.getSelectedCreators());
+ if (creator != designer.getRootComponent() && selection.addedable(creator)) {
+ return Location.add;
+ }
+ }
+ if (hasSelectionComponent()) {
+ int x = e.getX() + designer.getArea().getHorizontalValue();
+ int y = e.getY() + designer.getArea().getVerticalValue();
+ dir = getDirection(selection.getRelativeBounds(), x, y);
+ if (selection.size() == 1) {
+ if (!ArrayUtils.contains(selection.getSelectedCreator().getDirections(), dir.getActual())) {
+ dir = Location.outer;
+ }
+ }
+ } else {
+ dir = Location.outer;
+ }
+
+ if (designer.getDesignerMode().isFormParameterEditor() && dir == Location.outer) {
+ dir = designer.getLoc2Root(e);
+ }
+ return dir;
+ }
+
+ private Direction getDirection(Rectangle bounds, int x, int y) {
+ if (x < (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) {
+ return Location.outer;
+ } else if ((x >= (bounds.x - XCreatorConstants.RESIZE_BOX_SIZ)) && (x <= bounds.x)) {
+ if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
+ return Location.outer;
+ } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
+ return Location.left_top;
+ } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
+ return Location.left;
+ } else if ((y >= (bounds.y + bounds.height))
+ && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
+ return Location.left_bottom;
+ } else {
+ return Location.outer;
+ }
+ } else if ((x > bounds.x) && (x < (bounds.x + bounds.width))) {
+ if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
+ return Location.outer;
+ } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
+ return Location.top;
+ } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
+ return Location.inner;
+ } else if ((y >= (bounds.y + bounds.height))
+ && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
+ return Location.bottom;
+ } else {
+ return Location.outer;
+ }
+ } else if ((x >= (bounds.x + bounds.width))
+ && (x <= (bounds.x + bounds.width + XCreatorConstants.RESIZE_BOX_SIZ))) {
+ if (y < (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) {
+ return Location.outer;
+ } else if ((y >= (bounds.y - XCreatorConstants.RESIZE_BOX_SIZ)) && (y <= bounds.y)) {
+ return Location.right_top;
+ } else if ((y > bounds.y) && (y < (bounds.y + bounds.height))) {
+ return Location.right;
+ } else if ((y >= (bounds.y + bounds.height))
+ && (y <= (bounds.y + bounds.height + XCreatorConstants.RESIZE_BOX_SIZ))) {
+ return Location.right_bottom;
+ } else {
+ return Location.outer;
+ }
+ } else {
+ return Location.outer;
+ }
+ }
+
+ private void fireCreatorSelected() {
+ designer.getEditListenerTable().fireCreatorModified(selection.getSelectedCreator(),
+ DesignerEvent.CREATOR_SELECTED);
+ }
+
+ public void setSelectedCreator(XCreator rootComponent) {
+ selection.setSelectedCreator(rootComponent);
+ fireCreatorSelected();
+ }
+
+ public void setSelectedCreators(ArrayList rebuildSelection) {
+ selection.setSelectedCreators(rebuildSelection);
+ fireCreatorSelected();
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/models/StateModel.java b/designer_form/src/com/fr/design/designer/beans/models/StateModel.java
new file mode 100644
index 000000000..d92cd9c76
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/models/StateModel.java
@@ -0,0 +1,433 @@
+package com.fr.design.designer.beans.models;
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import com.fr.design.beans.location.Absorptionline;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormSelectionUtils;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.designer.beans.location.Location;
+import com.fr.design.designer.creator.XConnector;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWAbsoluteLayout;
+import com.fr.design.utils.ComponentUtils;
+
+/**
+ * 普通模式下的状态model
+ */
+public class StateModel {
+ // 对应的selection model
+
+ private SelectionModel selectionModel;
+ // 当前鼠标进入拖拽区域的位置类型
+ private Direction driection;
+
+ // 当前拖拽的起始位置
+ private int current_x;
+ private int current_y;
+
+ private Point startPoint = new Point();
+ private Point currentPoint = new Point();
+
+ private Absorptionline lineInX;
+ private Absorptionline lineInY;
+
+ // 当前是否处于拖拽选择状态
+ private boolean selecting;
+ private boolean dragging;
+
+ private boolean addable;
+
+ private FormDesigner designer;
+
+ public StateModel(FormDesigner designer) {
+ this.designer = designer;
+ selectionModel = designer.getSelectionModel();
+ }
+
+ /**
+ * 返回direction
+ * @return direction方向
+ */
+ public Direction getDirection() {
+ return driection;
+ }
+
+ /**
+ * 是否有组件正被选中
+ *
+ * @return true 如果至少一个组件被选中
+ */
+ public boolean isSelecting() {
+ return selecting;
+ }
+
+ /**
+ *是否能拖拽
+ * @return 非outer且选中为空
+ */
+ public boolean dragable() {
+ return ((driection != Location.outer) && !selecting);
+ }
+
+ /**
+ * 拖拽中是否可以转换为添加模式:
+ * 如果拖拽组件只有一个,鼠标当前所在位置的最底层表单容器与这个组件的容器不同;
+ * 如果拖拽组件为多个,鼠标当前所在位置的最底层表单容器除了要求要跟这些组件的容器不同外,还必须是绝对定位布局
+ */
+ private void checkAddable(MouseEvent e) {
+ addable = false;
+ designer.setPainter(null);
+
+ if (driection != Location.inner) {
+ return;
+ }
+
+ XCreator comp = designer.getComponentAt(e.getX(), e.getY(), selectionModel.getSelection().getSelectedCreators());
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(comp);
+ XCreator creator = selectionModel.getSelection().getSelectedCreator();
+ Component creatorContainer = XCreatorUtils.getParentXLayoutContainer(creator);
+ if (creatorContainer != null && creatorContainer != container
+ && (selectionModel.getSelection().size() == 1 || container instanceof XWAbsoluteLayout)) {
+ HoverPainter painter = AdapterBus.getContainerPainter(designer, container);
+ designer.setPainter(painter);
+ if (painter != null) {
+ Rectangle rect = ComponentUtils.getRelativeBounds(container);
+ rect.x -= designer.getArea().getHorizontalValue();
+ rect.y -= designer.getArea().getVerticalValue();
+ painter.setRenderingBounds(rect);
+ painter.setHotspot(new Point(e.getX(), e.getY()));
+ painter.setCreator(creator);
+ }
+ addable = true;
+ }
+ }
+
+ private boolean addBean(XLayoutContainer container, int x, int y) {
+ LayoutAdapter adapter = container.getLayoutAdapter();
+ Rectangle r = ComponentUtils.getRelativeBounds(container);
+ if (selectionModel.getSelection().size() == 1) {
+ return adapter.addBean(selectionModel.getSelection().getSelectedCreator(), x
+ + designer.getArea().getHorizontalValue() - r.x, y + designer.getArea().getVerticalValue() - r.y);
+ }
+ for (XCreator creator : selectionModel.getSelection().getSelectedCreators()) {
+ adapter.addBean(creator, x + designer.getArea().getHorizontalValue() - r.x, y + designer.getArea().getVerticalValue()- r.y);
+ }
+ return true;
+ }
+
+ private void adding(int x, int y) {
+ // 当前鼠标所在的组件
+ XCreator hoveredComponent = designer.getComponentAt(x, y, selectionModel.getSelection().getSelectedCreators());
+
+ // 获取该组件所在的焦点容器
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent);
+
+ boolean success = false;
+
+ if (container != null) {
+ // 如果是容器,则调用其acceptComponent接受组件
+ success = addBean(container, x, y);
+ }
+
+ if (success) {
+ FormSelectionUtils.rebuildSelection(designer);
+ designer.getEditListenerTable().fireCreatorModified(
+ selectionModel.getSelection().getSelectedCreator(), DesignerEvent.CREATOR_ADDED);
+ } else {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ // 取消提示
+ designer.setPainter(null);
+ }
+
+ /**
+ *是否拖拽
+ * @return dragging状态
+ */
+ public boolean isDragging() {
+ return dragging;
+ }
+
+ /**
+ *是否可以开始画线
+ * @return startPoint不为空返回true
+ */
+ public boolean prepareForDrawLining() {
+ return startPoint != null;
+ }
+
+ /**
+ *设置开始位置
+ * @param p point位置
+ */
+ public void setStartPoint(Point p) {
+ this.startPoint = p;
+ }
+
+ /**
+ *返回开始位置
+ * @return 点位置
+ */
+ public Point getStartPoint() {
+ return startPoint;
+ }
+
+ /**
+ *返回当前点位置
+ * @return 点位置
+ */
+ public Point getEndPoint() {
+ return currentPoint;
+ }
+
+ /**
+ *当前选中组件
+ * @param e 鼠标事件
+ */
+ public void startSelecting(MouseEvent e) {
+ selecting = true;
+ selectionModel.setHotspotBounds(new Rectangle());
+ current_x = getMouseXY(e).x;
+ current_y = getMouseXY(e).y;
+ }
+
+ /**
+ *当前鼠标的xy
+ * @param e 鼠标事件
+ */
+ public void startResizing(MouseEvent e) {
+ if (!selectionModel.getSelection().isEmpty()) {
+ driection.backupBounds(designer);
+ }
+ current_x = getMouseXY(e).x;
+ current_y = getMouseXY(e).y;
+ }
+
+ /**
+ *起始点开始DrawLine
+ * @param p 点位置
+ */
+ public void startDrawLine(Point p) {
+ this.startPoint = p;
+ if(p != null) {
+ try {
+ designer.setCursor(XConnector.connectorCursor);
+ } catch (Exception e) {
+ }
+ } else {
+ designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
+ }
+
+ /**
+ *鼠标释放时所在的区域及圈中的组件
+ * @param e 鼠标事件
+ */
+ public void selectCreators(MouseEvent e) {
+ int x = getMouseXY(e).x;
+ int y = getMouseXY(e).y;
+
+ Rectangle bounds = createCurrentBounds(x, y);
+
+ if ((x != current_x) || (y != current_y)) {
+ selectionModel.setSelectedCreators(getHotspotCreators(bounds, designer.getRootComponent()));
+ }
+ selectionModel.setHotspotBounds(null);
+ }
+
+ /**
+ *画所在区域线
+ * @param e 鼠标事件
+ */
+ public void drawLine(MouseEvent e) {
+ designer.getDrawLineHelper().setDrawLine(true);
+ Point p = designer.getDrawLineHelper().getNearWidgetPoint(e);
+ if (p != null) {
+ currentPoint = p;
+ } else {
+ currentPoint.x = e.getX() + designer.getArea().getHorizontalValue();
+ currentPoint.y = e.getY() + designer.getArea().getVerticalValue();
+ }
+ }
+
+ private Rectangle createCurrentBounds(int x, int y) {
+ Rectangle bounds = new Rectangle();
+
+ bounds.x = Math.min(x, current_x);
+ bounds.y = Math.min(y, current_y);
+ bounds.width = Math.max(x, current_x) - bounds.x;
+ bounds.height = Math.max(y, current_y) - bounds.y;
+
+ return bounds;
+ }
+
+ private ArrayList getHotspotCreators(Rectangle selection, XCreator root) {
+ ArrayList creators = new ArrayList();
+
+ if (!root.isVisible() && !designer.isRoot(root)) {
+ return creators;
+ }
+
+ if (root instanceof XLayoutContainer) {
+ XLayoutContainer container = (XLayoutContainer) root;
+ int count = container.getXCreatorCount();
+ Rectangle clipped = new Rectangle(selection);
+
+ for (int i = count - 1; i >= 0; i--) {
+ XCreator child = container.getXCreator(i);
+
+ if (selection.contains(child.getBounds())) {
+ creators.add(child);
+ } else {
+ clipped.x = selection.x - child.getX();
+ clipped.y = selection.y - child.getY();
+ creators.addAll(getHotspotCreators(clipped, child));
+ }
+ }
+ }
+
+ return creators;
+ }
+
+
+ /**
+ *重置model
+ */
+ public void resetModel() {
+ dragging = false;
+ selecting = false;
+ }
+
+ /**
+ *重置
+ */
+ public void reset() {
+ driection = Location.outer;
+ dragging = false;
+ selecting = false;
+ }
+
+ /**
+ *取消拖拽
+ */
+ public void draggingCancel() {
+ designer.repaint();
+ reset();
+ }
+
+ /**
+ *设置可拉伸方向
+ * @param dir 拉伸方向
+ */
+ public void setDirection(Direction dir) {
+ if(driection != dir) {
+ this.driection = dir;
+ driection.updateCursor(designer);
+ }
+ }
+
+ /**
+ *x吸附线赋值
+ * @param line 线
+ */
+ public void setXAbsorptionline(Absorptionline line) {
+ this.lineInX = line;
+ }
+
+ /**
+ *y吸附线赋值
+ * @param line 线
+ */
+ public void setYAbsorptionline(Absorptionline line) {
+ this.lineInY = line;
+ }
+
+ /**
+ *画吸附线
+ * @param g Graphics类
+ */
+ public void paintAbsorptionline(Graphics g) {
+ if(lineInX != null) {
+ lineInX.paint(g,designer.getArea());
+ }
+ if(lineInY != null) {
+ lineInY.paint(g,designer.getArea());
+ }
+ }
+
+ /**
+ *拖拽
+ * @param e 鼠标事件
+ */
+ public void dragging(MouseEvent e) {
+ checkAddable(e);
+ setDependLinePainter(e);
+ driection.drag(getMouseXY(e).x-current_x, getMouseXY(e).y-current_y, designer);
+ this.dragging = true;
+ }
+
+ // 拖拽时画依附线用到的painter
+ private void setDependLinePainter(MouseEvent e){
+ XCreator comp = designer.getComponentAt(e.getX(), e.getY(), selectionModel.getSelection().getSelectedCreators());
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(comp);
+ XCreator creator = selectionModel.getSelection().getSelectedCreator();
+ HoverPainter painter = AdapterBus.getContainerPainter(designer, container);
+ designer.setPainter(painter);
+ if (painter != null) {
+ painter.setHotspot(new Point(e.getX(), e.getY()));
+ painter.setCreator(creator);
+ }
+ }
+
+ /**
+ *释放捕获
+ * @param e 鼠标事件
+ */
+ public void releaseDragging(MouseEvent e) {
+ this.dragging = false;
+ if (addable) {
+ adding(e.getX(), e.getY());
+ } else if (!selectionModel.getSelection().isEmpty()) {
+ selectionModel.releaseDragging();
+ }
+ designer.repaint();
+ }
+
+ /**
+ *改变选择区域
+ *
+ * @param e 鼠标事件
+ */
+ public void changeSelection(MouseEvent e) {
+ Rectangle bounds = createCurrentBounds(getMouseXY(e).x, getMouseXY(e).y);
+ selectionModel.setHotspotBounds(bounds);
+ }
+
+ /**
+ *返回鼠标所在的x、y 考虑滚动条的值
+ *
+ * @param e 鼠标事件
+ * @return xy值
+ */
+ public Point getMouseXY(MouseEvent e) {
+ Point p1 = new Point(e.getX() + designer.getArea().getHorizontalValue(), e.getY()
+ + designer.getArea().getVerticalValue());
+ return p1;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/AbstractPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/AbstractPainter.java
new file mode 100644
index 000000000..06565fe4f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/AbstractPainter.java
@@ -0,0 +1,93 @@
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+
+public abstract class AbstractPainter implements HoverPainter {
+
+ protected Point hotspot;
+ protected Rectangle hotspot_bounds;
+ protected XLayoutContainer container;
+ protected XCreator creator;
+
+ /**
+ * 构造函数
+ * @param container 容器
+ */
+ public AbstractPainter(XLayoutContainer container) {
+ this.container = container;
+ }
+
+ @Override
+ public void setHotspot(Point p) {
+ hotspot = p;
+ }
+
+ /**
+ * 画初始区域
+ * @param g 画图类
+ * @param startX 起始x位置
+ * @param startY 起始y位置
+ */
+ public void paint(Graphics g, int startX, int startY) {
+ if(hotspot_bounds != null){
+ drawHotspot(g, hotspot_bounds.x, hotspot_bounds.y, hotspot_bounds.width, hotspot_bounds.height, Color.lightGray, true, false);
+ }
+ }
+
+ /**
+ * 设置边界
+ * @param rect 位置
+ */
+ @Override
+ public void setRenderingBounds(Rectangle rect) {
+ hotspot_bounds = rect;
+ }
+
+ @Override
+ public void setCreator(XCreator component) {
+ this.creator = component;
+ }
+
+ protected void drawHotspot(Graphics g, int x, int y, int width, int height, boolean accept) {
+ Color bColor = accept ? XCreatorConstants.LAYOUT_HOTSPOT_COLOR : XCreatorConstants.LAYOUT_FORBIDDEN_COLOR;
+ drawHotspot(g, x, y, width, height, bColor, accept, false);
+ }
+
+ /**
+ * 自适应布局那边渲染提示,要画整个背景,不是画边框
+ */
+ protected void drawRegionBackground(Graphics g, int x, int y, int width, int height, Color bColor, boolean accept) {
+ drawHotspot(g, x, y, width, height, bColor, accept, true);
+ }
+
+ protected void drawHotspot(Graphics g, int x, int y, int width, int height, Color bColor, boolean accept, boolean drawBackground) {
+ Graphics2D g2d = (Graphics2D) g;
+ Color color = g2d.getColor();
+ Stroke backup = g2d.getStroke();
+ // 设置线条的样式
+ g2d.setStroke(XCreatorConstants.STROKE);
+ g2d.setColor(bColor);
+ if (!accept) {
+ g2d.drawString(Inter.getLocText("Cannot-Add_To_This_Area") + "!", x + width / 3, y + height / 2);
+ } else if (drawBackground) {
+ g2d.fillRect(x, y, width, height);
+ } else {
+ g2d.drawRect(x, y, width, height);
+ }
+ g2d.setStroke(backup);
+ g2d.setColor(color);
+ }
+
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRBorderLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRBorderLayoutPainter.java
new file mode 100644
index 000000000..eeac7593f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRBorderLayoutPainter.java
@@ -0,0 +1,140 @@
+package com.fr.design.designer.beans.painters;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Graphics;
+
+import com.fr.design.designer.beans.adapters.layout.FRBorderLayoutAdapter;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.form.layout.FRBorderLayout;
+import com.fr.form.ui.container.WBorderLayout;
+
+public class FRBorderLayoutPainter extends AbstractPainter {
+
+ public FRBorderLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public void paint(Graphics g, int startX, int startY) {
+ super.paint(g, startX, startY);
+ int x = hotspot.x;
+ int y = hotspot.y;
+ int hotspot_x = hotspot_bounds.x;
+ int hotspot_y = hotspot_bounds.y;
+ int hotspot_w = hotspot_bounds.width;
+ int hotspot_h = hotspot_bounds.height;
+ FRBorderLayoutAdapter adapter = (FRBorderLayoutAdapter) container.getLayoutAdapter();
+ FRBorderLayout layout = (FRBorderLayout) container.getLayout();
+ boolean accept = adapter.accept(creator, x - hotspot_x, y - hotspot_y);
+ WBorderLayout wLayout = ((XWBorderLayout)container).toData();
+ int northHeight = wLayout.getNorthSize();
+ int southHeight = wLayout.getSouthSize();
+ int eastWidth = wLayout.getEastSize();
+ int westWidth = wLayout.getWestSize();
+
+ int really_x = hotspot_x;
+ int really_y = hotspot_y;
+ int really_w = hotspot_w;
+ int really_h = hotspot_h;
+
+ if (y < (hotspot_y + northHeight)) {
+ // NORTH
+ really_x = hotspot_x;
+ really_y = hotspot_y;
+ really_w = hotspot_w;
+ really_h = northHeight;
+ } else if ((y >= (hotspot_y + northHeight)) && (y < ((hotspot_y + hotspot_h) - southHeight))) {
+ if (x < (hotspot_x + westWidth)) {
+ // WEST
+ Component north = layout.getLayoutComponent(BorderLayout.NORTH);
+ Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
+ really_x = hotspot_x;
+ really_y = hotspot_y;
+
+ if (north != null) {
+ really_y += northHeight;
+ }
+
+ really_w = westWidth;
+ really_h = hotspot_h;
+
+ if (north != null) {
+ really_h -= northHeight;
+ }
+
+ if (south != null) {
+ really_h -= southHeight;
+ }
+ } else if ((x >= (hotspot_x + westWidth)) && (x < ((hotspot_x + hotspot_w) - eastWidth))) {
+ // CENTER
+ Component north = layout.getLayoutComponent(BorderLayout.NORTH);
+ Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
+ Component east = layout.getLayoutComponent(BorderLayout.EAST);
+ Component west = layout.getLayoutComponent(BorderLayout.WEST);
+ really_x = hotspot_x;
+
+ if (west != null) {
+ really_x += westWidth;
+ }
+
+ really_y = hotspot_y;
+
+ if (north != null) {
+ really_y += northHeight;
+ }
+
+ really_w = hotspot_w;
+
+ if (west != null) {
+ really_w -= westWidth;
+ }
+
+ if (east != null) {
+ really_w -= eastWidth;
+ }
+
+ really_h = hotspot_h;
+
+ if (north != null) {
+ really_h -= northHeight;
+ }
+
+ if (south != null) {
+ really_h -= southHeight;
+ }
+ } else {
+ // EAST
+ Component north = layout.getLayoutComponent(BorderLayout.NORTH);
+ Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
+
+ really_x = (hotspot_x + hotspot_w) - eastWidth;
+ really_y = hotspot_y;
+
+ if (north != null) {
+ really_y += northHeight;
+ }
+
+ really_w = eastWidth;
+ really_h = hotspot_h;
+
+ if (north != null) {
+ really_h -= northHeight;
+ }
+
+ if (south != null) {
+ really_h -= southHeight;
+ }
+ }
+ } else {
+ // SOUTH
+ really_x = hotspot_x;
+ really_y = (hotspot_y + hotspot_h) - southHeight;
+ really_w = hotspot_w;
+ really_h = southHeight;
+ }
+
+ drawHotspot(g, really_x, really_y, really_w, really_h, accept);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRBoxLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRBoxLayoutPainter.java
new file mode 100644
index 000000000..a83451c2f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRBoxLayoutPainter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.form.util.XCreatorConstants;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class FRBoxLayoutPainter extends AbstractPainter {
+
+ public FRBoxLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+ protected int[] calculateAddPosition(int x, int y) {
+ int[] result = new int[2];
+ int count = container.getComponentCount();
+ for (int i = 0; i < count; i++) {
+ Component c1 = container.getComponent(i);
+ if(i == 0) {
+ result[0] = c1.getBounds().x;
+ result[1] = c1.getBounds().y;
+ }
+ Component c2 = null;
+ if (i < count - 1) {
+ c2 = container.getComponent(i + 1);
+ }
+ if (c2 != null) {
+ if (x > c1.getBounds().x && x < c2.getBounds().x) {
+ result[0] = c1.getBounds().x + c1.getBounds().width;
+ } else if (x <= c1.getBounds().x && result[0] > c1.getBounds().x) {
+ result[0] = c1.getBounds().x;
+ }
+ if (y > c1.getBounds().y && y < c2.getBounds().y) {
+ result[1] = c1.getBounds().y + c1.getSize().height;
+ } else if (y <= c1.getBounds().y && result[1] > c1.getBounds().y) {
+ result[1] = c1.getBounds().y;
+ }
+ } else {
+ if (x > c1.getBounds().x) {
+ result[0] = c1.getBounds().x + c1.getBounds().width;
+ }
+ if (y > c1.getBounds().y) {
+ result[1] = c1.getBounds().y + c1.getSize().height;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected void drawHotLine(Graphics g, int startX, int startY, int x1, int y1, int x2, int y2) {
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setPaint(XCreatorConstants.LAYOUT_HOTSPOT_COLOR);
+ g2d.setStroke(XCreatorConstants.STROKE);
+ g2d.drawLine(x1 - startX, y1 - startY, x2 - startY, y2 - startY);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRFitLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRFitLayoutPainter.java
new file mode 100644
index 000000000..79f735684
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRFitLayoutPainter.java
@@ -0,0 +1,249 @@
+/**
+ *
+ */
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Stroke;
+
+import com.fr.design.designer.beans.adapters.layout.FRFitLayoutAdapter;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
+import com.fr.general.ComparatorUtils;
+
+/**
+ * @author jim
+ * @date 2014-7-14
+ */
+public class FRFitLayoutPainter extends AbstractPainter{
+
+ private static final int BORDER_PROPORTION = 10;
+ private static final int X = 0;
+ private static final int Y = 1;
+ private static final int WIDTH = 2;
+ private static final int HEIGHT = 3;
+
+ private static final Color DEPEND_LINE_COLOR = new Color(200,200,200);
+ private static final int DEPEND_LINE_SOCOPE = 3;
+
+ /**
+ * 构造函数
+ * @param container
+ */
+ public FRFitLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+ /**
+ * 组件渲染
+ * @param g 画图类
+ * @param startX 开始位置x
+ * @param startY 开始位置y
+ */
+ @Override
+ public void paint(Graphics g, int startX, int startY) {
+ if(hotspot_bounds == null && creator != null && container != null){
+ drawDependingLine(g);
+ return;
+ }
+ super.paint(g, startX, startY);
+ int x = hotspot.x - hotspot_bounds.x;
+ int y = hotspot.y - hotspot_bounds.y;
+ FRFitLayoutAdapter adapter = (FRFitLayoutAdapter) container.getLayoutAdapter();
+ Component currentComp = container.getComponentAt(x, y);
+ if (currentComp == null ) {
+ return;
+ }
+ int[] hot_rec = new int[]{hotspot_bounds.x, hotspot_bounds.y, hotspot_bounds.width, hotspot_bounds.height};
+ boolean accept = adapter.accept(creator, x, y);
+ Color bColor = XCreatorConstants.FIT_LAYOUT_HOTSPOT_COLOR;
+ if (accept) {
+ y = y==container.getHeight() ? y-1 : y;
+ x = x==container.getWidth() ? x-1 : x;
+ hot_rec = adapter.getChildPosition(currentComp, creator, x, y);
+ } else {
+ bColor = XCreatorConstants.LAYOUT_FORBIDDEN_COLOR;
+ Rectangle rec = currentComp.getBounds();
+ hot_rec = currentComp == container ? new int[]{x, y, 0, 0} : new int[]{rec.x, rec.y, rec.width, rec.height};
+ }
+ // tab布局的边界提示区域
+ if(!ComparatorUtils.equals(container.getBackupParent(),container.getOuterLayout()) && adapter.intersectsEdge(x, y, container)){
+ dealHotspotOfTab(hot_rec,container,x,y,bColor,g,accept);
+ return;
+ }
+ hot_rec[X] += hotspot_bounds.x;
+ hot_rec[Y] += hotspot_bounds.y;
+ drawRegionBackground(g, hot_rec[X], hot_rec[Y], hot_rec[WIDTH], hot_rec[HEIGHT], bColor, accept);
+ if (accept) {
+ //画交叉区域和中间点区域
+ // 拖入的区域也改为整个渲染,点区域的后画下,不然被遮住了
+ paintCrossPoint(currentComp, g, x, y);
+ }
+ }
+
+ private void dealHotspotOfTab(int[] hot_rec,XLayoutContainer container,int x,int y,Color bColor,Graphics g,boolean accept){
+ int containerX = container.getX();
+ int containerY = container.getY();
+ int containerWidth = container.getWidth();
+ int containerHeight = container.getHeight();
+ // 当前坐标点
+ Rectangle currentXY = new Rectangle(x, y, 1, 1);
+ // 上边缘
+ Rectangle upEdge = new Rectangle(containerX, containerY, containerWidth, BORDER_PROPORTION);
+ if(upEdge.intersects(currentXY)){
+ hotspot_bounds.y -= WCardMainBorderLayout.TAB_HEIGHT;
+ hot_rec[WIDTH] = container.getWidth();
+ hot_rec[HEIGHT] = (container.getHeight() + WCardMainBorderLayout.TAB_HEIGHT)/2;
+ }
+
+ int bottomY = containerY + containerHeight - BORDER_PROPORTION;
+ // 下边缘
+ Rectangle bottomEdge = new Rectangle(containerX, bottomY, containerWidth, BORDER_PROPORTION);
+ if(bottomEdge.intersects(currentXY)){
+ hotspot_bounds.y -= WCardMainBorderLayout.TAB_HEIGHT/2;
+ hot_rec[WIDTH] = container.getWidth();
+ hot_rec[HEIGHT] = (container.getHeight() + WCardMainBorderLayout.TAB_HEIGHT)/2;
+ accept = false;
+ }
+
+ //左右边缘的高度 -10*2 是为了不和上下边缘重合
+ int verticalHeight = containerHeight - BORDER_PROPORTION * 2;
+ int leftY = containerY + BORDER_PROPORTION;
+ // 左边缘
+ Rectangle leftEdge = new Rectangle(containerX, leftY, BORDER_PROPORTION, verticalHeight);
+ if(leftEdge.intersects(currentXY)){
+ hotspot_bounds.y -= WCardMainBorderLayout.TAB_HEIGHT;
+ hot_rec[WIDTH] = container.getWidth()/2;
+ hot_rec[HEIGHT] = (container.getHeight() + WCardMainBorderLayout.TAB_HEIGHT);
+ }
+
+ int rightY = containerY + BORDER_PROPORTION;
+ int rightX = containerX + containerWidth - BORDER_PROPORTION;
+ // 右边缘
+ Rectangle rightEdge = new Rectangle(rightX, rightY, BORDER_PROPORTION, verticalHeight);
+ if(rightEdge.intersects(currentXY)){
+ hotspot_bounds.y -= WCardMainBorderLayout.TAB_HEIGHT;
+ hotspot_bounds.x += container.getWidth()/2;
+ hot_rec[WIDTH] = container.getWidth()/2;
+ hot_rec[HEIGHT] = (container.getHeight() + WCardMainBorderLayout.TAB_HEIGHT);
+ }
+ hot_rec[X] += hotspot_bounds.x;
+ hot_rec[Y] += hotspot_bounds.y;
+ drawRegionBackground(g, hot_rec[X], hot_rec[Y], hot_rec[WIDTH], hot_rec[HEIGHT], bColor,accept);
+ }
+
+ private void paintCrossPoint(Component currentComp, Graphics g, int x, int y) {
+ if (currentComp == container) {
+ return;
+ }
+ Color bColor = XCreatorConstants.FIT_LAYOUT_POINT_COLOR;
+ int cX = currentComp.getX(), cY = currentComp.getY(), cH = currentComp.getHeight(), cW = currentComp.getWidth();
+ int defaultWidth = cW/BORDER_PROPORTION, defaultHeight = cH/BORDER_PROPORTION;
+ // 交叉点提示区域最大值为10px
+ int defaultLength = Math.min(BORDER_PROPORTION, Math.min(defaultWidth, defaultHeight));
+ Component topComp = container.getTopComp(cX, cY);
+ Component bottomComp = container.getBottomComp(cX, cY, cH);
+ Component rightComp = container.getRightComp(cX, cY, cW); //组件的左右组件要区分上侧和下侧
+ Component leftComp = container.getLeftComp(cX, cY);
+ boolean top = topComp!=null && topComp!=container, left = leftComp!=null && leftComp!=container,bottom = bottomComp!=null && bottomComp!=container,right = rightComp!=null && rightComp!=container;
+ if (top || left) {
+ drawRegionBackground(g, cX+hotspot_bounds.x, cY+hotspot_bounds.y, defaultLength, defaultLength, bColor, true);
+ }
+ if (bottom || left) {
+ drawRegionBackground(g, cX+hotspot_bounds.x, cY+cH-defaultLength+hotspot_bounds.y, defaultLength, defaultLength, bColor,true);
+ }
+ if (top || right) {
+ drawRegionBackground(g, cX+cW-defaultLength+hotspot_bounds.x, cY+hotspot_bounds.y, defaultLength, defaultLength, bColor,true);
+ }
+ if (bottom || right) {
+ drawRegionBackground(g, cX+cW-defaultLength+hotspot_bounds.x, cY+cH-defaultLength+hotspot_bounds.y, defaultLength, defaultLength, bColor,true);
+ }
+ if (left && right) {
+ if (leftComp.getY()==cY && rightComp.getY()==cY) {
+ drawRegionBackground(g, cX+cW/2-defaultWidth+hotspot_bounds.x, cY+hotspot_bounds.y, defaultWidth*2, defaultLength, bColor,true);
+ }
+ //底边线位置,左右组件都不为null且低端对齐,取左、右靠下侧组件判断
+ leftComp = container.getBottomLeftComp(cX, cY, cH);
+ rightComp = container.getBottomRightComp(cX, cY, cH, cW);
+ if (leftComp.getY()+leftComp.getHeight()==cY+cH && rightComp.getY()+rightComp.getHeight()==cY+cH) {
+ drawRegionBackground(g, cX+cW/2-defaultWidth+hotspot_bounds.x, cY+cH-defaultLength+hotspot_bounds.y, defaultWidth*2, defaultLength, bColor,true);
+ }
+ }
+ if (top && bottom) {
+ if (topComp.getX()==cX && bottomComp.getX()==cX) {
+ drawRegionBackground(g, cX+hotspot_bounds.x, cY+cH/2-defaultHeight+hotspot_bounds.y, defaultLength, defaultHeight*2, bColor,true);
+ }
+ // 右边线位置,上下组件不为null且右端对齐,取上、下靠右侧组件判断
+ topComp = container.getRightTopComp(cX, cY, cW);
+ bottomComp = container.getRightBottomComp(cX, cY, cH, cW);
+ if (topComp.getX()+topComp.getWidth()==cX+cW && bottomComp.getX()+bottomComp.getWidth()==cX+cW) {
+ drawRegionBackground(g, cX+cW-defaultLength+hotspot_bounds.x, cY+cH/2-defaultHeight+hotspot_bounds.y, defaultLength, defaultHeight*2, bColor,true);
+ }
+ }
+ }
+
+ // 画依附线
+ private void drawDependingLine(Graphics g){
+ Graphics2D g2d = (Graphics2D) g;
+ Stroke backup = g2d.getStroke();
+
+ // 当前拖拽组件的坐标
+ int oriX = creator.getX();
+ int oriY = creator.getY();
+
+ // 拖拽位置的即时坐标
+ double x = hotspot.getX();
+ double y = hotspot.getY();
+
+ // 容器所有的内部组件的横纵坐标值
+ int[] posXs = container.getHors();
+ int[] posYs = container.getVeris();
+
+ // 依附线的坐标
+ int lineX = 0;
+ int lineY = 0;
+
+ // 根据拖拽位置调整依附线的坐标
+ lineX = getDependLinePos(lineX, posXs, oriX, x);
+ lineY = getDependLinePos(lineY, posYs, oriY, y);
+
+
+ g2d.setStroke(backup);
+ g2d.setColor(DEPEND_LINE_COLOR);
+ if(lineX != 0){
+ g2d.drawRect(lineX, 0, 0, container.getHeight());
+ }
+ if(lineY != 0){
+ g2d.drawRect(0, lineY, container.getWidth(), 0);
+ }
+
+ }
+
+ /**
+ * 根据容器内部组件的横纵坐标值画依附线
+ *
+ * @param lineCoordinate 依附线坐标值
+ * @param referCoordinates 容器内部所有组件坐标值
+ * @param oriCoordinate 当前拖拽组件坐标
+ * @param currentCoordinate 拖拽位置的即时坐标
+ * @return 依附线的坐标
+ *
+ */
+ private int getDependLinePos(int lineCoordinate,int referCoordinates[],int oriCoordinate,double currentCoordinate){
+ for(int i=0; i referCoordinates[i]-DEPEND_LINE_SOCOPE && currentCoordinate < referCoordinates[i] + DEPEND_LINE_SOCOPE){
+ lineCoordinate = referCoordinates[i];
+ break;
+ }
+ }
+ return lineCoordinate;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutAnchorPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutAnchorPainter.java
new file mode 100644
index 000000000..d8aa3a096
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutAnchorPainter.java
@@ -0,0 +1,48 @@
+package com.fr.design.designer.beans.painters;
+
+import java.awt.BasicStroke;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Stroke;
+
+import com.fr.design.designer.beans.adapters.layout.AbstractAnchorPainter;
+import com.fr.design.form.layout.FRGridLayout;
+import com.fr.design.form.util.XCreatorConstants;
+
+public class FRGridLayoutAnchorPainter extends AbstractAnchorPainter {
+
+ protected FRGridLayout grid_layout;
+
+ public FRGridLayoutAnchorPainter(Container container) {
+ super(container);
+ grid_layout = (FRGridLayout) container.getLayout();
+ }
+
+ @Override
+ public void paint(Graphics g, int startX, int startY) {
+ int columns = grid_layout.getColumns();
+ int rows = grid_layout.getRows();
+ int width = hotspot.width;
+ int height = hotspot.height;
+ Graphics2D g2d = (Graphics2D) g;
+ Stroke back = g2d.getStroke();
+ g2d.setStroke(new BasicStroke(1));
+ g.setColor(XCreatorConstants.LAYOUT_SEP_COLOR);
+ g.drawRect(hotspot.x, hotspot.y, hotspot.width, hotspot.height);
+
+ if (columns != 0) {
+ for (int i = 1; i < columns; i++) {
+ int x = (i * width) / columns;
+ g.drawLine(hotspot.x + x, hotspot.y, hotspot.x + x, hotspot.y + height);
+ }
+ }
+ if (rows != 0) {
+ for (int i = 1; i < rows; i++) {
+ int y = (i * height) / rows;
+ g.drawLine(hotspot.x, hotspot.y + y, hotspot.x + width, hotspot.y + y);
+ }
+ }
+ g2d.setStroke(back);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutPainter.java
new file mode 100644
index 000000000..8e0b637dd
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRGridLayoutPainter.java
@@ -0,0 +1,51 @@
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Point;
+
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.form.util.XCreatorConstants;
+
+public class FRGridLayoutPainter extends FRGridLayoutAnchorPainter implements HoverPainter {
+
+ private Point point;
+ private XCreator current;
+
+ public FRGridLayoutPainter(Container container) {
+ super(container);
+ }
+
+ @Override
+ public void setHotspot(Point p) {
+ point = p;
+ }
+
+ @Override
+ public void setCreator(XCreator creator) {
+ this.current = creator;
+ }
+
+ @Override
+ public void paint(Graphics g, int startX, int startY) {
+ super.paint(g, startX, startY);
+ int x = point.x;
+ int y = point.y;
+ int column = grid_layout.getColumns();
+ int row = grid_layout.getRows();
+ if (column == 0) {
+ column = 1;
+ }
+ if (row == 0) {
+ row = 1;
+ }
+ double w = (double) hotspot.width / column;
+ double h = (double) hotspot.height / row;
+ int ix = (int) (x / w);
+ int iy = (int) (y / h);
+ x = (int) (ix * w + hotspot.x);
+ y = (int) (iy * h + hotspot.y);
+ drawHotspot(g, x, y, (int) w, (int) h, XCreatorConstants.SELECTION_COLOR);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRHorizontalLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRHorizontalLayoutPainter.java
new file mode 100644
index 000000000..7d08712d4
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRHorizontalLayoutPainter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.utils.ComponentUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FRHorizontalLayoutPainter extends FRBoxLayoutPainter {
+
+ public FRHorizontalLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public void paint(Graphics g, int startX, int startY) {
+ super.paint(g, startX, startY);
+ int x = hotspot.x;
+ Rectangle bounds = ComponentUtils.getRelativeBounds(container);
+ int my = bounds.y;
+ int mx = bounds.x;
+ int[] xy = calculateAddPosition(x - mx + startX, 0);
+ if (xy.length != 0) {
+ drawHotLine(g, startX, startY, xy[0] + mx, my, xy[0] + mx, my + container.getSize().height);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRParameterLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRParameterLayoutPainter.java
new file mode 100644
index 000000000..a598561c6
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRParameterLayoutPainter.java
@@ -0,0 +1,17 @@
+package com.fr.design.designer.beans.painters;
+
+import com.fr.design.designer.creator.XLayoutContainer;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: zx
+ * Date: 14-7-21
+ * Time: 下午7:57
+ */
+public class FRParameterLayoutPainter extends AbstractPainter{
+
+ public FRParameterLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/FRVerticalLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/FRVerticalLayoutPainter.java
new file mode 100644
index 000000000..cec14dd31
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/FRVerticalLayoutPainter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.utils.ComponentUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FRVerticalLayoutPainter extends FRBoxLayoutPainter {
+
+ public FRVerticalLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public void paint(Graphics g, int startX, int startY) {
+ super.paint(g, startX, startY);
+ int y = hotspot.y;
+ Rectangle bounds = ComponentUtils.getRelativeBounds(container);
+ int my = bounds.y;
+ int mx = bounds.x;
+ int[] xy = calculateAddPosition(0, y + startY - my);
+ if (xy.length != 0) {
+ drawHotLine(g, startX, startY, mx, xy[1] + my, mx + container.getSize().width, xy[1] + my);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/NullLayoutPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/NullLayoutPainter.java
new file mode 100644
index 000000000..36b0a2e54
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/NullLayoutPainter.java
@@ -0,0 +1,29 @@
+package com.fr.design.designer.beans.painters;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.creator.XLayoutContainer;
+
+public class NullLayoutPainter extends AbstractPainter {
+
+ public NullLayoutPainter(XLayoutContainer container) {
+ super(container);
+ }
+
+ @Override
+ public void paint(Graphics g,int startX,int startY) {
+
+ HoverPainter painter = container.getLayoutAdapter().getPainter();
+ if (painter != null) {
+ painter.setCreator(this.creator);
+ painter.setHotspot(this.hotspot);
+ painter.setRenderingBounds(this.hotspot_bounds);
+ painter.paint(g,startX,startY);
+ } else {
+ g.setColor(Color.lightGray);
+ g.drawRect(hotspot_bounds.x, hotspot_bounds.y, hotspot_bounds.width, hotspot_bounds.height);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/beans/painters/NullPainter.java b/designer_form/src/com/fr/design/designer/beans/painters/NullPainter.java
new file mode 100644
index 000000000..bf719f603
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/beans/painters/NullPainter.java
@@ -0,0 +1,10 @@
+package com.fr.design.designer.beans.painters;
+
+import com.fr.design.designer.creator.XLayoutContainer;
+
+public class NullPainter extends AbstractPainter {
+
+ public NullPainter( XLayoutContainer container) {
+ super(container);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/CRPropertyDescriptor.java b/designer_form/src/com/fr/design/designer/creator/CRPropertyDescriptor.java
new file mode 100644
index 000000000..c56e150c0
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/CRPropertyDescriptor.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import com.fr.design.gui.xtable.AbstractPropertyGroupModel;
+import com.fr.stable.StringUtils;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public final class CRPropertyDescriptor extends PropertyDescriptor {
+
+ private PropertyChangeAdapter l;
+
+ public CRPropertyDescriptor(String name, Class> beanClass) throws IntrospectionException {
+ super(name, beanClass);
+ }
+
+ public CRPropertyDescriptor(String name, Class> beanClass, String readMethod, String writeMethod) throws IntrospectionException{
+ super(name, beanClass, readMethod, writeMethod);
+ }
+
+
+ public CRPropertyDescriptor putKeyValue(String key, Object value) {
+ if (StringUtils.isNotEmpty(key)) {
+ this.setValue(key, value);
+ }
+ return this;
+ }
+
+ public CRPropertyDescriptor setPropertyChangeListener(PropertyChangeAdapter l) {
+ this.l = l;
+ return this;
+ }
+
+ public void firePropertyChanged() {
+ if (l != null) {
+ l.propertyChange();
+ }
+ }
+
+ public CRPropertyDescriptor setEditorClass(Class> clazz) {
+ this.setPropertyEditorClass(clazz);
+ return this;
+ }
+
+ public CRPropertyDescriptor setRendererClass(Class> clazz) {
+ this.putKeyValue(AbstractPropertyGroupModel.RENDERER, clazz);
+ return this;
+ }
+
+ public CRPropertyDescriptor setI18NName(String displayName) {
+ this.setDisplayName(displayName);
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java b/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java
new file mode 100644
index 000000000..5b2f35c05
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/DedicateLayoutContainer.java
@@ -0,0 +1,88 @@
+/**
+ *
+ */
+package com.fr.design.designer.creator;
+
+import com.fr.form.ui.container.WLayout;
+
+import java.awt.*;
+import java.beans.IntrospectionException;
+import java.util.ArrayList;
+
+/**
+ * 一些控件专属的容器,如标题容器,sclae容器
+ * @author jim
+ * @date 2014-11-7
+ */
+public abstract class DedicateLayoutContainer extends XLayoutContainer {
+
+ public DedicateLayoutContainer(WLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 得到属性名
+ * @return 属性名
+ * @throws IntrospectionException
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[0];
+ }
+
+ /**
+ * 返回容器图标
+ *
+ * @return
+ */
+ @Override
+ public String getIconPath() {
+ if(this.getXCreator(XWScaleLayout.INDEX) != null){
+ return this.getXCreator(XWScaleLayout.INDEX).getIconPath();
+ }
+ return "/com/fr/web/images/form/resources/text_field_16.png";
+ }
+
+
+ /**
+ * 控件树不显示此组件
+ * @param path 控件树list
+ */
+ public void notShowInComponentTree(ArrayList path) {
+ path.remove(path.size()-1);
+ }
+
+ /**
+ * 重置组件的名称
+ * @param name 名称
+ */
+ public void resetCreatorName(String name) {
+ super.resetCreatorName(name);
+ XCreator child = getXCreator(XWScaleLayout.INDEX);
+ child.toData().setWidgetName(name);
+ }
+
+ /**
+ * 返回对应属性表的组件,scale和title返回其子组件
+ * @return 组件
+ */
+ public XCreator getPropertyDescriptorCreator() {
+ return getXCreator(XWScaleLayout.INDEX);
+ }
+
+ /**
+ * 是否作为控件树的叶子节点
+ * @return 是则返回true
+ */
+ public boolean isComponentTreeLeaf() {
+ return true;
+ }
+
+ /**
+ * 是否为sclae和title专属容器
+ * @return 是则返回true
+ */
+ public boolean isDedicateContainer() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/FormCardPane.java b/designer_form/src/com/fr/design/designer/creator/FormCardPane.java
new file mode 100644
index 000000000..5bf160678
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/FormCardPane.java
@@ -0,0 +1,244 @@
+package com.fr.design.designer.creator;
+
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.event.ContainerListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.Icon;
+import javax.swing.JComponent;
+import com.fr.design.gui.ilable.UILabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+public class FormCardPane extends JComponent implements SwingConstants {
+
+ private boolean showTab;
+ private int tabPlace;
+ private JPanel tabPane;
+ private JPanel cardPane;
+ private CardLayout layout;
+ private java.util.List tabComponent = new java.util.ArrayList();
+ private int showIndex;
+
+ public FormCardPane(boolean showTab, int tabPlace) {
+ this.showTab = showTab;
+ this.tabPlace = tabPlace;
+ initTabComponent();
+ initCardComponent();
+ setLayout(new FormCardLayout());
+ this.add(tabPane);
+ this.add(cardPane);
+ }
+
+ public FormCardPane(ContainerListener containerListener) {
+ this(true, TOP);
+ cardPane.addContainerListener(containerListener);
+ }
+
+ private void initTabComponent() {
+ tabPane = new JPanel();
+ tabPane.setOpaque(true);
+ tabPane.setBorder(BorderFactory.createLineBorder(Color.pink));
+ tabPane.setBackground(Color.white);
+ }
+
+ private void initCardComponent() {
+ cardPane = new JPanel();
+ cardPane.setBorder(BorderFactory.createLineBorder(Color.orange));
+ layout = new CardLayout();
+ cardPane.setLayout(layout);
+ }
+
+ public void setSelectedIndex(int showIndex) {
+ this.setSelectedComponent(this.getComponentAt(showIndex));
+ }
+
+ public int getTabCount() {
+ return cardPane.getComponentCount();
+ }
+
+ @Override
+ public void add(Component comp, Object constraints) {
+ this.add(comp, constraints, -1);
+ }
+
+ @Override
+ public void removeAll() {
+ cardPane.removeAll();
+ tabComponent.clear();
+ }
+
+ private void reSetTabComponent() {
+ if (tabPlace == TOP || tabPlace == BOTTOM) {
+ int totalWidth = 0;
+ for (Component comp : tabComponent) {
+ totalWidth += comp.getWidth();
+ }
+ showTabComponent(totalWidth > tabPane.getWidth());
+
+ } else if (tabPlace == LEFT || tabPlace == RIGHT) {
+ int totalHeight = 0;
+ for (Component comp : tabComponent) {
+ totalHeight += comp.getHeight();
+ }
+ showTabComponent(totalHeight > tabPane.getHeight());
+ }
+ }
+
+ private void showTabComponent(boolean showButton) {
+ tabPane.removeAll();
+ if (this.showIndex < 0 || this.showIndex >= tabComponent.size()) {
+ this.showIndex = 0;
+ }
+ if (tabPlace == TOP || tabPlace == BOTTOM) {
+ tabPane.setLayout(new FlowLayout(FlowLayout.LEFT));
+
+ } else if (tabPlace == LEFT || tabPlace == RIGHT) {
+ tabPane.setLayout(new BoxLayout(tabPane, BoxLayout.Y_AXIS));
+ } else {
+ return;
+ }
+
+ for (Component comp : tabComponent) {
+ tabPane.add(comp);
+ }
+ tabPane.repaint();
+ }
+
+ @Override
+ public void add(Component comp, Object constraints, int index) {
+ if (!(comp instanceof XCreator)) {
+ return;
+ }
+ JComponent tabComp = new JPanel();
+ if (constraints instanceof String) {
+ tabComp = new UILabel((String) constraints);
+
+ } else if (constraints instanceof Icon) {
+ tabComp = new UILabel((Icon) constraints);
+ } else {
+ return;
+ }
+ tabComp.setOpaque(true);
+ tabComp.setBorder(BorderFactory.createLineBorder(Color.red));
+ cardPane.add(comp, ((((XCreator) comp).toData())).getWidgetName(), index);
+ if (index == -1) {
+ tabComponent.add(tabComp);
+ } else {
+ tabComponent.add(index, tabComp);
+ }
+
+ reSetTabComponent();
+ }
+
+ public void setTabPlacement(int tabPlace) {
+ this.tabPlace = tabPlace;
+ }
+
+ public Component getComponentAt(int i) {
+ return cardPane.getComponent(i);
+ }
+
+ public void setSelectedComponent(Component child) {
+ if (child instanceof XCreator) {
+ int order = cardPane.getComponentZOrder(child);
+ if (order == -1 || order == showIndex) {
+ return;
+ }
+ tabComponent.get(showIndex).setBackground(null);
+ this.showIndex = order;
+ tabComponent.get(showIndex).setBackground(Color.orange);
+ layout.show(cardPane, ((((XCreator) child).toData())).getWidgetName());
+ }
+ }
+
+ class FormCardLayout implements LayoutManager {
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void layoutContainer(Container parent) {
+ Insets inset = parent.getInsets();
+ int parentWidth = parent.getWidth() - inset.left - inset.right;
+ int parentHeight = parent.getHeight() - inset.top - inset.bottom;
+ if (showTab) {
+ if (tabPlace == TOP || tabPlace == BOTTOM) {
+ int height = getTabPaneHeight();
+ tabPane.setSize(parentWidth, height);
+ cardPane.setSize(parentWidth, parentHeight - height);
+ if (tabPlace == TOP) {
+ tabPane.setLocation(inset.left, inset.top);
+ cardPane.setLocation(inset.left, inset.top + height);
+ } else {
+ cardPane.setLocation(inset.left, inset.top);
+ tabPane.setLocation(inset.left, inset.top + parentHeight - height);
+ }
+ } else if (tabPlace == LEFT || tabPlace == RIGHT) {
+ int width = getTabPaneWidth();
+ tabPane.setSize(width, parentHeight);
+ cardPane.setSize(parentWidth - width, parentHeight);
+ if (tabPlace == LEFT) {
+ tabPane.setLocation(inset.left, inset.top);
+ cardPane.setLocation(inset.left + width, inset.top);
+ } else {
+ cardPane.setLocation(inset.left, inset.top);
+ tabPane.setLocation(inset.left + parentWidth - width, inset.top);
+ }
+ }
+
+ } else {
+ tabPane.setVisible(false);
+ cardPane.setSize(parent.getWidth(), parent.getHeight());
+ cardPane.setLocation(0, 0);
+ }
+ }
+
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ public int getTabPaneHeight() {
+ return 22;
+ }
+
+ public int getTabPaneWidth() {
+ return 40;
+ }
+
+ public void addCreatorListener(ContainerListener containerListener) {
+
+ }
+
+ public void setShowTab(boolean showTab) {
+ this.showTab = showTab;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/NullCreator.java b/designer_form/src/com/fr/design/designer/creator/NullCreator.java
new file mode 100644
index 000000000..642b74fd0
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/NullCreator.java
@@ -0,0 +1,33 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Color;
+import java.awt.Dimension;
+
+import javax.swing.JComponent;
+import com.fr.design.gui.ilable.UILabel;
+import javax.swing.SwingConstants;
+
+import com.fr.form.ui.Widget;
+
+//避免意外的发生导致整个模板打不开,尤其是不同版本之间
+public class NullCreator extends XWidgetCreator {
+
+ public NullCreator(Widget widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ protected String getIconName() {
+ return "none_widget.png";
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ UILabel l = new UILabel("UNEXPECTED WIDGET");
+ l.setForeground(Color.red);
+ l.setVerticalAlignment(SwingConstants.CENTER);
+ l.setHorizontalAlignment(SwingConstants.CENTER);
+ setBorder(DEFALUTBORDER);
+ return editor = l;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XAbstractSplitLayout.java b/designer_form/src/com/fr/design/designer/creator/XAbstractSplitLayout.java
new file mode 100644
index 000000000..1728ceff0
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XAbstractSplitLayout.java
@@ -0,0 +1,49 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.event.ContainerEvent;
+
+import com.fr.design.form.layout.FRSplitLayout;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WSplitLayout;
+
+public abstract class XAbstractSplitLayout extends XLayoutContainer {
+
+ public XAbstractSplitLayout(WSplitLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public WSplitLayout toData() {
+ return (WSplitLayout) data;
+ }
+
+ @Override
+ public void convert() {
+ isRefreshing = true;
+ WSplitLayout wb = this.toData();
+ this.removeAll();
+ String[] arrs = { WSplitLayout.CENTER, WSplitLayout.ASIDE };
+ for (int i = 0; i < arrs.length; i++) {
+ Widget wgt = wb.getLayoutWidget(arrs[i]);
+ if (wgt != null) {
+ XWidgetCreator comp = (XWidgetCreator) XCreatorUtils.createXCreator(wgt, calculatePreferredSize(wgt));
+ this.add(comp, arrs[i]);
+ }
+ }
+ isRefreshing = false;
+ }
+
+ @Override
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ FRSplitLayout b = (FRSplitLayout) getLayout();
+ Object constraints = b.getConstraints(creator);
+ WSplitLayout wb = this.toData();
+ Widget w = creator.toData();
+ wb.addWidget(w, constraints);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java b/designer_form/src/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java
new file mode 100644
index 000000000..a09b61424
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XBorderStyleWidgetCreator.java
@@ -0,0 +1,149 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Insets;
+
+import javax.swing.JComponent;
+
+import com.fr.base.Formula;
+import com.fr.design.border.UIRoundedBorder;
+import com.fr.form.ui.AbstractBorderStyleWidget;
+import com.fr.form.ui.Label;
+import com.fr.form.ui.LayoutBorderStyle;
+import com.fr.form.ui.PaddingMargin;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.WidgetTitle;
+import com.fr.form.ui.WidgetValue;
+import com.fr.form.ui.container.WTitleLayout;
+import com.fr.general.ComparatorUtils;
+import com.fr.stable.Constants;
+import com.fr.stable.StringUtils;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: zx
+ * Date: 14-9-22
+ * Time: 上午10:40
+ */
+
+public class XBorderStyleWidgetCreator extends XWidgetCreator{
+ private int cornerSize = 15;
+ private int noneSize = 0;
+
+ public XBorderStyleWidgetCreator(Widget widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 返回容器对应的widget
+ * @return 同上
+ */
+ @Override
+ public AbstractBorderStyleWidget toData() {
+ return (AbstractBorderStyleWidget) data;
+ }
+
+ protected void initStyle() {
+ LayoutBorderStyle style = toData().getBorderStyle();
+ initBorderStyle();
+ if (ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE)) {
+ initTitleStyle(style);
+ } else {
+ clearTitleWidget();
+ }
+ }
+
+ // 边框默认值设为NONE,不然像scalelayout这种只用默认边框的会不显示边框
+ protected void initBorderStyle() {
+ LayoutBorderStyle style = toData().getBorderStyle();
+ if (style != null && style.getBorder() != Constants.LINE_NONE) {
+ this.setBorder(new UIRoundedBorder(style.getBorder(), style.getColor(), style.isCorner() ? cornerSize : noneSize));
+ } else {
+ this.setBorder(DEFALUTBORDER);
+ }
+ }
+
+ private void clearTitleWidget() {
+ if (acceptType(XWFitLayout.class)) {
+ return;
+ }
+ XWTitleLayout parent = (XWTitleLayout) this.getParent();
+ if (parent.getComponentCount() > 1) {
+ parent.remove(parent.getTitleCreator());
+ }
+ }
+
+ /**
+ * 设置样式为标题样式时,对应组件加上标题
+ * @param style 样式
+ */
+ protected void initTitleStyle(LayoutBorderStyle style){
+ if (style.getTitle() == null) {
+ return;
+ }
+ XWTitleLayout parent = (XWTitleLayout) this.getParent();
+ if (parent.getComponentCount() > 1) {
+ XLabel title = (XLabel) parent.getTitleCreator();
+ Label widget = title.toData();
+ updateTitleWidgetStyle(widget, style);
+ title.initXCreatorProperties();
+ return;
+ }
+ // 初始化标题控件
+ XLabel title = new XLabel(new Label(), new Dimension());
+ Label label = title.toData();
+ updateTitleWidgetStyle(label, style);
+ parent.add(title, WTitleLayout.TITLE);
+ // 初始化标题边框
+ title.initXCreatorProperties();
+ WTitleLayout layout = parent.toData();
+ layout.updateChildBounds(layout.getBodyBoundsWidget().getBounds());
+ }
+
+ /**
+ * 更新标题控件所有的样式
+ */
+ private void updateTitleWidgetStyle(Label title, LayoutBorderStyle style) {
+ //标题的边框样式目前是取对应的控件的边框样式
+ title.setBorder(style.getBorder());
+ title.setColor(style.getColor());
+ title.setCorner(style.isCorner());
+
+ WidgetTitle wTitle = style.getTitle();
+ //设置成随机不重复的, 不然都用一个名字的话, 联动只能联动一个
+ title.setWidgetName(wTitle.TITLE_NAME_INDEX + this.toData().getWidgetName());
+ title.setWidgetValue(getTitleValue(wTitle));
+ title.setFont(wTitle.getFrFont());
+ title.setTextalign(wTitle.getPosition());
+ title.setBackground(wTitle.getBackground());
+ }
+
+ private WidgetValue getTitleValue(WidgetTitle wTitle){
+ String content = String.valueOf(wTitle.getTextObject());
+ Object vlaue = content.startsWith("=") ? new Formula(content) : content;
+ return new WidgetValue(vlaue);
+ }
+
+ @Override
+ protected String getIconName() {
+ return StringUtils.EMPTY;
+ }
+ @Override
+ protected JComponent initEditor() {
+ return this;
+ }
+
+ /**
+ * 内边距
+ * @return 同上
+ */
+ @Override
+ public Insets getInsets() {
+ PaddingMargin padding = toData().getMargin();
+ if (padding == null) {
+ return new Insets(0, 0, 0, 0);
+ }
+ return new Insets(padding.getTop(), padding.getLeft(), padding.getBottom(), padding.getRight());
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XButton.java b/designer_form/src/com/fr/design/designer/creator/XButton.java
new file mode 100644
index 000000000..4e0bd880a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XButton.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.AlphaComposite;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.SwingConstants;
+
+import com.fr.base.ScreenResolution;
+import com.fr.base.background.GradientBackground;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.mainframe.widget.editors.ButtonTypeEditor;
+import com.fr.design.mainframe.widget.editors.FontEditor;
+import com.fr.design.mainframe.widget.editors.IconEditor;
+import com.fr.design.mainframe.widget.editors.ImgBackgroundEditor;
+import com.fr.design.mainframe.widget.editors.ShortCutTextEditor;
+import com.fr.design.mainframe.widget.renderer.FontCellRenderer;
+import com.fr.design.mainframe.widget.renderer.IconCellRenderer;
+import com.fr.form.parameter.FormSubmitButton;
+import com.fr.form.ui.Button;
+import com.fr.form.ui.FreeButton;
+import com.fr.general.Background;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XButton extends XWidgetCreator {
+
+ public final static Background DEFAULTBG = new GradientBackground(new Color(247,247,247),new Color(210,210,210),GradientBackground.TOP2BOTTOM);
+ public final static Font DEFAULTFT = new Font("Song_TypeFace",0,12);
+ public final static Color DEFAULTFOREGROUNDCOLOR = Color.BLACK;
+ private Background bg;
+ private UILabel contentLabel;
+
+ public XButton(Button widget, Dimension initSize) {
+ this(new FreeButton(widget),initSize);
+ }
+
+ public XButton(FreeButton widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ public XButton(FormSubmitButton widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ public Background getContentBackground() {
+ return bg;
+ }
+
+ public void setContentBackground(Background bg) {
+ this.bg = bg;
+ }
+
+ public UILabel getContentLabel() {
+ return contentLabel;
+ }
+
+ public void setContentLabel(UILabel contentLabel) {
+ this.contentLabel = contentLabel;
+ }
+
+ /**
+ *根据下拉框选择返回按钮样式的默认设置或自定义设置列表
+ * @return 列表
+ * @throws IntrospectionException 抛错
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ CRPropertyDescriptor[] crp = ((FreeButton) data).isCustomStyle() ? getisCustomStyle() : getisnotCustomStyle();
+
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), crp);
+ }
+
+ protected CRPropertyDescriptor creatNonListenerStyle(int i) throws IntrospectionException{
+ CRPropertyDescriptor[] crPropertyDescriptors = {
+ new CRPropertyDescriptor("text", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[] {"Form-Button", "Name"})),
+ new CRPropertyDescriptor("customStyle", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Form-Button", "Style"})).setEditorClass(
+ ButtonTypeEditor.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("initialBackground", this.data.getClass()).setEditorClass(
+ ImgBackgroundEditor.class).setI18NName(Inter.getLocText("FR-Designer_Background-Initial")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("overBackground", this.data.getClass()).setEditorClass(
+ ImgBackgroundEditor.class).setI18NName(Inter.getLocText("FR-Designer_Background-Over")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("clickBackground", this.data.getClass()).setEditorClass(
+ ImgBackgroundEditor.class).setI18NName(Inter.getLocText("FR-Designer_Background-Click")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("font", this.data.getClass()).setI18NName(Inter.getLocText("FR-Designer_FRFont"))
+ .setEditorClass(FontEditor.class).setRendererClass(FontCellRenderer.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("iconName", this.data.getClass()).setI18NName(Inter.getLocText("FR-Designer_Icon"))
+ .setEditorClass(IconEditor.class).setRendererClass(IconCellRenderer.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("hotkeys", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_Button-Hotkeys"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setEditorClass(ShortCutTextEditor.class)
+
+ };
+ return crPropertyDescriptors[i];
+ }
+ protected CRPropertyDescriptor[] getisCustomStyle() throws IntrospectionException{
+ return new CRPropertyDescriptor[]{
+ creatNonListenerStyle(0) .setPropertyChangeListener(new PropertyChangeAdapter() {
+ @Override
+ public void propertyChange() {
+ setButtonText(((FreeButton) data).getText());
+ }
+ }),
+
+ creatNonListenerStyle(1) .setPropertyChangeListener(new PropertyChangeAdapter() {
+ @Override
+ public void propertyChange() {
+ checkButonType();
+ }
+ }),
+ creatNonListenerStyle(2).setPropertyChangeListener(
+ new PropertyChangeAdapter() {
+ @Override
+ public void propertyChange() {
+ bg = ((FreeButton) data).getInitialBackground();
+ }
+ }),
+ creatNonListenerStyle(3),
+ creatNonListenerStyle(4),
+ creatNonListenerStyle(5) .setPropertyChangeListener(
+ new PropertyChangeAdapter() {
+ @Override
+ public void propertyChange() {
+ FreeButton button = (FreeButton) data;
+ if (button.getFont() != null) {
+ contentLabel.setFont(button.getFont().applyResolutionNP(
+ ScreenResolution.getScreenResolution()));
+ contentLabel.setForeground(button.getFont().getForeground());
+ }
+ }
+ }),
+ creatNonListenerStyle(6),
+ creatNonListenerStyle(7)
+
+ };
+ }
+
+ protected CRPropertyDescriptor[] getisnotCustomStyle() throws IntrospectionException {
+ return new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("text", this.data.getClass())
+ .setI18NName(Inter.getLocText(new String[] {"Form-Button", "Name"}))
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ setButtonText(((FreeButton) data).getText());
+ }
+ }),
+ new CRPropertyDescriptor("customStyle", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Form-Button", "Style"})).setEditorClass(
+ ButtonTypeEditor.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ checkButonType();
+ }
+ }),
+ new CRPropertyDescriptor("iconName", this.data.getClass()).setI18NName(Inter.getLocText("FR-Designer_Icon"))
+ .setEditorClass(IconEditor.class).setRendererClass(IconCellRenderer.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("hotkeys", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Button-Hotkeys"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setEditorClass(ShortCutTextEditor.class)
+
+
+ };
+
+ }
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = new UILabel();
+ contentLabel = new UILabel();
+ }
+ return editor;
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ //不可见时,按钮.4f透明
+ AlphaComposite composite = this.data.isVisible() ? (AlphaComposite)((Graphics2D)g).getComposite() : AlphaComposite.getInstance(AlphaComposite.SRC_OVER,HALF_OPACITY);
+ ((Graphics2D)g).setComposite(composite);
+ Dimension panelSize = (contentLabel).getSize();
+ if(bg != null) {
+ bg.paint(g, new Rectangle2D.Double(0, 0, panelSize.getWidth(), panelSize.getHeight()));
+ }
+ }
+
+ public void setButtonText(String text) {
+ contentLabel.setText(text);
+ }
+
+ private void checkButonType() {
+ UILabel l = contentLabel;
+ FreeButton button = (FreeButton) data;
+
+ if (!button.isCustomStyle()) {
+ l.setBorder(BorderFactory.createLineBorder(new Color(148, 148, 148)));
+ bg = DEFAULTBG;
+ contentLabel.setFont(DEFAULTFT);
+ contentLabel.setForeground(DEFAULTFOREGROUNDCOLOR);
+ editor.setLayout(new BorderLayout());
+ editor.add(l, BorderLayout.CENTER);
+ } else {
+ l.setBorder(null);
+ editor.setLayout(new BorderLayout());
+ editor.add(l,BorderLayout.CENTER);
+ if (button.getFont() != null) {
+ contentLabel.setFont(button.getFont().applyResolutionNP(
+ ScreenResolution.getScreenResolution()));
+ contentLabel.setForeground(button.getFont().getForeground());
+ }
+ l.setBounds(0, 0, button.getButtonWidth() == 0 ? this.getWidth() : button.getButtonWidth(), button
+ .getButtonHeight() == 0 ? this.getHeight() : button.getButtonHeight());
+ bg = button.getInitialBackground();
+ }
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ checkButonType();
+ UILabel l = contentLabel;
+ FreeButton button = (FreeButton) data;
+ l.setText(button.getText());
+ if (button.isCustomStyle() && button.getFont() != null) {
+ l.setFont(button.getFont().applyResolutionNP(ScreenResolution.getScreenResolution()));
+ l.setForeground(button.getFont().getForeground());
+ }
+
+ l.setVerticalAlignment(SwingConstants.CENTER);
+ l.setHorizontalAlignment(SwingConstants.CENTER);
+ if (button.getButtonHeight() > 0 && button.getButtonWidth() > 0) {
+ this.setSize(button.getButtonWidth(), button.getButtonHeight());
+ l.setSize(button.getButtonWidth(), button.getButtonHeight());
+ XLayoutContainer parent;
+ if ((parent = XCreatorUtils.getParentXLayoutContainer(this)) instanceof XWAbsoluteLayout) {
+ ((XWAbsoluteLayout) parent).toData().setBounds(toData(), getBounds());
+ }
+ }
+ l.setEnabled(button.isEnabled());
+ }
+
+ /**
+ * 初始化按钮的Size
+ * @return 尺寸
+ */
+ public Dimension initEditorSize() {
+ FreeButton button = (FreeButton) data;
+ if (checkbutton(button)) {
+ return new Dimension(button.getButtonWidth(), button.getButtonHeight());
+ }
+ return super.initEditorSize();
+ }
+ private boolean checkbutton(FreeButton button){
+ return (button.isCustomStyle() && button.getButtonHeight() > 0 && button.getButtonWidth() > 0) ;
+ }
+ @Override
+ protected String getIconName() {
+ return "button_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XChartEditor.java b/designer_form/src/com/fr/design/designer/creator/XChartEditor.java
new file mode 100644
index 000000000..2087dda10
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XChartEditor.java
@@ -0,0 +1,203 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+
+import com.fr.base.chart.BaseChart;
+import com.fr.base.chart.BaseChartCollection;
+import com.fr.design.gui.chart.BaseChartPropertyPane;
+import com.fr.design.gui.chart.MiddleChartComponent;
+import com.fr.design.mainframe.BaseJForm;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
+import com.fr.design.mainframe.widget.renderer.LayoutBorderStyleRenderer;
+import com.fr.design.module.DesignModuleFactory;
+import com.fr.design.designer.beans.events.DesignerEditor;
+import com.fr.form.ui.AbstractBorderStyleWidget;
+import com.fr.form.ui.BaseChartEditor;
+import com.fr.form.ui.Widget;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+/**
+ * form中的图表按钮弹出的控件, 创建初始化图表内容.
+ *
+ * @author kunsnat E-mail:kunsnat@gmail.com
+ * @version 创建时间:2013-7-5 上午10:28:30
+ * 类说明
+ */
+public class XChartEditor extends XBorderStyleWidgetCreator {
+ private static final long serialVersionUID = -7009439442104836657L;
+ //具体来说是DesignerEditor
+ private DesignerEditor designerEditor;
+ // private DesignerEditor designerEditor;
+ //marro:无奈的属性,暂时想不出好办法
+ private boolean isRefreshing = false;
+
+ public XChartEditor(BaseChartEditor editor) {
+ this(editor, new Dimension(250, 150));
+ }
+
+ public XChartEditor(BaseChartEditor editor, Dimension size) {
+ super((Widget)editor, size);
+ }
+
+ @Override
+ public String getIconPath() {
+ return super.getIconPath();
+ }
+
+
+ @Override
+ protected String getIconName() {
+ return "Chart.png";
+ }
+
+ /**
+ * 返回组件默认名
+ * @return 组件类名(小写)
+ */
+ public String createDefaultName() {
+ return "chart";
+ }
+
+ /**
+ * 是否支持设置标题
+ * @return 是返回true
+ */
+ public boolean hasTitleStyle() {
+ return true;
+ }
+
+ /**
+ * 得到属性名
+ * @return 属性名
+ * @throws java.beans.IntrospectionException
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetName", this.data.getClass()).setI18NName(Inter
+ .getLocText("Form-Widget_Name")),
+ new CRPropertyDescriptor("borderStyle", this.data.getClass()).setEditorClass(
+ WLayoutBorderStyleEditor.class).setRendererClass(LayoutBorderStyleRenderer.class).setI18NName(
+ Inter.getLocText("Chart-Style_Name")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ initStyle();
+ }
+ }),
+ };
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return false;
+ }
+
+ /**
+ * 返回设计器的Editor
+ */
+ public DesignerEditor getDesignerEditor() {
+ return designerEditor;
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ initBorderStyle();
+ BaseChartCollection collection = ((BaseChartEditor) data).getChartCollection();
+ isRefreshing = true;
+ ((MiddleChartComponent) designerEditor.getEditorTarget()).populate(collection);
+ isRefreshing = false;
+ }
+
+ /**
+ * 点击选中的时候, 刷新界面
+ * 右键 reset之后, 触发事件 populate此方法
+ *
+ * @param jform 表单
+ * @param formDesigner 表单设计器
+ * @return 控件.
+ */
+ public JComponent createToolPane(final BaseJForm jform, final FormDesigner formDesigner) {
+ getDesignerEditorTarget().addStopEditingListener(new PropertyChangeAdapter() {
+ public void propertyChange() {
+ JComponent pane = jform.getEditingPane();
+ if (pane instanceof BaseChartPropertyPane) {
+ ((BaseChartPropertyPane) pane).setSupportCellData(true);
+ ((BaseChartPropertyPane) pane).populateChartPropertyPane(getDesignerEditorTarget().update(), formDesigner);
+ }
+ }
+ });
+
+ final BaseChartPropertyPane propertyPane = DesignModuleFactory.getChartWidgetPropertyPane(formDesigner);
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (getDesignerEditor().getEditorTarget() != null) {
+ propertyPane.setSupportCellData(true);
+ propertyPane.populateChartPropertyPane(getDesignerEditorTarget().update(), formDesigner);
+ }
+ }
+ });
+ return (JComponent)propertyPane;
+ }
+
+ private MiddleChartComponent getDesignerEditorTarget() {
+ MiddleChartComponent bcc = null;
+ if (getDesignerEditor().getEditorTarget() instanceof MiddleChartComponent) {
+ bcc = (MiddleChartComponent) getDesignerEditor().getEditorTarget();
+ }
+ return bcc;
+ }
+
+ /**
+ * 渲染Painter
+ */
+ public void paint(Graphics g) {
+ super.paint(g);
+ designerEditor.paintEditor(g, this.getSize());
+ }
+
+ /**
+ * 初始化Editor大小.
+ *
+ * @return 返回大小.
+ */
+ public Dimension initEditorSize() {
+ return new Dimension(250, 100);
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (designerEditor == null) {
+ final MiddleChartComponent chartComponent = DesignModuleFactory.getChartComponent(((BaseChartEditor) data).getChartCollection());
+ if (chartComponent != null) {
+ JComponent jChart = chartComponent;
+ jChart.setBorder(BorderFactory.createLineBorder(Color.lightGray));
+ designerEditor = new DesignerEditor(jChart);
+ chartComponent.addStopEditingListener(designerEditor);
+ designerEditor.addPropertyChangeListener(new PropertyChangeAdapter() {
+ public void propertyChange() {
+ if (!isRefreshing) {
+ ((BaseChartEditor) data).resetChangeChartCollection(chartComponent.update());
+ }
+ }
+ });
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XCheckBox.java b/designer_form/src/com/fr/design/designer/creator/XCheckBox.java
new file mode 100644
index 000000000..39d41407e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XCheckBox.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.stable.core.PropertyChangeAdapter;
+import com.fr.design.gui.icheckbox.UICheckBox;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.form.ui.CheckBox;
+import com.fr.form.ui.WidgetValue;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XCheckBox extends XWidgetCreator {
+
+ public XCheckBox(CheckBox widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("text", this.data.getClass()).setI18NName(Inter.getLocText("Text"))
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ ((UICheckBox) editor).setText(((CheckBox) data).getText());
+ }
+ }),
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(WidgetValueEditor.class)
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ WidgetValue value = ((CheckBox) data).getWidgetValue();
+ if (value != null && value.getValue() instanceof Boolean) {
+ ((UICheckBox) editor).setSelected((Boolean) value.getValue());
+ }
+ }
+ }),
+ new CRPropertyDescriptor("fontSize", this.data.getClass(), "getFontSize", "setFontSize")
+ .setI18NName(Inter.getLocText(new String[]{"FRFont", "FRFont-Size"}))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ });
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = new UICheckBox();
+ editor.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
+ }
+ return editor;
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ UICheckBox jCheckBox = (UICheckBox) editor;
+ CheckBox check = (CheckBox) data;
+ jCheckBox.setText(check.getText());
+ if (check.getWidgetValue() != null && check.getWidgetValue().getValue() instanceof Boolean) {
+ jCheckBox.setSelected((Boolean) check.getWidgetValue().getValue());
+ }
+ }
+
+ @Override
+ protected String getIconName() {
+ return "check_box_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XCheckBoxGroup.java b/designer_form/src/com/fr/design/designer/creator/XCheckBoxGroup.java
new file mode 100644
index 000000000..0aba61dad
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XCheckBoxGroup.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+
+import com.fr.design.gui.icheckbox.UICheckBox;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.widget.editors.DictionaryEditor;
+import com.fr.design.mainframe.widget.editors.InChangeBooleanEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.DictionaryRenderer;
+import com.fr.form.ui.CheckBoxGroup;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XCheckBoxGroup extends XFieldEditor {
+
+ public XCheckBoxGroup(CheckBoxGroup widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), getCRPropertyDescriptor());
+ }
+
+ private CRPropertyDescriptor[] getCRPropertyDescriptor() throws IntrospectionException {
+ CRPropertyDescriptor[] crp = new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(WidgetValueEditor.class),
+ new CRPropertyDescriptor("dictionary", this.data.getClass()).setI18NName(
+ Inter.getLocText("DS-Dictionary")).setEditorClass(DictionaryEditor.class).setRendererClass(
+ DictionaryRenderer.class),
+ new CRPropertyDescriptor("adaptive", this.data.getClass()).setI18NName(Inter.getLocText("Adaptive"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced").setEditorClass(InChangeBooleanEditor.class),
+ new CRPropertyDescriptor("chooseAll", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Provide", "Choose_All"})).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("returnString", this.data.getClass()).setI18NName(
+ Inter.getLocText("Return-String")).setEditorClass(InChangeBooleanEditor.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Return-Value") };
+ if (((CheckBoxGroup) this.toData()).isReturnString()) {
+ crp = (CRPropertyDescriptor[]) ArrayUtils.addAll(crp, new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("delimiter", this.data.getClass()).setI18NName(
+ Inter.getLocText("Form-Delimiter")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Return-Value"),
+ new CRPropertyDescriptor("startSymbol", this.data.getClass()).setI18NName(
+ Inter.getLocText("ComboCheckBox-Start_Symbol")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Return-Value"),
+ new CRPropertyDescriptor("endSymbol", this.data.getClass()).setI18NName(
+ Inter.getLocText("ComboCheckBox-End_Symbol")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Return-Value") });
+ }
+ if (!((CheckBoxGroup) this.toData()).isAdaptive()) {
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("columnsInRow", this.data
+ .getClass()).setI18NName(Inter.getLocText("Button-Group-Display-Columns")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ }
+ return crp;
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ editor.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
+ UICheckBox cb1 = new UICheckBox();
+ editor.add(cb1, BorderLayout.WEST);
+ UICheckBox cb2 = new UICheckBox();
+ editor.add(cb2, BorderLayout.EAST);
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "checkbox_group_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XComboBox.java b/designer_form/src/com/fr/design/designer/creator/XComboBox.java
new file mode 100644
index 000000000..b08b6369c
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XComboBox.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.widget.editors.DictionaryEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.DictionaryRenderer;
+import com.fr.form.ui.ComboBox;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XComboBox extends XCustomWriteAbleRepeatEditor {
+ LimpidButton btn;
+
+ public XComboBox(ComboBox widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 控件的属性列表
+ * @return 此控件所用的属性列表
+ * @throws IntrospectionException 异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+ super.supportedDescriptor(),
+ new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(WidgetValueEditor.class),
+ new CRPropertyDescriptor("dictionary", this.data.getClass()).setI18NName(Inter.getLocText("FR-Designer_DS-Dictionary")).setEditorClass(DictionaryEditor.class).setRendererClass(DictionaryRenderer.class)
+ });
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ UITextField textField = new UITextField(5);
+ textField.setOpaque(false);
+ editor.add(textField, BorderLayout.CENTER);
+ btn = new LimpidButton("", this.getIconPath(), toData().isVisible() ? FULL_OPACITY : HALF_OPACITY);
+ btn.setPreferredSize(new Dimension(21, 21));
+ btn.setOpaque(true);
+ editor.add(btn, BorderLayout.EAST);
+ editor.setBackground(Color.WHITE);
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "combo_box_16.png";
+ }
+
+ protected void makeVisible(boolean visible) {
+ btn.makeVisible(visible);
+ }
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName){
+ return new XWScaleLayout();
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ this.setSize(width, minHeight);
+ parentPanel.add(this);
+ }
+
+ /**
+ * 此控件在自适应布局要保持原样高度
+ *
+ * @return 是则返回true
+ */
+ @Override
+ public boolean shouldScaleCreator() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XComboCheckBox.java b/designer_form/src/com/fr/design/designer/creator/XComboCheckBox.java
new file mode 100644
index 000000000..482af817b
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XComboCheckBox.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import com.fr.design.mainframe.widget.editors.InChangeBooleanEditor;
+import com.fr.form.ui.ComboCheckBox;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+import java.awt.*;
+import java.beans.IntrospectionException;
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XComboCheckBox extends XComboBox {
+
+ public XComboCheckBox(ComboCheckBox widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), !((ComboCheckBox) this.toData())
+ .isReturnString() ? new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("supportTag", this.data.getClass()).setI18NName(
+ Inter.getLocText("Form-SupportTag")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"),
+ new CRPropertyDescriptor("delimiter", this.data.getClass()).setI18NName(
+ Inter.getLocText("Form-Delimiter")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"),
+ new CRPropertyDescriptor("returnString", this.data.getClass()).setEditorClass(
+ InChangeBooleanEditor.class).setI18NName(Inter.getLocText("Return-String")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Return-Value") } : new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("delimiter", this.data.getClass()).setI18NName(
+ Inter.getLocText("Form-Delimiter")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"),
+ new CRPropertyDescriptor("returnString", this.data.getClass()).setI18NName(
+ Inter.getLocText("Return-String")).setEditorClass(InChangeBooleanEditor.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Return-Value"),
+ new CRPropertyDescriptor("startSymbol", this.data.getClass()).setI18NName(
+ Inter.getLocText("ComboCheckBox-Start_Symbol")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Return-Value"),
+ new CRPropertyDescriptor("endSymbol", this.data.getClass()).setI18NName(
+ Inter.getLocText("ComboCheckBox-End_Symbol")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Return-Value") });
+ }
+
+ @Override
+ protected String getIconName() {
+ return "combo_check_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XComponent.java b/designer_form/src/com/fr/design/designer/creator/XComponent.java
new file mode 100644
index 000000000..b6af33983
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XComponent.java
@@ -0,0 +1,32 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Rectangle;
+
+import javax.swing.JComponent;
+
+import com.fr.design.mainframe.BaseJForm;
+import com.fr.design.mainframe.FormDesigner;
+
+public interface XComponent {
+
+ /**
+ * 返回组件的位置大小
+ * @return 返回bound
+ */
+ Rectangle getBounds();
+
+ /**
+ * 设置组件的位置大小
+ * @param oldbounds bound大小
+ */
+ void setBounds(Rectangle oldbounds);
+
+ /**
+ * 生成工具菜单界面
+ * @param jform BaseJForm类
+ * @param formeditor 设计界面组件
+ * @return 返回工具界面
+ */
+ JComponent createToolPane(BaseJForm jform, FormDesigner formeditor);
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XConnector.java b/designer_form/src/com/fr/design/designer/creator/XConnector.java
new file mode 100644
index 000000000..f157abccc
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XConnector.java
@@ -0,0 +1,186 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+
+import javax.swing.JComponent;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.mainframe.BaseJForm;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.form.ui.Connector;
+import com.fr.design.form.util.XCreatorConstants;
+
+//这个类仅仅是对Connector包装下,使得表单设计页面逻辑更清晰
+public class XConnector implements XComponent {
+
+ private XWAbsoluteLayout parent;
+ private Connector connector;
+ public static Cursor connectorCursor;
+ public static Cursor moveCursor;
+
+ static {
+ connectorCursor = Toolkit.getDefaultToolkit().createCustomCursor(
+ BaseUtils.readImage("/com/fr/design/images/form/designer/cursor/connectorcursor.png"), new Point(0, 0),
+ "connector");
+ moveCursor = Toolkit.getDefaultToolkit().createCustomCursor(
+ BaseUtils.readImage("/com/fr/design/images/form/designer/cursor/move.png"), new Point(16, 16),
+ "move");
+ }
+
+ public XConnector(Connector connector, XWAbsoluteLayout xWAbsoluteLayout) {
+ this.connector = connector;
+ this.parent = xWAbsoluteLayout;
+ }
+
+ private boolean near(int x1, int x2) {
+ return x1 - x2 >= -XCreatorConstants.RESIZE_BOX_SIZ && x1 - x2 <= XCreatorConstants.RESIZE_BOX_SIZ;
+ }
+
+ private Rectangle createRectangle(Point A, Point B) {
+ return new Rectangle(Math.min(A.x, B.x), Math.min(A.y, B.y), Math.abs(A.x - B.x), Math.abs(A.y - B.y));
+ }
+
+ public XLayoutContainer getParentXLayoutContainer() {
+ return parent;
+ }
+
+ public Connector getConnector() {
+ return connector;
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return createRectangle(connector.getStartPoint(), connector.getEndPoint());
+ }
+
+ @Override
+ public void setBounds(Rectangle oldbounds) {
+
+ }
+
+ public JComponent createToolPane(BaseJForm jform, FormDesigner formEditor) {
+ return jform.getEditingPane();
+ }
+
+ public ConnectorDirection getDirection(int x, int y) {
+
+ Point pS = connector.getStartPoint();
+ if (near(x, pS.x) && near(y, pS.y)) {
+ return new ConnectorDirection(pS, null);
+ }
+ Point pE = connector.getEndPoint();
+ if (near(x, pE.x) && near(y, pE.y)) {
+ return new ConnectorDirection(null, pE);
+ }
+
+ Point p1 = pS;
+ Point p2;
+ Point p;
+ int size = connector.getPointCount();
+ for (int i = 0; i < size - 1; i++) {
+ p2 = connector.getPointIndex(i + 1);
+ p = connector.getMidPoint(p1, p2);
+ if (near(p.x, x) && near(p.y, y)) {
+ return new ConnectorDirection(p1, p2);
+ }
+ p1 = p2;
+ }
+ return new ConnectorDirection();
+ }
+
+ public class ConnectorDirection implements Direction {
+
+ private Point A;
+ private Point B;
+ private Rectangle oldbounds;
+
+ private ConnectorDirection() {
+
+ }
+
+ private ConnectorDirection(Point A, Point B) {
+ this.A = A;
+ this.B = B;
+ }
+
+ private Cursor getCursor() {
+ if (A == null || B == null) {
+ return A == B ? Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR) : moveCursor;
+ }
+ if (A.x == B.x) {
+ return Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
+ } else if (A.y == B.y) {
+ return Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
+ } else {
+ return Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
+ }
+ }
+
+ private void setXY(Point p1, Point p2, int dx, int dy, Rectangle oldbounds) {
+ if (p1.x == p2.x) {
+ p1.x = p2.x = oldbounds.x + dx;
+ } else {
+ p1.y = p2.y = oldbounds.y + dy;
+ }
+ }
+
+ @Override
+ public void drag(int dx, int dy, FormDesigner designer) {
+ if (A == null || B == null) {
+ if (A != null) {
+ A.x = oldbounds.x + dx;
+ A.y = oldbounds.y + dy;
+ } else if (B != null) {
+ B.x = oldbounds.x + dx;
+ B.y = oldbounds.y + dy;
+ } else {
+ setBounds(new Rectangle(oldbounds.x + dx, oldbounds.y + dy, oldbounds.width, oldbounds.height));
+ }
+ designer.getDrawLineHelper().resetConnector(connector);
+ return;
+ }
+ if (A == connector.getStartPoint()) {
+ this.A = new Point(A.x, A.y);
+ connector.addPoint(1, A);
+ }
+ if (connector.getEndPoint() == B) {
+ this.B = new Point(B.x, B.y);
+ connector.addPoint(connector.getPointCount() - 1, B);
+ }
+ setXY(A, B, dx, dy, oldbounds);
+
+ }
+
+ public Rectangle getBounds() {
+ if (A == null || B == null) {
+ if (A != null) {
+ return new Rectangle(A.x, A.y, 0, 0);
+ } else if (B != null) {
+ return new Rectangle(B.x, B.y, 0, 0);
+ } else {
+ return XConnector.this.getBounds();
+ }
+ }
+ return createRectangle(A, B);
+ }
+
+ @Override
+ public int getActual() {
+ return 0;
+ }
+
+ @Override
+ public void updateCursor(FormDesigner formEditor) {
+ formEditor.setCursor(getCursor());
+ }
+
+ @Override
+ public void backupBounds(FormDesigner formEditor) {
+ oldbounds = getBounds();
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XCreator.java b/designer_form/src/com/fr/design/designer/creator/XCreator.java
new file mode 100644
index 000000000..02c573266
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XCreator.java
@@ -0,0 +1,521 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.events.DesignerEditor;
+import com.fr.design.designer.beans.models.SelectionModel;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.*;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WTitleLayout;
+import com.fr.stable.StableUtils;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.beans.IntrospectionException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author richer
+ * @since 6.5.3 com.fr.base.listener.OB的设计组件
+ *
+ */
+public abstract class XCreator extends JPanel implements XComponent, XCreatorTools {
+
+ protected static final Border DEFALUTBORDER = BorderFactory.createLineBorder(new Color(210, 210, 210), 1);
+ public static final Dimension SMALL_PREFERRED_SIZE = new Dimension(80, 21);
+ protected static final Dimension MIDDLE_PREFERRED_SIZE = new Dimension(80, 50);
+ protected static final Dimension BIG_PREFERRED_SIZE = new Dimension(80, 80);
+ // barry: 拖拽控件时,控件要恢复原始大小,就先把控件当前大小备份到这里。
+ protected Dimension backupSize;
+ protected XLayoutContainer backupParent;
+
+ protected Widget data;
+ protected JComponent editor;
+ // XCreator加入到某些XLayoutContainer中时,能调整宽度或者高度
+ private int[] directions;
+ private Rectangle backupBound;
+
+ public XCreator(Widget ob, Dimension initSize) {
+ this.data = ob;
+
+ this.initEditor();
+
+ if (editor != null && editor != this) {
+ this.setLayout(FRGUIPaneFactory.createBorderLayout());
+ add(editor, BorderLayout.CENTER);
+ }
+
+ if (initSize.width == 0) {
+ initSize.width = this.initEditorSize().width;
+ }
+ if (initSize.height == 0) {
+ initSize.height = this.initEditorSize().height;
+ }
+ this.setPreferredSize(initSize);
+ this.setSize(initSize);
+ this.setMaximumSize(initSize);
+ this.initXCreatorProperties();
+ }
+
+ public int[] getDirections() {
+ return directions;
+ }
+
+ public void setDirections(int[] directions) {
+ this.directions = directions;
+ }
+
+ /**
+ * 应用备份的大小
+ */
+ public void useBackupSize() {
+ if (this.backupSize != null) {
+ setSize(this.backupSize);
+ }
+ }
+
+ /**
+ * 备份当前大小
+ */
+ public void backupCurrentSize() {
+ this.backupSize = getSize();
+ }
+
+ public XLayoutContainer getBackupParent() {
+ return backupParent;
+ }
+
+ public void setBackupParent(XLayoutContainer backupContainer) {
+ this.backupParent = backupContainer;
+ }
+
+ /**
+ * 备份当前parent容器
+ */
+ public void backupParent() {
+ setBackupParent(XCreatorUtils.getParentXLayoutContainer(this));
+ }
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName){
+ return new XWTitleLayout();
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ parentPanel.add(this, WTitleLayout.BODY);
+ }
+
+ /**
+ * 设置父容器的名字
+ *
+ * @param parentPanel 当前父容器
+ * @param widgetName 当前控件名
+ *
+ *
+ * @date 2014-11-27-上午9:47:00
+ *
+ */
+ protected void setWrapperName(XLayoutContainer parentPanel, String widgetName){
+ parentPanel.toData().setWidgetName(widgetName);
+ }
+
+ /**
+ * 初始化当前组件的父容器
+ * 大体分为三种: Scale缩放型, Title标题型, Border自定义标题栏
+ *
+ * @param minHeight 最小高度
+ *
+ * @return 父容器
+ *
+ *
+ * @date 2014-11-25-下午5:15:23
+ *
+ */
+ public XLayoutContainer initCreatorWrapper(int minHeight){
+ XLayoutContainer parentPanel;
+ String widgetName = this.toData().getWidgetName();
+ parentPanel = this.getCreatorWrapper(widgetName);
+
+ int width = this.getWidth();
+ int height = this.getHeight();
+
+ parentPanel.setLocation(this.getX(), this.getY());
+ parentPanel.setSize(width, height);
+ setWrapperName(parentPanel, widgetName);
+ this.setLocation(0, 0);
+ this.addToWrapper(parentPanel, width, minHeight);
+ LayoutUtils.layoutRootContainer(parentPanel);
+
+ return parentPanel;
+ }
+
+ /**
+ * 初始化creator的属性值
+ */
+ public void rebuid() {
+ initXCreatorProperties();
+ }
+
+ /**
+ * 返回组件属性值
+ * @return 返回组件属性值
+ * @throws IntrospectionException 异常
+ */
+ public abstract CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException;
+
+ /**
+ * 生成creator对应的控件widget
+ * @return 控件widget
+ */
+ public Widget toData() {
+ return this.data;
+ }
+
+ protected abstract JComponent initEditor();
+
+ /**
+ * 根据Widget的属性值初始化XCreator的属性值
+ */
+ protected abstract void initXCreatorProperties();
+
+ /**
+ * 返回XCreator的默认大小80x21
+ * @return 默认的最小大小
+ */
+ public Dimension initEditorSize() {
+ return SMALL_PREFERRED_SIZE;
+ }
+
+ protected String getIconName() {
+ return "";
+ }
+
+ public String getIconPath() {
+ return "/com/fr/web/images/form/resources/" + getIconName();
+ }
+
+ /**
+ * 返回组件默认名
+ * @return 组件类名(小写)
+ */
+ public String createDefaultName() {
+ String name = this.getClass().getSimpleName();
+ return Character.toLowerCase(name.charAt(1)) + name.substring(2);
+ }
+
+ @Override
+ public void setBounds(Rectangle bounds) {
+ Dimension size = this.getMinimumSize();
+ if (bounds.getWidth() < size.width) {
+ bounds.width = size.width;
+ //针对拖动,不大好。
+ bounds.x = this.getX();
+ }
+ if (bounds.getHeight() < size.height) {
+ bounds.height = size.height;
+ bounds.y = this.getY();
+ }
+ super.setBounds(bounds);
+ }
+
+ public DesignerEditor extends JComponent> getDesignerEditor() {
+ return null;
+ }
+
+ /**
+ * 根据权限编辑工具界面
+ * @param jform 表单容器
+ *@param formEditor 设计界面组件
+ *@return 工具界面
+ */
+ public JComponent createToolPane(BaseJForm jform, FormDesigner formEditor) {
+ if (!BaseUtils.isAuthorityEditing()) {
+ if (isDedicateContainer()) {
+ // 图表块和报表块由于控件树处不显示,但对应的属性表要显示,此处处理下
+ XCreator child = ((XLayoutContainer) this).getXCreator(0);
+ return child.createToolPane(jform, formEditor);
+ }
+ return WidgetPropertyPane.getInstance(formEditor);
+ } else {
+ //判断是不是布局,布局不支持权限编辑
+ if (formEditor.isSupportAuthority()) {
+ AuthorityPropertyPane authorityPropertyPane = new AuthorityPropertyPane(formEditor);
+ authorityPropertyPane.populate();
+ return authorityPropertyPane;
+ }
+
+ return new NoSupportAuthorityEdit();
+
+ }
+
+ }
+
+ @Override
+ public Dimension getMinimumSize() {
+ return new Dimension(0, 0);
+ }
+
+ /**
+ * 是否支持切换到报表界面编辑
+ * @return 是则返回true
+ */
+ public boolean isReport(){
+ return false;
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return true;
+ }
+
+ /**
+ * 该组件是否可以拖入表单主体
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoAdaptPane(){
+ return true;
+ }
+
+ /**
+ * 该组件是否可以拖拽(表单中参数面板和自适应布局不可以拖拽)
+ * @return 是则返回true
+ */
+ public boolean isSupportDrag(){
+ return true;
+ }
+
+ public List getAllXCreatorNameList(XCreator xCreator, List namelist){
+ namelist.add(xCreator.toData().getWidgetName());
+ return namelist;
+ }
+
+ /**
+ * 是否有查询按钮
+ * @param xCreator 控件或容器
+ * @return 有无查询按钮
+ */
+ public boolean SearchQueryCreators(XCreator xCreator) {
+ return false;
+ }
+
+ /**
+ * @return the backupBound
+ */
+ public Rectangle getBackupBound() {
+ return backupBound;
+ }
+
+ /**
+ * @param rec the backupBound to set
+ */
+ public void setBackupBound(Rectangle rec) {
+ this.backupBound = rec;
+ }
+
+ /**
+ * 控件树不显示此组件
+ * @param path 控件树list
+ */
+ public void notShowInComponentTree(ArrayList path) {
+ return;
+ }
+
+ /**
+ * 重置组件的名称
+ * @param name 名称
+ */
+ public void resetCreatorName(String name) {
+ toData().setWidgetName(name);
+ }
+
+ /**
+ * 返回编辑的子组件,scale为其内部组件
+ * @return 组件
+ */
+ public XCreator getEditingChildCreator() {
+ return this;
+ }
+
+ /**
+ * 返回对应属性表的组件,scale和title返回其子组件
+ * @return 组件
+ */
+ public XCreator getPropertyDescriptorCreator() {
+ return this;
+ }
+
+ /**
+ * 更新子组件的Bound; 没有不处理
+ * @param minHeight 最小高度
+ */
+ public void updateChildBound(int minHeight) {
+ return;
+ }
+
+ /**
+ * 是否作为控件树的叶子节点
+ * @return 是则返回true
+ */
+ public boolean isComponentTreeLeaf() {
+ return true;
+ }
+
+ /**
+ * 是否为sclae和title专属容器
+ * @return 是则返回true
+ */
+ public boolean isDedicateContainer() {
+ return false;
+ }
+
+ /**
+ * 是否接收这种类型
+ * @param acceptTypes 接收的类型
+ * @return 接收指定的类型则返回true,否则返回false
+ */
+ public boolean acceptType(Class>... acceptTypes) {
+ for (Class> type : acceptTypes) {
+ if (StableUtils.classInstanceOf(this.getClass(), type)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 是否组件要缩放(自适应里部分组件需要, 如数字、文本、下拉框、下拉复选框、密码、下拉树、下拉复选树、日期)
+ *
+ * @return 是则返回true
+ */
+ public boolean shouldScaleCreator() {
+ return false;
+ }
+
+ /**
+ * 是否支持标题样式
+ * @return 默认false
+ */
+ public boolean hasTitleStyle() {
+ return false;
+ }
+
+ /**
+ * 响应点击事件
+ *
+ * @param editingMouseListener 鼠标点击,位置处理器
+ * @param e 鼠标点击事件
+ */
+ public void respondClick(EditingMouseListener editingMouseListener,MouseEvent e){
+ FormDesigner designer = editingMouseListener.getDesigner();
+ SelectionModel selectionModel = editingMouseListener.getSelectionModel();
+
+ if (e.getClickCount() <= 1) {
+ selectionModel.selectACreatorAtMouseEvent(e);
+ }
+
+ if (editingMouseListener.stopEditing()) {
+ if (this != designer.getRootComponent()) {
+ ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);
+ editingMouseListener.startEditing(this, adapter.getDesignerEditor(), adapter);
+ }
+ }
+ }
+
+ /**
+ * 删除相关组件
+ *
+ * @param creator 当前组件
+ * @param designer 表单设计器
+ *
+ */
+ public void deleteRelatedComponent(XCreator creator,FormDesigner designer){
+ return;
+ }
+
+ /**
+ * 选择相关组件
+ *
+ * @param creator 当前组件
+ *
+ */
+ public void seleteRelatedComponent(XCreator creator){
+ return;
+ }
+
+ /**
+ * 返回组件
+ * @return
+ * String
+ */
+ public XCreator getXCreator(){
+ return this;
+ }
+
+ /**
+ * 按百分比调整组件
+ * @param percent 百分比
+ * void
+ */
+ public void adjustCompSize(double percent){
+ return;
+ }
+
+ /**
+ * 返回一些需要的子组件
+ * @return 返回一些需要的子组件
+ * ArrayList>
+ */
+ public ArrayList> getTargetChildrenList(){
+ return new ArrayList();
+ }
+
+ public XLayoutContainer getOuterLayout(){
+ return this.getBackupParent();
+ }
+
+ /**
+ * 重新调整子组件宽度
+ * @param width 宽度
+ */
+ public void recalculateChildWidth(int width){
+ return;
+ }
+ /**
+ * 重新调整子组件高度
+ * @param height 高度
+ */
+ public void recalculateChildHeight(int height){
+ return;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XCreatorTools.java b/designer_form/src/com/fr/design/designer/creator/XCreatorTools.java
new file mode 100644
index 000000000..6434fcc91
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XCreatorTools.java
@@ -0,0 +1,58 @@
+/**
+ *
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Component;
+import java.util.ArrayList;
+
+/**
+ * @author jim
+ * @date 2014-11-7
+ *
+ */
+public interface XCreatorTools {
+
+ /**
+ * 控件树不显示此组件
+ * @param path 控件树list
+ */
+ void notShowInComponentTree(ArrayList path);
+
+ /**
+ * 重置组件的名称
+ * @param name 名称
+ */
+ void resetCreatorName(String name);
+
+ /**
+ * 返回编辑的子组件,scale为其内部组件
+ * @return 组件
+ */
+ XCreator getEditingChildCreator();
+
+ /**
+ * 返回对应属性表的组件,scale和title返回其子组件
+ * @return 组件
+ */
+ XCreator getPropertyDescriptorCreator();
+
+ /**
+ * 更新子组件的Bound; 没有不处理
+ * @param minHeight 最小高度
+ */
+ void updateChildBound(int minHeight);
+
+ /**
+ * 是否作为控件树的叶子节点
+ * @return 是则返回true
+ */
+ boolean isComponentTreeLeaf();
+
+ /**
+ * 是否为sclae和title专属容器
+ * @return 是则返回true
+ */
+ boolean isDedicateContainer();
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XCreatorUtils.java b/designer_form/src/com/fr/design/designer/creator/XCreatorUtils.java
new file mode 100644
index 000000000..19cfe2d8d
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XCreatorUtils.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import com.fr.base.FRContext;
+import com.fr.design.ExtraDesignClassManager;
+import com.fr.design.designer.creator.cardlayout.XCardAddButton;
+import com.fr.design.designer.creator.cardlayout.XCardSwitchButton;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout;
+import com.fr.design.designer.creator.cardlayout.XWCardTagLayout;
+import com.fr.design.designer.creator.cardlayout.XWCardTitleLayout;
+import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
+import com.fr.design.module.DesignModuleFactory;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.form.parameter.FormSubmitButton;
+import com.fr.form.ui.Button;
+import com.fr.form.ui.*;
+import com.fr.form.ui.Label;
+import com.fr.form.ui.TextArea;
+import com.fr.form.ui.container.*;
+import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
+import com.fr.form.ui.container.cardlayout.WCardTagLayout;
+import com.fr.form.ui.container.cardlayout.WCardTitleLayout;
+import com.fr.form.ui.container.cardlayout.WTabFitLayout;
+import com.fr.general.IOUtils;
+import com.fr.stable.StringUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.lang.reflect.Constructor;
+
+/**
+ * XCreator的相关处理
+ *
+ * @author richer
+ * @since 6.5.3
+ */
+public class XCreatorUtils {
+
+ public static java.util.Map, Class>> objectMap = new java.util.HashMap, Class>>();
+ public static java.util.Map, Class>> xLayoutMap = new java.util.HashMap, Class>>();
+
+ static {
+ objectMap.put(TextEditor.class, XTextEditor.class);
+ objectMap.put(TextArea.class, XTextArea.class);
+ objectMap.put(NumberEditor.class, XNumberEditor.class);
+ objectMap.put(FreeButton.class, XButton.class);
+ objectMap.put(CheckBox.class, XCheckBox.class);
+ objectMap.put(CheckBoxGroup.class, XCheckBoxGroup.class);
+ objectMap.put(ComboBox.class, XComboBox.class);
+ objectMap.put(ComboCheckBox.class, XComboCheckBox.class);
+ objectMap.put(DateEditor.class, XDateEditor.class);
+ objectMap.put(FileEditor.class, XFileUploader.class);
+ objectMap.put(Table.class, XTableEditor.class);
+ objectMap.put(IframeEditor.class, XIframeEditor.class);
+ objectMap.put(FreeButton.class, XButton.class);
+ objectMap.put(FormSubmitButton.class, XButton.class);
+ objectMap.put(Button.class, XButton.class);
+ objectMap.put(Label.class, XLabel.class);
+ objectMap.put(ListEditor.class, XListEditor.class);
+ objectMap.put(TableTree.class, XTableTree.class);
+ objectMap.put(MultiFileEditor.class, XMultiFileUploader.class);
+ objectMap.put(Password.class, XPassword.class);
+ objectMap.put(Radio.class, XRadio.class);
+ objectMap.put(RadioGroup.class, XRadioGroup.class);
+ objectMap.put(TreeEditor.class, XTreeEditor.class);
+ objectMap.put(TreeComboBoxEditor.class, XTreeComboBoxEditor.class);
+ objectMap.put(EditorHolder.class, XEditorHolder.class);
+ objectMap.put(DataTable.class, XDataTable.class);
+ objectMap.put(ElementCaseEditor.class, XElementCase.class);
+ objectMap.put(NameWidget.class, XNameWidget.class);
+ objectMap.put(CardSwitchButton.class, XCardSwitchButton.class);
+ objectMap.put(CardAddButton.class, XCardAddButton.class);
+ putExtraEditor();
+
+ xLayoutMap.put(WAbsoluteLayout.class, XWAbsoluteLayout.class);
+ xLayoutMap.put(WParameterLayout.class, XWParameterLayout.class);
+ xLayoutMap.put(WAbsoluteLayout.class, XWAbsoluteLayout.class);
+ xLayoutMap.put(WHorizontalBoxLayout.class, XWHorizontalBoxLayout.class);
+ xLayoutMap.put(WBorderLayout.class, XWBorderLayout.class);
+ xLayoutMap.put(WCardLayout.class, XWCardLayout.class);
+ xLayoutMap.put(WVerticalBoxLayout.class, XWVerticalBoxLayout.class);
+ xLayoutMap.put(WHorizontalSplitLayout.class, XWHorizontalSplitLayout.class);
+ xLayoutMap.put(WVerticalSplitLayout.class, XWVerticalSplitLayout.class);
+ xLayoutMap.put(WGridLayout.class, XWGridLayout.class);
+
+ xLayoutMap.put(WFitLayout.class, XWFitLayout.class);
+ xLayoutMap.put(WScaleLayout.class, XWScaleLayout.class);
+ xLayoutMap.put(WTitleLayout.class, XWTitleLayout.class);
+ xLayoutMap.put(WCardTagLayout.class, XWCardTagLayout.class);
+ xLayoutMap.put(WCardTitleLayout.class, XWCardTitleLayout.class);
+ xLayoutMap.put(WTabFitLayout.class, XWTabFitLayout.class);
+ xLayoutMap.put(WCardMainBorderLayout.class, XWCardMainBorderLayout.class);
+
+ objectMap.putAll(ExtraDesignClassManager.getInstance().getParameterWidgetOptionsMap());
+ objectMap.putAll(ExtraDesignClassManager.getInstance().getFormWidgetOptionsMap());
+ }
+
+ private static void putExtraEditor() {
+ if (DesignModuleFactory.getChartEditorClass() != null) {
+ objectMap.put(DesignModuleFactory.getChartEditorClass(), XChartEditor.class);
+ }
+ }
+
+ private static Class extends XCreator> searchXCreatorClass(Class extends Widget> clazz) {
+ Class extends XCreator> xClazz = (Class extends XCreator>) objectMap.get(clazz);
+ if (xClazz == null) {
+ xClazz = (Class extends XCreator>) xLayoutMap.get(clazz);
+ }
+ return xClazz;
+ }
+
+ /**
+ *创建creator
+ * @param widget 控件
+ * @return 返回控件的creator
+ */
+ public static XCreator createXCreator(Widget widget) {
+ return createXCreator(widget, new Dimension());
+ }
+
+ /**
+ * 带初始大小的Widget转化为XCreator当然XCreator也需要把大小赋值上
+ * @param widget 控件
+ * @param d 大小
+ * @return 返回控件的xcreator
+ */
+ public static XCreator createXCreator(Widget widget, Dimension d) {
+ Class extends Widget> widgetClass;
+ Class extends XCreator> clazz;
+
+ if (widget == null) {
+ clazz = NullCreator.class;
+ } else {
+ widgetClass = widget.getClass();
+ clazz = XCreatorUtils.searchXCreatorClass(widgetClass);
+ if (clazz == null) {
+ FRContext.getLogger().error(widget + "'s" + " xcreator doesn't exsit!");
+ clazz = NullCreator.class;
+ }
+ }
+ XCreator creator = null;
+ Constructor[] constructors = clazz.getConstructors();
+ for (Constructor c : constructors) {
+ try {
+ creator = (XCreator) c.newInstance(widget, d);
+ break;
+ } catch (Exception ignore) {
+ // richie:这里的错误可以忽略
+// FRContext.getLogger().error(ignore.getMessage());
+ }
+ }
+ if (creator == null) {
+ FRContext.getLogger().error("Error to create xcreator!");
+ creator = new NullCreator(widget, d);
+ }
+ return creator;
+ }
+
+ /**
+ *刷新所有名字控件
+ * @param container 布局容器
+ */
+ public static void refreshAllNameWidgets(XLayoutContainer container) {
+ _refreshNameWidget(container);
+ LayoutUtils.layoutRootContainer(container);
+ }
+
+ private static void _refreshNameWidget(XLayoutContainer container) {
+ for (int i = 0, len = container.getXCreatorCount(); i < len; i++) {
+ XCreator creator = container.getXCreator(i);
+ if (creator instanceof XLayoutContainer) {
+ _refreshNameWidget((XLayoutContainer) creator);
+ } else if (creator instanceof XNameWidget) {
+ ((XNameWidget) creator).rebuild();
+ }
+ }
+ }
+
+ /**
+ * 获取焦点组件所在的顶层容器,不包括目标本身
+ *
+ * @param creator 组件
+ * @return 返回父容器
+ */
+ public static XLayoutContainer getParentXLayoutContainer(XCreator creator) {
+ Container c = creator.getParent();
+ while (c != null) {
+ XCreator crea = (XCreator) c;
+ if (crea.isDedicateContainer()) {
+ return (XLayoutContainer) c.getParent();
+ }
+ if (c instanceof XLayoutContainer) {
+ return (XLayoutContainer) c;
+ }
+ c = c.getParent();
+ }
+
+ return null;
+ }
+
+ /**
+ * 获取焦点组件所在的顶层容器,可能是目标本身
+ *
+ * @param creator 组件
+ * @return 返回顶层容器
+ */
+ public static XLayoutContainer getHotspotContainer(XCreator creator) {
+ if (creator.isDedicateContainer()) {
+ return (XLayoutContainer) creator.getParent();
+ }
+ if (creator instanceof XLayoutContainer) {
+ return (XLayoutContainer) creator;
+ }
+ return getParentXLayoutContainer(creator);
+ }
+
+ /**
+ * 返回组件的图标
+ *
+ * @param creator 组件
+ * @return 组件icon
+ */
+ public static Icon getCreatorIcon(XCreator creator) {
+ String iconPath = creator.getIconPath();
+ if (StringUtils.isEmpty(iconPath)) {
+ return null;
+ }
+ return IOUtils.readIcon(iconPath);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XCustomWriteAbleRepeatEditor.java b/designer_form/src/com/fr/design/designer/creator/XCustomWriteAbleRepeatEditor.java
new file mode 100644
index 000000000..6166dea95
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XCustomWriteAbleRepeatEditor.java
@@ -0,0 +1 @@
+package com.fr.design.designer.creator;
import com.fr.form.ui.WriteAbleRepeatEditor;
import com.fr.general.Inter;
import com.fr.stable.ArrayUtils;
import java.awt.*;
import java.beans.IntrospectionException;
/**
* Author : Shockway
* Date: 13-9-22
* Time: 上午10:40
*/
public abstract class XCustomWriteAbleRepeatEditor extends XWriteAbleRepeatEditor {
public XCustomWriteAbleRepeatEditor(WriteAbleRepeatEditor widget, Dimension initSize) {
super(widget, initSize);
}
public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
new CRPropertyDescriptor[] { new CRPropertyDescriptor("customData",
this.data.getClass()).setI18NName(Inter.getLocText("Form-Allow_CustomData"))});
}
}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XDataTable.java b/designer_form/src/com/fr/design/designer/creator/XDataTable.java
new file mode 100644
index 000000000..054b5267f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XDataTable.java
@@ -0,0 +1,94 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.stable.core.PropertyChangeAdapter;
+import com.fr.design.mainframe.widget.editors.DataTableConfigPane;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.designer.beans.events.DesignerEditor;
+import com.fr.form.data.DataTableConfig;
+import com.fr.form.ui.DataTable;
+import com.fr.form.ui.WidgetValue;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+
+public class XDataTable extends XWidgetCreator{
+
+ private DesignerEditor designerEditor;
+
+ public XDataTable(DataTable widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ protected String getIconName() {
+ return "text_field_16.png";
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] { new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(WidgetValueEditor.class)
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ if (((DataTable) toData()).getWidgetValue() != null
+ && ((DataTable) toData()).getWidgetValue().getValue() instanceof DataTableConfig) {
+ designerEditor.getEditorTarget().populate(
+ (DataTableConfig) ((DataTable) toData()).getWidgetValue().getValue());
+ }
+ }
+ }) });
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ designerEditor.paintEditor(g, this.getSize());
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ designerEditor.getEditorTarget().setSize(this.getSize());
+ LayoutUtils.layoutContainer(designerEditor.getEditorTarget());
+ if (((DataTable) toData()).getWidgetValue() != null
+ && ((DataTable) toData()).getWidgetValue().getValue() instanceof DataTableConfig) {
+ designerEditor.getEditorTarget().populate(
+ (DataTableConfig) ((DataTable) toData()).getWidgetValue().getValue());
+ }
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(250, 100);
+ }
+
+ @Override
+ public DesignerEditor getDesignerEditor() {
+ return designerEditor;
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (designerEditor == null) {
+ final DataTableConfigPane configPane = new DataTableConfigPane();
+ designerEditor = new DesignerEditor(configPane);
+ configPane.addpropertyChangeListener(designerEditor);
+ designerEditor.addStopEditingListener(new PropertyChangeAdapter() {
+ @Override
+ public void propertyChange() {
+ ((DataTable) toData()).setWidgetValue(new WidgetValue(configPane.update()));
+ }
+ });
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XDateEditor.java b/designer_form/src/com/fr/design/designer/creator/XDateEditor.java
new file mode 100644
index 000000000..80efa40fc
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XDateEditor.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+import java.util.Date;
+
+import javax.swing.JComponent;
+
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.widget.editors.DateFormatEditor;
+import com.fr.design.mainframe.widget.editors.DateRangeEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.DateCellRenderer;
+import com.fr.form.ui.DateEditor;
+import com.fr.form.ui.WidgetValue;
+import com.fr.general.DateUtils;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.StringUtils;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XDateEditor extends XDirectWriteEditor {
+
+ private UITextField textField;
+ private LimpidButton btn;
+
+ public XDateEditor(DateEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 控件的属性列表
+ * @return 此控件所用的属性列表
+ * @throws IntrospectionException 异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(
+ WidgetValueEditor.class).setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ initFieldText();
+ }
+ }),
+ new CRPropertyDescriptor("formatText", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Engine_Format")).setEditorClass(formatClass()).setRendererClass(
+ DateCellRenderer.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("startDate", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Start-Date")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced").setEditorClass(DateRangeEditor.class),
+ new CRPropertyDescriptor("endDate", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_End-Date")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced").setEditorClass(DateRangeEditor.class),
+ new CRPropertyDescriptor("returnDate", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Return-Date")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Return-Value"),
+ new CRPropertyDescriptor("waterMark", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_WaterMark")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced")
+ });
+ }
+
+ protected Class formatClass() {
+ return DateFormatEditor.class;
+ }
+
+ private void initFieldText() {
+ DateEditor dateEditor = (DateEditor) data;
+ if (dateEditor.getWidgetValue() != null) {
+ WidgetValue widgetValue = dateEditor.getWidgetValue();
+ //控件值.toString
+ String valueStr = widgetValue.toString();
+ //控件值
+ Object value = widgetValue.getValue();
+ //格式
+ String format = dateEditor.getFormatText();
+
+ if(value instanceof Date){
+ valueStr = DateUtils.getDate2Str(format, (Date) value);
+ }
+
+ //日期控件默认值
+ if(StringUtils.isEmpty(valueStr)){
+ valueStr = DateUtils.getDate2Str(format, new Date());
+ dateEditor.setWidgetValue(new WidgetValue(new Date()));
+ }
+
+ textField.setText(valueStr);
+ }
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ initFieldText();
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ editor.add(textField = new UITextField(5), BorderLayout.CENTER);
+ btn = new LimpidButton("", this.getIconPath(), toData().isVisible() ? FULL_OPACITY : HALF_OPACITY);
+ btn.setPreferredSize(new Dimension(21, 21));
+ editor.add(btn, BorderLayout.EAST);
+ textField.setOpaque(false);
+ editor.setBackground(Color.WHITE);
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "date_16.png";
+ }
+
+ protected void makeVisible(boolean visible) {
+ btn.makeVisible(visible);
+ }
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName){
+ return new XWScaleLayout();
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ this.setSize(width, minHeight);
+ parentPanel.add(this);
+ }
+
+ /**
+ * 此控件在自适应布局要保持原样高度
+ *
+ * @return 是则返回true
+ */
+ @Override
+ public boolean shouldScaleCreator() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XDirectWriteEditor.java b/designer_form/src/com/fr/design/designer/creator/XDirectWriteEditor.java
new file mode 100644
index 000000000..80b899380
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XDirectWriteEditor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import com.fr.form.ui.DirectWriteEditor;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class XDirectWriteEditor extends XFieldEditor {
+
+ public XDirectWriteEditor(DirectWriteEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] { new CRPropertyDescriptor("directEdit", this.data.getClass())
+ .setI18NName(Inter.getLocText("Form-Allow_Edit")) });
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XEditorHolder.java b/designer_form/src/com/fr/design/designer/creator/XEditorHolder.java
new file mode 100644
index 000000000..c036d90a7
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XEditorHolder.java
@@ -0,0 +1,96 @@
+package com.fr.design.designer.creator;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.events.DesignerEditor;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.gui.xpane.ToolTipEditor;
+import com.fr.design.mainframe.EditingMouseListener;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.form.ui.EditorHolder;
+
+import javax.swing.*;
+
+import java.awt.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+
+public class XEditorHolder extends XWidgetCreator {
+
+ private DesignerEditor designerEditor;
+ private static Icon icon = BaseUtils.readIcon("/com/fr/design/images/form/designer/holder.png");
+
+// public XEditorHolder(EditorHolder widget) {
+// super(widget);
+// }
+
+ public XEditorHolder(EditorHolder widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 响应点击事件
+ *
+ * @param editingMouseListener 事件处理器
+ * @param e 点击事件
+ *
+ */
+ public void respondClick(EditingMouseListener editingMouseListener,MouseEvent e){
+
+ FormDesigner designer = editingMouseListener.getDesigner();
+ if (editingMouseListener.stopEditing()) {
+ ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);
+ editingMouseListener.startEditing(this, adapter.getDesignerEditor(), adapter);
+ Rectangle rect = this.getBounds();
+ int min = rect.x + rect.width / 2 - editingMouseListener.getMinMoveSize();
+ int max = rect.x + rect.width / 2 + editingMouseListener.getMinMoveSize();
+ if (e.getX() > min && e.getX() < max) {
+ ToolTipEditor.getInstance().showToolTip((XEditorHolder) this, e.getXOnScreen(),
+ e.getYOnScreen());
+ }
+
+ }
+ }
+
+ @Override
+ protected String getIconName() {
+ return "text_field_16.png";
+ }
+
+ @Override
+ public DesignerEditor getDesignerEditor() {
+ if (designerEditor == null) {
+ UILabel comp = new UILabel(icon);
+ designerEditor = new DesignerEditor(comp);
+
+ comp.addFocusListener(new FocusListener() {
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ ToolTipEditor.getInstance().hideToolTip();
+
+ }
+
+ });
+
+ comp.setBorder(BorderFactory.createLineBorder(new Color(128, 152, 186)));
+
+ }
+ return designerEditor;
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = new UILabel(icon);
+ editor.setBorder(BorderFactory.createLineBorder(new Color(128, 152, 186)));
+ }
+ return editor;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XElementCase.java b/designer_form/src/com/fr/design/designer/creator/XElementCase.java
new file mode 100644
index 000000000..32af5487a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XElementCase.java
@@ -0,0 +1,235 @@
+package com.fr.design.designer.creator;
+
+import com.fr.design.ExtraDesignClassManager;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.fun.FormElementCaseEditorProcessor;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.mainframe.CoverReportPane;
+import com.fr.design.mainframe.EditingMouseListener;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.widget.editors.BooleanEditor;
+import com.fr.design.mainframe.widget.editors.PaddingMarginEditor;
+import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
+import com.fr.design.mainframe.widget.renderer.LayoutBorderStyleRenderer;
+import com.fr.design.mainframe.widget.renderer.PaddingMarginCellRenderer;
+import com.fr.form.FormElementCaseContainerProvider;
+import com.fr.form.FormElementCaseProvider;
+import com.fr.form.ui.ElementCaseEditor;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.awt.image.BufferedImage;
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+
+public class XElementCase extends XBorderStyleWidgetCreator implements FormElementCaseContainerProvider{
+ private UILabel imageLable;
+ private JPanel coverPanel;
+
+ public XElementCase(ElementCaseEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ // 报表块初始化时要加载对应的borderStyle
+ initBorderStyle();
+ }
+
+ /**
+ * 是否支持设置标题
+ * @return 是返回true
+ */
+ public boolean hasTitleStyle() {
+ return true;
+ }
+
+ /**
+ * 返回组件属性值
+ * @return 返回组件属性值
+ * @throws IntrospectionException 异常
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+
+ CRPropertyDescriptor[] propertyTableEditor = new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("widgetName", this.data.getClass())
+ .setI18NName(Inter.getLocText("Form-Widget_Name")),
+ new CRPropertyDescriptor("borderStyle", this.data.getClass()).setEditorClass(
+ WLayoutBorderStyleEditor.class).setRendererClass(LayoutBorderStyleRenderer.class).setI18NName(
+ Inter.getLocText("FR-Designer-Widget_Style")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ initStyle();
+ }
+ }),
+ new CRPropertyDescriptor("margin", this.data.getClass()).setEditorClass(PaddingMarginEditor.class)
+ .setRendererClass(PaddingMarginCellRenderer.class).setI18NName(Inter.getLocText("FR-Layout_Padding"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("showToolBar", this.data.getClass()).setEditorClass(BooleanEditor.class)
+ .setI18NName(Inter.getLocText("Form-EC_toolbar"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+
+ };
+
+ FormElementCaseEditorProcessor processor = ExtraDesignClassManager.getInstance().getPropertyTableEditor();
+ if (processor == null){
+ return propertyTableEditor;
+ }
+ PropertyDescriptor[] extraEditor = processor.createPropertyDescriptor(this.data.getClass());
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(propertyTableEditor, extraEditor);
+ }
+
+ @Override
+ protected String getIconName() {
+ return "text_field_16.png";
+ }
+
+ /**
+ * 返回组件默认名
+ * @return 组件类名(小写)
+ */
+ public String createDefaultName() {
+ return "report";
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ setBorder(DEFALUTBORDER);
+ editor = new JPanel();
+ editor.setBackground(null);
+ editor.setLayout(null);
+ imageLable = initImageBackground();
+
+ coverPanel = new CoverReportPane();
+ coverPanel.setPreferredSize(imageLable.getPreferredSize());
+ coverPanel.setBounds(imageLable.getBounds());
+
+ editor.add(coverPanel);
+ coverPanel.setVisible(false);
+ editor.add(imageLable);
+ }
+ return editor;
+ }
+
+ /**
+ * 从data中获取到图片背景, 并设置到Label上
+ */
+ private UILabel initImageBackground(){
+ UILabel imageLable = new UILabel();
+ BufferedImage image = toData().getECImage();
+ setLabelBackground(image, imageLable);
+
+ return imageLable;
+ }
+
+ /**
+ * 设置指定Label的背景
+ */
+ private void setLabelBackground(Image image, UILabel imageLable){
+ ImageIcon icon = new ImageIcon(image);
+ imageLable.setIcon(icon);
+ imageLable.setOpaque(true);
+ imageLable.setLayout(null);
+ imageLable.setBounds(0, 0, icon.getIconWidth(), icon.getIconHeight());
+ }
+
+ /**
+ * 是否展现覆盖的pane
+ * @param display 是否
+ */
+ public void displayCoverPane(boolean display){
+ coverPanel.setVisible(display);
+ coverPanel.setPreferredSize(editor.getPreferredSize());
+ coverPanel.setBounds(editor.getBounds());
+ editor.repaint();
+ }
+
+ public JComponent getCoverPane(){
+ return coverPanel;
+ }
+
+ /**
+ * 初始化大小
+ * @return 尺寸
+ */
+ public Dimension initEditorSize() {
+ return new Dimension(250, 100);
+ }
+
+ /**
+ * 是否是报表块
+ * @return 是
+ */
+ public boolean isReport() {
+ return true;
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return false;
+ }
+
+ /**
+ * 返回报表块对应的widget
+ * @return 返回ElementCaseEditor
+ */
+ public ElementCaseEditor toData() {
+ return ((ElementCaseEditor) data);
+ }
+
+ public FormElementCaseProvider getElementCase() {
+ return toData().getElementCase();
+ }
+
+ public String getElementCaseContainerName() {
+ return toData().getWidgetName();
+ }
+
+ public void setElementCase(FormElementCaseProvider el) {
+ toData().setElementCase(el);
+ }
+
+ public void setBackground(BufferedImage image){
+ toData().setECImage(image);
+ setEditorIcon(image);
+ }
+
+ private void setEditorIcon(BufferedImage image){
+ setLabelBackground(image, imageLable);
+ }
+
+ public Dimension getSize(){
+ return new Dimension(this.getWidth(), this.getHeight());
+ }
+
+ /**
+ * 响应点击事件
+ * @param editingMouseListener 事件处理器
+ * @param e 点击事件
+ */
+ public void respondClick(EditingMouseListener editingMouseListener,MouseEvent e){
+ super.respondClick(editingMouseListener, e);
+ switchTab(e,editingMouseListener);
+ }
+
+
+ private void switchTab(MouseEvent e,EditingMouseListener editingMouseListener){
+ FormDesigner designer = editingMouseListener.getDesigner();
+ if (e.getClickCount() == 2 || designer.getCursor().getType() == Cursor.HAND_CURSOR){
+ FormElementCaseContainerProvider component = (FormElementCaseContainerProvider) designer.getComponentAt(e);
+ //切换设计器
+ designer.switchTab(component);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XFieldEditor.java b/designer_form/src/com/fr/design/designer/creator/XFieldEditor.java
new file mode 100644
index 000000000..c5af4a4ae
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XFieldEditor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.border.Border;
+
+import com.fr.design.mainframe.widget.editors.InChangeBooleanEditor;
+import com.fr.form.ui.FieldEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class XFieldEditor extends XWidgetCreator {
+
+ protected static final Border FIELDBORDER = BorderFactory.createLineBorder(new Color(128, 152, 186), 1);
+
+ public XFieldEditor(FieldEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+ super.supportedDescriptor(),getCRPropertyDescriptor()
+ );
+ }
+
+ private CRPropertyDescriptor[] getCRPropertyDescriptor() throws IntrospectionException {
+ CRPropertyDescriptor allowBlank = new CRPropertyDescriptor("allowBlank", this.data.getClass()).setI18NName(
+ Inter.getLocText("Allow_Blank")).setEditorClass(InChangeBooleanEditor.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced");
+ CRPropertyDescriptor blankErrorMsg = new CRPropertyDescriptor("errorMessage", this.data.getClass()).setI18NName(
+ Inter.getLocText("Verify-Message"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced");
+ CRPropertyDescriptor fontSize = new CRPropertyDescriptor("fontSize", this.data.getClass(), "getFontSize", "setFontSize")
+ .setI18NName(Inter.getLocText(new String[]{"FRFont", "FRFont-Size"}))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced");
+ return !((FieldEditor) toData()).isAllowBlank() ?
+ new CRPropertyDescriptor[] {allowBlank, blankErrorMsg, fontSize}
+ : new CRPropertyDescriptor[] {allowBlank, fontSize};
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XFileUploader.java b/designer_form/src/com/fr/design/designer/creator/XFileUploader.java
new file mode 100644
index 000000000..6966c8371
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XFileUploader.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.design.gui.ibutton.UIButton;
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.form.ui.FileEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XFileUploader extends XFieldEditor {
+
+ public XFileUploader(FileEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+ super.supportedDescriptor(),
+ new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("allowTypes", this.data.getClass())
+ .setI18NName(Inter.getLocText("File-Allow_Upload_Files"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ });
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ UITextField textField = new UITextField(10);
+ editor.add(textField, BorderLayout.CENTER);
+ UIButton btn = new UIButton("...");
+ btn.setPreferredSize(new Dimension(24, 24));
+ editor.add(btn, BorderLayout.EAST);
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "file_up.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XIframeEditor.java b/designer_form/src/com/fr/design/designer/creator/XIframeEditor.java
new file mode 100644
index 000000000..c1b0356e9
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XIframeEditor.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+import com.fr.stable.core.PropertyChangeAdapter;
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.widget.editors.ParameterEditor;
+import com.fr.design.mainframe.widget.renderer.ParameterRenderer;
+import com.fr.form.ui.IframeEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.StringUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XIframeEditor extends XWidgetCreator {
+
+ public XIframeEditor(IframeEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("src", this.data.getClass()).setI18NName(Inter.getLocText("Form-Url"))
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ initFieldText();
+ }
+ }),
+ new CRPropertyDescriptor("overflowx", this.data.getClass()).setI18NName(
+ Inter.getLocText("Preference-Horizontal_Scroll_Bar_Visible")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("overflowy", this.data.getClass()).setI18NName(
+ Inter.getLocText("Preference-Vertical_Scroll_Bar_Visible")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("parameters", this.data.getClass())
+ .setI18NName(Inter.getLocText("Parameters")).setEditorClass(ParameterEditor.class)
+ .setRendererClass(ParameterRenderer.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced") });
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ UITextField address = new UITextField();
+ editor.add(address, BorderLayout.NORTH);
+ JPanel contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
+ contentPane.setBackground(Color.white);
+ editor.add(contentPane, BorderLayout.CENTER);
+ }
+ return editor;
+ }
+
+ private void initFieldText() {
+ IframeEditor iframe = (IframeEditor) data;
+ String src = iframe.getSrc();
+ ((UITextField) editor.getComponent(0)).setText(StringUtils.isNotEmpty(src) ? src : "http://ip:port/address?");
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ initFieldText();
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(160, 80);
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * 这里控制 网页预定义控件在工具栏不显示
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return false;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "iframe_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XLabel.java b/designer_form/src/com/fr/design/designer/creator/XLabel.java
new file mode 100644
index 000000000..20491ec39
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XLabel.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+import javax.swing.SwingConstants;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.ScreenResolution;
+import com.fr.base.Style;
+import com.fr.design.border.UIRoundedBorder;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.mainframe.widget.editors.FontEditor;
+import com.fr.design.mainframe.widget.editors.ItemCellEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.FontCellRenderer;
+import com.fr.design.mainframe.widget.renderer.LabelHorizontalAlignmentRenderer;
+import com.fr.form.ui.Label;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.Constants;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XLabel extends XWidgetCreator {
+
+ private int cornerSize = 15;
+
+ public XLabel(Label widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 生成creator对应的控件widget
+ * @return 控件widget
+ */
+ public Label toData() {
+ return (Label) data;
+ }
+
+ /**
+ * 返回组件属性值
+ * @return 返回组件属性值
+ * @throws IntrospectionException 异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"FR-Designer_Widget", "Value"})).setEditorClass(
+ WidgetValueEditor.class),
+ new CRPropertyDescriptor("wrap", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_StyleAlignment-Wrap_Text")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("verticalCenter", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_PageSetup-Vertically")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("textalign", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Alignment-Style")).setEditorClass(ItemCellEditor.class)
+ .setRendererClass(LabelHorizontalAlignmentRenderer.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("font", this.data.getClass()).setI18NName(Inter.getLocText("FR-Designer_Font"))
+ .setEditorClass(FontEditor.class).setRendererClass(FontCellRenderer.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced") });
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Label label = (Label) data;
+ Dimension size = this.getSize();
+ //先画背景,再画标题
+ if (toData().getBackground() != null) {
+ toData().getBackground().paint(g,new Rectangle2D.Double(0, 0, size.getWidth(), size.getHeight()));
+ }
+ if (label.getWidgetValue() != null) {
+ Graphics2D g2d = (Graphics2D) g.create();
+ BaseUtils.drawStringStyleInRotation(g2d, this.getWidth(), this.getHeight(), label.getWidgetValue()
+ .toString(), Style.getInstance(label.getFont()).deriveHorizontalAlignment(label.getTextalign())
+ .deriveVerticalAlignment(label.isVerticalCenter() ? SwingConstants.CENTER : SwingConstants.TOP)
+ .deriveTextStyle(label.isWrap() ? Style.TEXTSTYLE_WRAPTEXT : Style.TEXTSTYLE_SINGLELINE),
+ ScreenResolution.getScreenResolution());
+ }
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = new UILabel();
+ }
+ return editor;
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ if (toData().getBorder() != Constants.LINE_NONE) {
+ this.setBorder(new UIRoundedBorder(toData().getBorder(), toData().getColor(), toData().isCorner() ? cornerSize : 0));
+ } else {
+ this.setBorder(DEFALUTBORDER);
+ }
+ }
+
+ @Override
+ protected String getIconName() {
+ return "label_16.png";
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XLayoutContainer.java b/designer_form/src/com/fr/design/designer/creator/XLayoutContainer.java
new file mode 100644
index 000000000..fec4899a8
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XLayoutContainer.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import com.fr.base.FRContext;
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.form.layout.FRLayoutManager;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.widget.editors.PaddingMarginEditor;
+import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor;
+import com.fr.design.mainframe.widget.renderer.LayoutBorderStyleRenderer;
+import com.fr.design.mainframe.widget.renderer.PaddingMarginCellRenderer;
+import com.fr.design.parameter.ParameterBridge;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WLayout;
+import com.fr.general.Background;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ContainerEvent;
+import java.awt.event.ContainerListener;
+import java.beans.IntrospectionException;
+import java.util.List;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class XLayoutContainer extends XBorderStyleWidgetCreator implements ContainerListener, ParameterBridge {
+
+ // 布局内部组件默认最小宽度36,最小高度21
+ public static int MIN_WIDTH = 36;
+ public static int MIN_HEIGHT = 21;
+
+ protected static final Dimension LARGEPREFERREDSIZE = new Dimension(200, 200);
+ protected boolean isRefreshing;
+ protected int default_Length = 5; // 取指定点坐在的组件,默认为5保证取四侧相邻的组件时x、y在组件内非边框上
+
+ public XLayoutContainer(WLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ this.addContainerListener(this);
+ }
+
+ /**
+ * 得到属性名
+ * @return 属性名
+ * @throws IntrospectionException
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetName", this.data.getClass()).setI18NName(Inter
+ .getLocText("FR-Designer_Form-Widget_Name")),
+ new CRPropertyDescriptor("borderStyle", this.data.getClass()).setEditorClass(
+ WLayoutBorderStyleEditor.class).setRendererClass(LayoutBorderStyleRenderer.class).setI18NName(
+ Inter.getLocText("FR-Engine_Style")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ initStyle();
+ }
+ }),
+ new CRPropertyDescriptor("margin", this.data.getClass()).setEditorClass(PaddingMarginEditor.class)
+ .setRendererClass(PaddingMarginCellRenderer.class).setI18NName(Inter.getLocText("FR-Designer_Layout-Padding"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ };
+ }
+
+ /**
+ * 返回对应的wlayout
+ * @return wlayout控件
+ */
+ public WLayout toData() {
+ return (WLayout) data;
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ initBorderStyle();
+ this.initLayoutManager();
+ this.convert();
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ return this;
+ }
+
+ /**
+ * 当前组件zorder位置替换新的控件
+ * @param widget 控件
+ * @param oldcreator 旧组件
+ * @return 组件
+ */
+ public XCreator replace(Widget widget, XCreator oldcreator) {
+ int i = this.getComponentZOrder(oldcreator);
+ if (i != -1) {
+ this.toData().replace(widget, oldcreator.toData());
+ this.convert();
+ XCreator creator = (XCreator) this.getComponent(i);
+ creator.setSize(oldcreator.getSize());
+ return creator;
+ }
+ return null;
+ }
+
+ /**
+ * 初始化时默认的组件大小
+ * @return 默认Dimension
+ */
+ public Dimension initEditorSize() {
+ return LARGEPREFERREDSIZE;
+ }
+
+ protected abstract void initLayoutManager();
+
+ /**
+ * 将WLayout转换为XLayoutContainer
+ */
+ public void convert() {
+ isRefreshing = true;
+ WLayout layout = this.toData();
+ this.removeAll();
+ addWidgetToSwingComponent(layout);
+ isRefreshing = false;
+ }
+
+ protected void addWidgetToSwingComponent(WLayout layout) {
+ for (int i = 0; i < layout.getWidgetCount(); i++) {
+ Widget wgt = layout.getWidget(i);
+ if (wgt != null) {
+ XWidgetCreator comp = (XWidgetCreator) XCreatorUtils.createXCreator(wgt, calculatePreferredSize(wgt));
+ this.add(comp, i);
+ }
+ }
+ }
+
+ /**
+ * 设计界面中有组件添加时,要通知WLayout容器重新paint
+ * @param e 待说明
+ */
+ @Override
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ WLayout wlayout = this.toData();
+ Widget wgt = creator.toData();
+ wlayout.addWidget(wgt);
+ this.recalculateChildrenPreferredSize();
+ }
+
+ /**
+ * 设计界面中有组件添加时,要通知WLayout容器重新paint
+ * @param e 待说明
+ */
+ @Override
+ public void componentRemoved(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ WLayout wlayout = this.toData();
+ Widget wgt = ((XWidgetCreator) e.getChild()).toData();
+ wlayout.removeWidget(wgt);
+ this.recalculateChildrenPreferredSize();
+ }
+
+ /**
+ * 根据widget的属性值来获取
+ * @param wgt
+ * @return
+ */
+ protected Dimension calculatePreferredSize(Widget wgt) {
+ return new Dimension();
+ }
+
+ /**
+ * 重新调整子组件的大小
+ */
+ public void recalculateChildrenPreferredSize() {
+ for (int i = 0; i < this.getComponentCount(); i++) {
+ XCreator creator = this.getXCreator(i);
+ Widget wgt = creator.toData();
+ Dimension dim = calculatePreferredSize(wgt);
+ creator.setPreferredSize(dim);
+ creator.setMaximumSize(dim);
+ }
+ }
+
+ public int getXCreatorCount() {
+ return getComponentCount();
+ }
+
+ public XCreator getXCreator(int i) {
+ return (XCreator) getComponent(i);
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return false;
+ }
+
+ /**
+ * 是否作为控件树的叶子节点
+ * @return 是则返回true
+ */
+ public boolean isComponentTreeLeaf() {
+ return false;
+ }
+
+ public List getAllXCreatorNameList(XCreator xCreator, List namelist){
+ for (int i = 0; i < ((XLayoutContainer)xCreator).getXCreatorCount(); i++) {
+ XCreator creatorSon = ((XLayoutContainer)xCreator).getXCreator(i);
+ creatorSon.getAllXCreatorNameList(creatorSon, namelist);
+ }
+ return namelist;
+ }
+
+ /**
+ * 是否有查询按钮
+ * @param xCreator 控件或容器
+ * @return 有无查询按钮
+ */
+ public boolean SearchQueryCreators(XCreator xCreator) {
+ for (int i = 0; i < ((XLayoutContainer)xCreator).getXCreatorCount(); i++) {
+ XCreator creatorSon = ((XLayoutContainer)xCreator).getXCreator(i);
+ if(creatorSon.SearchQueryCreators(creatorSon)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public FRLayoutManager getFRLayout() {
+ LayoutManager layout = getLayout();
+ if (layout instanceof FRLayoutManager) {
+ return (FRLayoutManager) layout;
+ }
+ FRContext.getLogger().error("FRLayoutManager isn't exsit!");
+ return null;
+ }
+
+ public abstract LayoutAdapter getLayoutAdapter();
+
+ public int getIndexOfChild(Object child) {
+ int count = getComponentCount();
+ for (int i = 0; i < count; i++) {
+ Component comp = getComponent(i);
+ if (comp == child) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 主要为自适应用
+ * 返回指定point的上方组件
+ * @param x x位置
+ * @param y y位置
+ * @return 指定位置的组件
+ */
+ public Component getTopComp(int x, int y) {
+ return this.getComponentAt(x, y-default_Length);
+ }
+
+ /**
+ * 主要为自适应用
+ * 返回指定point的左方组件
+ * @param x x位置
+ * @param y y位置
+ * @return 指定位置的组件
+ */
+ public Component getLeftComp(int x, int y) {
+ return this.getComponentAt(x-default_Length, y);
+ }
+
+ /**
+ * 返回指定point的右方组件
+ * @param x x位置
+ * @param y y位置
+ * @param w 宽度
+ * @return 指定位置的组件
+ */
+ public Component getRightComp(int x, int y, int w) {
+ return this.getComponentAt(x+w+default_Length, y);
+ }
+
+ /**
+ * 返回指定point的下方组件
+ * @param x x位置
+ * @param y y位置
+ * @param h 高度
+ * @return 指定位置的组件
+ */
+ public Component getBottomComp(int x, int y, int h) {
+ return this.getComponentAt(x, y+h+default_Length);
+ }
+
+ /**
+ * 返回指定point的上方且是右侧的组件
+ * @param x x位置
+ * @param y y位置
+ * @param w 宽度
+ * @return 指定位置的组件
+ */
+ public Component getRightTopComp(int x, int y, int w) {
+ return this.getComponentAt(x+w-default_Length, y-default_Length);
+ }
+
+ /**
+ * 返回指定point的左方且是下侧的组件
+ * @param x x位置
+ * @param y y位置
+ * @param h 高度
+ * @return 指定位置的组件
+ */
+ public Component getBottomLeftComp(int x, int y, int h) {
+ return this.getComponentAt(x-default_Length, y+h-default_Length);
+ }
+
+ /**
+ * 返回指定point的右方且是下侧的组件
+ * @param x x位置
+ * @param y y位置
+ * @param h 高度
+ * @param w 宽度
+ * @return 指定位置的组件
+ */
+ public Component getBottomRightComp(int x, int y, int h, int w) {
+ return this.getComponentAt(x+w+default_Length, y+h-default_Length);
+ }
+
+ /**
+ * 返回指定point的下方且是右侧的组件
+ * @param x x位置
+ * @param y y位置
+ * @param h 高度
+ * @param w 宽度
+ * @return 指定位置的组件
+ */
+ public Component getRightBottomComp(int x, int y, int h, int w) {
+ return this.getComponentAt(x+w-default_Length, y+h+default_Length);
+ }
+
+ /**
+ * 是否延迟展示报表内容,也就是说是否要等点击了查询之后才执行报表
+ * @return 如果是true,则表示点击之后才开始计算,false则表示会根据参数默认值直接计算报表并展现
+ */
+ public boolean isDelayDisplayContent() {
+ return false;
+ }
+
+ /**
+ * 是否显示参数界面
+ * @return 显示参数界面则返回true,否则返回false
+ */
+ public boolean isDisplay() {
+ return false;
+ }
+
+ public Background getDataBackground(){
+ return toData().getBackground();
+ }
+
+ /**
+ * 获取参数界面的宽度
+ * @return 宽度
+ */
+ public int getDesignWidth() {
+ return 0;
+ }
+
+ /**
+ * 获取参数面板的对齐方式
+ * @return 左中右三种对齐方式
+ */
+ public int getPosition() {
+ return 0;
+ }
+
+ /**
+ * 切换到非添加状态
+ *
+ * @param designer 表单设计器
+ */
+ public void stopAddingState(FormDesigner designer){
+ return;
+ }
+
+ /**
+ * 寻找最近的为自适应布局的父容器
+ *
+ * @return 布局容器
+ *
+ *
+ * @date 2014-12-30-下午3:15:28
+ *
+ */
+ public XLayoutContainer findNearestFit(){
+ //一层一层网上找, 找到最近的fit那一层就return
+ XLayoutContainer parent = this.getBackupParent();
+ return parent == null ? null : parent.findNearestFit();
+ }
+
+ /**
+ * 获取容器所有内部组件横坐标值
+ *
+ * @return 横坐标数组
+ */
+ public int[] getHors(){
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+
+ /**
+ * 获取容器所有内部组件纵坐标值
+ *
+ * @return 纵坐标数组
+ */
+ public int[] getVeris(){
+ return ArrayUtils.EMPTY_INT_ARRAY;
+ }
+
+ public void setDelayDisplayContent(boolean delayPlaying){
+
+ }
+
+ public void setPosition(int align){
+
+ }
+
+ public void setDisplay(boolean showWindow){
+
+ }
+
+ public void setBackground(Background background){
+
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XListEditor.java b/designer_form/src/com/fr/design/designer/creator/XListEditor.java
new file mode 100644
index 000000000..01ed9d486
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XListEditor.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.DefaultListModel;
+import javax.swing.JComponent;
+import javax.swing.JList;
+
+import com.fr.design.mainframe.widget.editors.DictionaryEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.DictionaryRenderer;
+import com.fr.form.ui.ListEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XListEditor extends XFieldEditor {
+
+ public XListEditor(ListEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(
+ WidgetValueEditor.class),
+ new CRPropertyDescriptor("dictionary", this.data.getClass()).setI18NName(
+ Inter.getLocText("DS-Dictionary")).setEditorClass(DictionaryEditor.class)
+ .setRendererClass(DictionaryRenderer.class),
+ new CRPropertyDescriptor("needHead", this.data.getClass()).setI18NName(
+ Inter.getLocText("List-Need_Head")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced") });
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ JList jList = (JList)editor;
+ ListEditor l = (ListEditor)data;
+ jList.setSelectedIndex(0);
+ jList.setSelectionBackground(l.getSelectionBackground());
+ jList.setSelectionForeground(l.getSelectionForeground());
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ DefaultListModel model = new DefaultListModel();
+ model.addElement("Item 1");
+ model.addElement("item 2");
+ model.addElement("item 3");
+ model.addElement("item 4");
+ editor = new JList(model);
+ editor.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
+ }
+ return editor;
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(120, 80);
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * 这里控制 列表预定义控件在工具栏不显示
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return false;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "list_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XMultiFileUploader.java b/designer_form/src/com/fr/design/designer/creator/XMultiFileUploader.java
new file mode 100644
index 000000000..7640f99e7
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XMultiFileUploader.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+import com.fr.design.gui.ilable.UILabel;
+import javax.swing.JPanel;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.gui.ibutton.UIButton;
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.form.ui.MultiFileEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XMultiFileUploader extends XFieldEditor {
+
+ public XMultiFileUploader(MultiFileEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+ super.supportedDescriptor(),
+ new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("singleFile", this.data.getClass())
+ .setI18NName(Inter.getLocText("SINGLE_FILE_UPLOAD"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("accept", this.data.getClass())
+ .setI18NName(Inter.getLocText("File-Allow_Upload_Files"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("maxSize", this.data.getClass())
+ .setI18NName(Inter.getLocText("File-File_Size_Limit"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ });
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ JPanel choosePane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ choosePane.add(new UITextField(10), BorderLayout.CENTER);
+ UIButton btn = new UIButton("...");
+ btn.setPreferredSize(new Dimension(24, 24));
+ choosePane.add(btn, BorderLayout.EAST);
+ editor.add(choosePane, BorderLayout.NORTH);
+ JPanel opPane = FRGUIPaneFactory.createNColumnGridInnerContainer_S_Pane(1);
+ editor.add(opPane, BorderLayout.CENTER);
+
+ JPanel filePane1 = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ opPane.add(filePane1);
+ UILabel label1 = new UILabel(BaseUtils.readIcon("com/fr/web/images/form/resources/files_up_delete_16.png"));
+ filePane1.add(label1, BorderLayout.WEST);
+ filePane1.add(new UILabel("file1.png"), BorderLayout.CENTER);
+
+ JPanel filePane2 = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ opPane.add(filePane2);
+ UILabel label2 = new UILabel(BaseUtils.readIcon("com/fr/web/images/form/resources/files_up_delete_16.png"));
+ filePane2.add(label2, BorderLayout.WEST);
+ filePane2.add(new UILabel("file2.xml"), BorderLayout.CENTER);
+ }
+ return editor;
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return MIDDLE_PREFERRED_SIZE;
+ }
+
+ /**
+ * 该组件是否可以拖入参数面板
+ * 这里控制 文件预定义控件在工具栏不显示
+ * @return 是则返回true
+ */
+ public boolean canEnterIntoParaPane(){
+ return false;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "files_up.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XNameWidget.java b/designer_form/src/com/fr/design/designer/creator/XNameWidget.java
new file mode 100644
index 000000000..50252a14a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XNameWidget.java
@@ -0,0 +1,146 @@
+package com.fr.design.designer.creator;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.ScreenResolution;
+import com.fr.base.Style;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.widget.editors.NameWidgetComboboxEditor;
+import com.fr.form.ui.*;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+import javax.swing.*;
+import java.awt.*;
+import java.beans.IntrospectionException;
+
+public class XNameWidget extends XWidgetCreator {
+
+ public XNameWidget(NameWidget widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 返回对应的widget
+ * @return 返回NameWidget
+ */
+ public NameWidget toData() {
+ return (NameWidget) data;
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ if (editor == null) {
+ Graphics2D g2d = (Graphics2D) g.create();
+ BaseUtils.drawStringStyleInRotation(g2d, this.getWidth(), this.getHeight(), Inter.getLocText("FR-Engine_NameWidget-Invalid"), Style.getInstance()
+ .deriveHorizontalAlignment(SwingConstants.CENTER).deriveVerticalAlignment(SwingConstants.CENTER)
+ .deriveFRFont(FRFont.getInstance().applyForeground(Color.RED)), ScreenResolution
+ .getScreenResolution());
+ }
+ }
+
+ /**
+ * 返回控件支持的属性表
+ * @return 属性表
+ * @throws 内省异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetName", this.data.getClass()).setI18NName(Inter
+ .getLocText("Form-Widget_Name")),
+ new CRPropertyDescriptor("name", this.data.getClass()).setI18NName(Inter.getLocText("FR-Engine_NameWidget-Name")).setEditorClass(
+ NameWidgetComboboxEditor.class).setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ rebuild();
+ }
+ }) };
+ }
+
+ protected JComponent initEditor() {
+ if (editor == null) {
+ WidgetManagerProvider widgetManager = WidgetManager.getProviderInstance();
+ WidgetConfig wc = widgetManager.getWidgetConfig(toData().getName());
+ Widget widget;
+ if (wc != null && (widget= wc.toWidget()) != null) {
+ editor = XCreatorUtils.createXCreator(widget);
+ toData().setVisible(widget.isVisible());
+ this.setBorder(null);
+ } else {
+ this.setBorder(DEFALUTBORDER);
+ }
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "user_widget.png";
+ }
+
+ /**
+ * 属性改变后,重新构建控件
+ */
+ public void rebuild() {
+ editor = null;
+ removeAll();
+ initEditor();
+ if (editor != null) {
+ this.setLayout(FRGUIPaneFactory.createBorderLayout());
+ add(editor, BorderLayout.CENTER);
+ this.setVisible(toData().isVisible());
+ }
+ }
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName){
+ return shouldScaleCreator() ? new XWScaleLayout() : new XWTitleLayout();
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ if(!shouldScaleCreator()){
+ super.addToWrapper(parentPanel, width, minHeight);
+ return;
+ }
+
+ this.setSize(width, minHeight);
+ parentPanel.add(this);
+ }
+
+ /**
+ * 此控件在自适应布局要保持原样高度
+ *
+ * @return 是则返回true
+ */
+ @Override
+ public boolean shouldScaleCreator() {
+ if (editor == null) {
+ return false;
+ }
+ XCreator creator = (XCreator) editor;
+ return creator.shouldScaleCreator();
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XNumberEditor.java b/designer_form/src/com/fr/design/designer/creator/XNumberEditor.java
new file mode 100644
index 000000000..a57a90059
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XNumberEditor.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.ScreenResolution;
+import com.fr.base.Style;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.mainframe.widget.editors.InChangeBooleanEditor;
+import com.fr.design.mainframe.widget.editors.SpinnerMaxNumberEditor;
+import com.fr.design.mainframe.widget.editors.SpinnerMinNumberEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.form.ui.NumberEditor;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.Constants;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XNumberEditor extends XWrapperedFieldEditor {
+
+ public XNumberEditor(NumberEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 控件的属性列表
+ * @return 此控件所用的属性列表
+ * @throws IntrospectionException 异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ CRPropertyDescriptor[] sup = super.supportedDescriptor();
+ CRPropertyDescriptor allowDecimal = new CRPropertyDescriptor("allowDecimals", this.data.getClass())
+ .setEditorClass(InChangeBooleanEditor.class)
+ .setI18NName(Inter.getLocText("FR-Designer_Allow_Decimals"));
+ CRPropertyDescriptor decimalLength = new CRPropertyDescriptor("maxDecimalLength", this.data.getClass())
+ .setI18NName(Inter.getLocText(new String[]{"Double", "Numbers"}));
+ sup = (CRPropertyDescriptor[]) ArrayUtils.addAll(sup, ((NumberEditor)this.data).isAllowDecimals() ?
+ new CRPropertyDescriptor[] {allowDecimal, decimalLength} : new CRPropertyDescriptor[] {allowDecimal});
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(sup,
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("allowNegative", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_Allow_Negative"))
+ .setEditorClass(InChangeBooleanEditor.class),
+ new CRPropertyDescriptor("minValue", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_Min_Value"))
+ .setEditorClass(SpinnerMinNumberEditor.class),
+ new CRPropertyDescriptor("maxValue", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_Max_Value"))
+ .setEditorClass(SpinnerMaxNumberEditor.class),
+ new CRPropertyDescriptor("widgetValue", this.data.getClass())
+ .setI18NName(Inter.getLocText(new String[]{"Widget", "Value"}))
+ .setEditorClass(WidgetValueEditor.class),
+ new CRPropertyDescriptor("waterMark", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_WaterMark"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ });
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ NumberEditor editor = (NumberEditor) data;
+ if (editor.getWidgetValue() != null) {
+ Graphics2D g2d = (Graphics2D) g.create();
+ BaseUtils.drawStringStyleInRotation(g2d, this.getWidth(), this.getHeight(), editor.getWidgetValue()
+ .toString(), Style.getInstance(FRFont.getInstance()).deriveHorizontalAlignment(Constants.LEFT)
+ .deriveTextStyle(Style.TEXTSTYLE_SINGLELINE), ScreenResolution.getScreenResolution());
+ }
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ setBorder(FIELDBORDER);
+ return this;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "number_field_16.png";
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XPassword.java b/designer_form/src/com/fr/design/designer/creator/XPassword.java
new file mode 100644
index 000000000..b25d63778
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XPassword.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.ibutton.UIPasswordField;
+import com.fr.design.mainframe.widget.editors.RegexEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.RegexCellRencerer;
+import com.fr.form.ui.Password;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XPassword extends XWrapperedFieldEditor {
+
+ public XPassword(Password widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = new UIPasswordField();
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "password_field_16.png";
+ }
+
+ /**
+ * 控件的属性列表
+ * @return 此控件所用的属性列表
+ * @throws IntrospectionException 异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(
+ WidgetValueEditor.class),
+ new CRPropertyDescriptor("regex", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_Input_Rule"))
+ .setEditorClass(RegexEditor.RegexEditor4TextArea.class)
+ .putKeyValue("renderer", RegexCellRencerer.class)
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("waterMark", this.data.getClass())
+ .setI18NName(Inter.getLocText("FR-Designer_WaterMark"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XRadio.java b/designer_form/src/com/fr/design/designer/creator/XRadio.java
new file mode 100644
index 000000000..56dbd3c0b
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XRadio.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+import javax.swing.JRadioButton;
+
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.form.ui.Radio;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XRadio extends XWidgetCreator {
+
+ public XRadio(Radio widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public Radio toData() {
+ return (Radio)data;
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("text", this.data.getClass()).setI18NName(Inter.getLocText("Text")),
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(WidgetValueEditor.class)});
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = new JRadioButton();
+ }
+ return editor;
+ }
+
+ @Override
+ protected void initXCreatorProperties() {
+ super.initXCreatorProperties();
+ JRadioButton jRadio = (JRadioButton) editor;
+ Radio radio = (Radio) data;
+ jRadio.setText(radio.getText());
+ if(radio.getWidgetValue() != null && radio.getWidgetValue().getValue() instanceof Boolean) {
+ jRadio.setSelected((Boolean) radio.getWidgetValue().getValue());
+ }
+ }
+
+ @Override
+ protected String getIconName() {
+ return "radio_button_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XRadioGroup.java b/designer_form/src/com/fr/design/designer/creator/XRadioGroup.java
new file mode 100644
index 000000000..d54f12dab
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XRadioGroup.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JComponent;
+import javax.swing.JRadioButton;
+
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.mainframe.widget.editors.DictionaryEditor;
+import com.fr.design.mainframe.widget.editors.InChangeBooleanEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.DictionaryRenderer;
+import com.fr.form.ui.RadioGroup;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XRadioGroup extends XFieldEditor {
+
+ public XRadioGroup(RadioGroup widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public RadioGroup toData() {
+ return (RadioGroup) data;
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),getCRPropertyDescriptor());
+ }
+
+ private CRPropertyDescriptor[] getCRPropertyDescriptor() throws IntrospectionException {
+ CRPropertyDescriptor[] crp = new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(WidgetValueEditor.class),
+ new CRPropertyDescriptor("dictionary", this.data.getClass()).setI18NName(
+ Inter.getLocText("DS-Dictionary")).setEditorClass(DictionaryEditor.class).setRendererClass(
+ DictionaryRenderer.class),
+ new CRPropertyDescriptor("adaptive", this.data.getClass()).setI18NName(Inter.getLocText("Adaptive"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced").setEditorClass(InChangeBooleanEditor.class)};
+ if (!toData().isAdaptive()) {
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("columnsInRow", this.data
+ .getClass()).setI18NName(Inter.getLocText("Button-Group-Display-Columns")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ }
+ return crp;
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ editor.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
+ ButtonGroup bg = new ButtonGroup();
+ JRadioButton radioLeft = new JRadioButton();
+ radioLeft.setSelected(true);
+ JRadioButton radioRight = new JRadioButton();
+ bg.add(radioLeft);
+ bg.add(radioRight);
+ editor.add(radioLeft, BorderLayout.WEST);
+ editor.add(radioRight, BorderLayout.EAST);
+ }
+ return editor;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "button_group_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XTableEditor.java b/designer_form/src/com/fr/design/designer/creator/XTableEditor.java
new file mode 100644
index 000000000..bd5feab0d
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XTableEditor.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableModel;
+
+import com.fr.form.ui.Table;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XTableEditor extends XWidgetCreator {
+
+ public XTableEditor(Table widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[0];
+ // TODO ALEX_SEP
+// return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+// super.supportedDescriptor(),
+// new CRPropertyDescriptor[]{
+// new CRPropertyDescriptor("indexWidgets", this.data.getClass())
+// .setEditorClass(GridEditor.class)
+// .setRendererClass(GridWidgetRenderer.class),
+// new CRPropertyDescriptor("dataURL", this.data.getClass()),
+// new CRPropertyDescriptor("databinding", this.data.getClass())
+// .setI18NName(Inter.getLocText("DataBinding"))
+// .setEditorClass(DataBindingEditor.class)
+// .setRendererClass(DataBindingCellRenderer.class)
+// .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+// });
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ DefaultTableModel tm = new DefaultTableModel(4, 2);
+ editor = new JTable(tm);
+ }
+ return editor;
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return MIDDLE_PREFERRED_SIZE;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "table_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XTableTree.java b/designer_form/src/com/fr/design/designer/creator/XTableTree.java
new file mode 100644
index 000000000..39280b097
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XTableTree.java
@@ -0,0 +1,57 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JComponent;
+import javax.swing.JList;
+
+import com.fr.design.mainframe.widget.editors.DictionaryEditor;
+import com.fr.design.mainframe.widget.renderer.DictionaryRenderer;
+import com.fr.form.ui.TableTree;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+public class XTableTree extends XWidgetCreator {
+
+ public XTableTree(TableTree widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+ super.supportedDescriptor(),
+ new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("dictionary", this.data.getClass())
+ .setI18NName(Inter.getLocText("DS-Dictionary"))
+ .setEditorClass(DictionaryEditor.class)
+ .setRendererClass(DictionaryRenderer.class),
+ new CRPropertyDescriptor("dataUrl", this.data.getClass()),
+ });
+ }
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ DefaultListModel model = new DefaultListModel();
+ model.addElement("Item 1");
+ model.addElement("item 2");
+ model.addElement("item 3");
+ model.addElement("item 4");
+ editor = new JList(model);
+ }
+ return editor;
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(120, 80);
+ }
+
+ @Override
+ protected String getIconName() {
+ return "list_16.png";
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XTextArea.java b/designer_form/src/com/fr/design/designer/creator/XTextArea.java
new file mode 100644
index 000000000..fbaf1a44e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XTextArea.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+import javax.swing.SwingConstants;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.ScreenResolution;
+import com.fr.base.Style;
+import com.fr.design.mainframe.widget.editors.RegexEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.RegexCellRencerer;
+import com.fr.form.ui.TextArea;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.Constants;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XTextArea extends XFieldEditor {
+
+ public XTextArea(TextArea widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"Widget", "Value"})).setEditorClass(
+ WidgetValueEditor.class),
+ new CRPropertyDescriptor("regex", this.data.getClass()).setI18NName(
+ Inter.getLocText("Input_Rule")).setEditorClass(RegexEditor.RegexEditor4TextArea.class)
+ .putKeyValue("renderer", RegexCellRencerer.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("waterMark", this.data.getClass()).setI18NName(
+ Inter.getLocText("WaterMark")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"), });
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ TextArea area = (TextArea) data;
+ if (area.getWidgetValue() != null) {
+ Graphics2D g2d = (Graphics2D) g.create();
+ BaseUtils.drawStringStyleInRotation(g2d, this.getWidth(), this.getHeight(), area.getWidgetValue()
+ .toString(), Style.getInstance(FRFont.getInstance()).deriveHorizontalAlignment(Constants.LEFT)
+ .deriveVerticalAlignment(SwingConstants.TOP)
+ .deriveTextStyle(Style.TEXTSTYLE_WRAPTEXT), ScreenResolution.getScreenResolution());
+ }
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ setBorder(FIELDBORDER);
+ return this;
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return BIG_PREFERRED_SIZE;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "text_area_16.png";
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XTextEditor.java b/designer_form/src/com/fr/design/designer/creator/XTextEditor.java
new file mode 100644
index 000000000..0165b3e18
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XTextEditor.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.ScreenResolution;
+import com.fr.base.Style;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.mainframe.widget.editors.RegexEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.RegexCellRencerer;
+import com.fr.form.ui.TextEditor;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.Constants;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XTextEditor extends XWrapperedFieldEditor {
+
+ public XTextEditor(TextEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 控件的属性列表
+ * @return 此控件所用的属性列表
+ * @throws IntrospectionException 异常
+ */
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(),
+ new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"FR-Designer_Widget", "Value"})).setEditorClass(
+ WidgetValueEditor.class),
+ new CRPropertyDescriptor("regex", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Input_Rule")).setEditorClass(RegexEditor.class).putKeyValue(
+ "renderer", RegexCellRencerer.class).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"),
+ new CRPropertyDescriptor("waterMark", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_WaterMark")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"), });
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ TextEditor area = (TextEditor) data;
+ if (area.getWidgetValue() != null) {
+ Graphics2D g2d = (Graphics2D) g.create();
+ BaseUtils.drawStringStyleInRotation(g2d, this.getWidth(), this.getHeight(), area.getWidgetValue()
+ .toString(), Style.getInstance(FRFont.getInstance()).deriveHorizontalAlignment(Constants.LEFT)
+ .deriveTextStyle(Style.TEXTSTYLE_SINGLELINE), ScreenResolution.getScreenResolution());
+ }
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ setBorder(FIELDBORDER);
+ return this;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "text_field_16.png";
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XTreeComboBoxEditor.java b/designer_form/src/com/fr/design/designer/creator/XTreeComboBoxEditor.java
new file mode 100644
index 000000000..52ec9d7a6
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XTreeComboBoxEditor.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.JComponent;
+
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.form.ui.TreeComboBoxEditor;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XTreeComboBoxEditor extends XTreeEditor {
+ LimpidButton btn;
+
+ public XTreeComboBoxEditor(TreeComboBoxEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ editor = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ UITextField textField = new UITextField(5);
+ textField.setOpaque(false);
+ editor.add(textField, BorderLayout.CENTER);
+ btn = new LimpidButton("", this.getIconPath(), toData().isVisible() ? FULL_OPACITY : HALF_OPACITY);
+ btn.setPreferredSize(new Dimension(21, 21));
+ btn.setOpaque(true);
+ editor.add(btn, BorderLayout.EAST);
+ editor.setBackground(Color.WHITE);
+ }
+ return editor;
+ }
+
+ protected CRPropertyDescriptor[] addWaterMark(CRPropertyDescriptor[] crp) throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("waterMark", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_WaterMark")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ }
+
+ protected CRPropertyDescriptor[] addAllowEdit(CRPropertyDescriptor[] crp) throws IntrospectionException{
+ return (CRPropertyDescriptor[])ArrayUtils.add(crp, new CRPropertyDescriptor("directEdit", this.data.getClass())
+ .setI18NName(Inter.getLocText("Form-Allow_Edit")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ }
+
+ protected CRPropertyDescriptor[] addCustomData(CRPropertyDescriptor[] crp) throws IntrospectionException{
+ return (CRPropertyDescriptor[])ArrayUtils.add(crp, new CRPropertyDescriptor("customData", this.data.getClass())
+ .setI18NName(Inter.getLocText("Form-Allow_CustomData")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ }
+
+ @Override
+ protected String getIconName() {
+ return "comboboxtree.png";
+ }
+
+ protected void makeVisible(boolean visible) {
+ btn.makeVisible(visible);
+ }
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName){
+ return new XWScaleLayout();
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ this.setSize(width, minHeight);
+ parentPanel.add(this);
+ }
+
+ /**
+ * 此控件在自适应布局要保持原样高度
+ *
+ * @return 是则返回true
+ */
+ @Override
+ public boolean shouldScaleCreator() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XTreeEditor.java b/designer_form/src/com/fr/design/designer/creator/XTreeEditor.java
new file mode 100644
index 000000000..4b36820bc
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XTreeEditor.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.fr.design.mainframe.widget.editors.InChangeBooleanEditor;
+import com.fr.design.mainframe.widget.editors.TreeModelEditor;
+import com.fr.design.mainframe.widget.editors.WidgetValueEditor;
+import com.fr.design.mainframe.widget.renderer.TreeModelRenderer;
+import com.fr.form.ui.FieldEditor;
+import com.fr.form.ui.TreeEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XTreeEditor extends XWidgetCreator {
+
+ public XTreeEditor(TreeEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ /**
+ * 树控件的属性面板
+ * @return 属性数组
+ * @throws Introspection过程错误
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ CRPropertyDescriptor[] crp = !((FieldEditor) toData()).isAllowBlank() ?
+ new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"FR-Designer_Widget", "Value"})).setEditorClass(WidgetValueEditor.class),
+ new CRPropertyDescriptor("model", this.data.getClass(), "getNodeOrDict", "setNodeOrDict").setI18NName(
+ Inter.getLocText("FR-Designer_DS-Dictionary")).setEditorClass(TreeModelEditor.class).setRendererClass(
+ TreeModelRenderer.class),
+ new CRPropertyDescriptor("allowBlank", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Allow_Blank")).setEditorClass(InChangeBooleanEditor.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("errorMessage", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Verify-Message"))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ }
+ : new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("widgetValue", this.data.getClass()).setI18NName(
+ Inter.getLocText(new String[]{"FR-Designer_Widget", "Value"})).setEditorClass(WidgetValueEditor.class),
+ new CRPropertyDescriptor("model", this.data.getClass(), "getNodeOrDict", "setNodeOrDict").setI18NName(
+ Inter.getLocText("FR-Designer_DS-Dictionary")).setEditorClass(TreeModelEditor.class).setRendererClass(
+ TreeModelRenderer.class),
+ new CRPropertyDescriptor("allowBlank", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Allow_Blank")).setEditorClass(InChangeBooleanEditor.class).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),};
+
+ crp = this.addWaterMark(crp);
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp,
+ new CRPropertyDescriptor("fontSize", this.data.getClass(), "getFontSize", "setFontSize")
+ .setI18NName(Inter.getLocText(new String[]{"FR-Designer_Font", "FRFont-Size"}))
+ .putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("multipleSelection", this.data.getClass()).setI18NName(
+ Inter.getLocText("Tree-Mutiple_Selection_Or_Not")).putKeyValue(
+ XCreatorConstants.PROPERTY_CATEGORY, "Advanced").setEditorClass(InChangeBooleanEditor.class));
+
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("ajax", this.data.getClass()).setI18NName(
+ Inter.getLocText("Widget-Load_By_Async")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY,
+ "Advanced"));
+
+ crp = this.addAllowEdit(crp);
+ crp = this.addCustomData(crp);
+
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("selectLeafOnly", this.data
+ .getClass()).setI18NName(Inter.getLocText("Tree-Select_Leaf_Only")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+ crp = (CRPropertyDescriptor[]) ArrayUtils.add(crp, new CRPropertyDescriptor("returnFullPath", this.data
+ .getClass()).setI18NName(Inter.getLocText("Tree-Return_Full_Path")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"));
+
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(super.supportedDescriptor(), crp);
+ }
+
+ protected CRPropertyDescriptor[] addWaterMark(CRPropertyDescriptor[] crp) throws IntrospectionException{
+ return crp;
+ }
+
+ protected CRPropertyDescriptor[] addAllowEdit(CRPropertyDescriptor[] crp) throws IntrospectionException{
+ return crp;
+ }
+
+ protected CRPropertyDescriptor[] addCustomData(CRPropertyDescriptor[] crp) throws IntrospectionException{
+ return crp;
+ }
+
+ @Override
+ protected JComponent initEditor() {
+ if (editor == null) {
+ DefaultMutableTreeNode root = new DefaultMutableTreeNode("Tree");
+ root.add(new DefaultMutableTreeNode("Leaf1"));
+ root.add(new DefaultMutableTreeNode("Leaf2"));
+ editor = new JTree(root);
+ editor.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
+ }
+ return editor;
+ }
+
+ @Override
+ /**
+ * 控件的预定义大小
+ * @return 控件的预定义大小
+ */
+ public Dimension initEditorSize() {
+ return SMALL_PREFERRED_SIZE;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "tree_16.png";
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java b/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java
new file mode 100644
index 000000000..6cf0fc216
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWAbsoluteLayout.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.event.ContainerEvent;
+import java.util.HashMap;
+
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.form.layout.FRAbsoluteLayout;
+import com.fr.form.ui.Connector;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WAbsoluteLayout;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XWAbsoluteLayout extends XLayoutContainer {
+
+ private HashMap xConnectorMap;
+
+ public XWAbsoluteLayout() {
+ this(new WAbsoluteLayout(),new Dimension());
+ }
+
+ public XWAbsoluteLayout(WAbsoluteLayout widget) {
+ this(widget,new Dimension());
+ }
+
+ public XWAbsoluteLayout(WAbsoluteLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ this.xConnectorMap = new HashMap();
+ Connector connector;
+ for (int i = 0; i < widget.connectorCount(); i++) {
+ connector = widget.getConnectorIndex(i);
+ xConnectorMap.put(connector, new XConnector(connector, this));
+ }
+ }
+
+ /**
+ * 增加对齐线
+ * @param connector 对齐线
+ */
+ public void addConnector(Connector connector) {
+ xConnectorMap.put(connector, new XConnector(connector, this));
+ ((WAbsoluteLayout) data).addConnector(connector);
+ }
+
+ public XConnector getXConnector(Connector connector) {
+ return xConnectorMap.get(connector);
+ }
+
+ /**
+ * 去除对齐线
+ * @param connector 对齐线
+ */
+ public void removeConnector(Connector connector) {
+ ((WAbsoluteLayout) data).removeConnector(connector);
+ xConnectorMap.remove(connector);
+ }
+
+ /**
+ * 返回对应的widget容器
+ * @return 返回WAbsoluteLayout
+ */
+ @Override
+ public WAbsoluteLayout toData() {
+ return (WAbsoluteLayout) data;
+ }
+
+ @Override
+ protected String getIconName() {
+ return "layout_absolute.png";
+ }
+
+ /**
+ * 返回默认的容器name
+ * @return 返回绝对布局容器名
+ */
+ @Override
+ public String createDefaultName() {
+ return "absolute";
+ }
+
+ @Override
+ protected void initLayoutManager() {
+ this.setLayout(new FRAbsoluteLayout());
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ WAbsoluteLayout layout = (WAbsoluteLayout) data;
+ Connector[] connector = layout.getConnector();
+ for (int i = 0, size = connector.length; i < size; i++) {
+ connector[i].draw(g);
+ }
+ }
+
+ /**
+ * 转换保存组件信息的wlayout为对应的container
+ */
+ @Override
+ public void convert() {
+ isRefreshing = true;
+ WAbsoluteLayout abs = toData();
+ this.removeAll();
+ for (int i = 0, count = abs.getWidgetCount(); i < count; i++) {
+ BoundsWidget bw = (BoundsWidget)abs.getWidget(i);
+ if (bw != null) {
+ Rectangle bounds = bw.getBounds();
+ XWidgetCreator comp = (XWidgetCreator)XCreatorUtils.createXCreator(bw.getWidget());
+ if (!comp.acceptType(XWParameterLayout.class)) {
+ comp.setDirections(Direction.ALL);
+ }
+ add(comp);
+ comp.setBounds(bounds);
+ }
+ }
+ isRefreshing = false;
+ }
+
+ /**
+ * 当前组件zorder位置替换新的控件
+ * @param widget 控件
+ * @param oldcreator 旧组件
+ * @return 组件
+ */
+ @Override
+ public XCreator replace(Widget widget, XCreator oldcreator) {
+ int i = this.getComponentZOrder(oldcreator);
+ if (i != -1) {
+ this.toData().replace(new BoundsWidget(widget, oldcreator.getBounds()),
+ new BoundsWidget(oldcreator.toData(), oldcreator.getBounds()));
+ this.convert();
+ return (XCreator) this.getComponent(i);
+ }
+ return null;
+ }
+
+ /**
+ * 组件增加
+ * @param e 容器事件
+ */
+ @Override
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ WAbsoluteLayout wabs = this.toData();
+ if (!creator.acceptType(XWFitLayout.class)) {
+ creator.setDirections(Direction.ALL);
+ }
+ wabs.addWidget(new BoundsWidget(creator.toData(), creator.getBounds()));
+ }
+
+ /**
+ * 在设计界面中有组件移除的时候,需要通知WLayout容器重新paint
+ * @param e 容器事件
+ */
+ @Override
+ public void componentRemoved(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ WAbsoluteLayout wlayout = this.toData();
+ XWidgetCreator xwc = ((XWidgetCreator) e.getChild());
+ Widget wgt = xwc.toData();
+ BoundsWidget bw = new BoundsWidget(wgt, xwc.getBounds());
+ wlayout.removeWidget(bw);
+ }
+
+ @Override
+ public Dimension getMinimumSize() {
+ return toData().getMinDesignSize();
+ }
+
+ @Override
+ public LayoutAdapter getLayoutAdapter() {
+ return new FRAbsoluteLayoutAdapter(this);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWBorderLayout.java b/designer_form/src/com/fr/design/designer/creator/XWBorderLayout.java
new file mode 100644
index 000000000..30aed94f2
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWBorderLayout.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ContainerEvent;
+import java.beans.IntrospectionException;
+
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.adapters.layout.FRBorderLayoutAdapter;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.form.layout.FRBorderLayout;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WBorderLayout;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.Inter;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XWBorderLayout extends XLayoutContainer {
+ private int Num = 5;
+ public XWBorderLayout(){
+ super(new WBorderLayout(),new Dimension(WBorderLayout.DEFAULT_WIDTH, WBorderLayout.DEFAULT_HEIGHT));
+ }
+
+ public XWBorderLayout(WBorderLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ protected String getIconName() {
+ return "layout_border.png";
+ }
+
+ /**
+ * 默认名称
+ * @return 名称
+ */
+ public String createDefaultName() {
+ return "border";
+ }
+
+ /**
+ * 转化成相应 WBorderLayout
+ * @return 相应 WBorderLayout
+ */
+ public WBorderLayout toData() {
+ return (WBorderLayout) data;
+ }
+
+ @Override
+ protected void initLayoutManager() {
+ this.setLayout(new FRBorderLayout(toData().getHgap(), toData().getVgap()));
+ }
+ /**
+ * 初始大小
+ * @return 初始大小
+ */
+ public Dimension initEditorSize() {
+ return new Dimension(WBorderLayout.DEFAULT_WIDTH, WBorderLayout.DEFAULT_HEIGHT);
+ }
+
+ /**
+ * 得到属性名
+ * @return 属性名
+ * @throws java.beans.IntrospectionException 抛错
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetName", this.data.getClass()).setI18NName(Inter
+ .getLocText("Form-Widget_Name"))
+ };
+ }
+
+ /**
+ * 将WLayout转换为XLayoutContainer
+ */
+ public void convert() {
+ isRefreshing = true;
+ WBorderLayout wb = this.toData();
+ this.removeAll();
+ String[] arrs = {WBorderLayout.NORTH, WBorderLayout.SOUTH, WBorderLayout.EAST, WBorderLayout.WEST, WBorderLayout.CENTER};
+ for (int i = 0; i < arrs.length; i++) {
+ Widget wgt = wb.getLayoutWidget(arrs[i]);
+ if (wgt != null) {
+ XWidgetCreator comp = (XWidgetCreator) XCreatorUtils.createXCreator(wgt, calculatePreferredSize(wgt));
+ this.add(comp, arrs[i]);
+ comp.setBackupParent(this);
+ }
+ }
+ isRefreshing = false;
+ }
+
+
+ /**
+ * 设计界面中有组件添加时,要通知WLayout容器重新paint
+ * @param e 事件
+ */
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ BorderLayout b = (BorderLayout) getLayout();
+ Object constraints = b.getConstraints(creator);
+ WBorderLayout wb = this.toData();
+ Widget w = creator.toData();
+ add(wb, w, constraints);
+ doResizePreferredSize(creator, calculatePreferredSize(w));
+ }
+
+ @Override
+ protected Dimension calculatePreferredSize(Widget wgt) {
+ WBorderLayout wlayout = this.toData();
+ Object constraints = wlayout.getConstraints(wgt);
+ Dimension d = new Dimension();
+ if (ComparatorUtils.equals(WBorderLayout.NORTH,constraints)) {
+ d.height = wlayout.getNorthSize();
+ } else if (ComparatorUtils.equals(WBorderLayout.SOUTH,constraints)) {
+ d.height = wlayout.getSouthSize();
+ } else if (ComparatorUtils.equals(WBorderLayout.EAST,constraints)) {
+ d.width = wlayout.getEastSize();
+ } else if (ComparatorUtils.equals(WBorderLayout.WEST,constraints)) {
+ d.width = wlayout.getWestSize();
+ }
+ return d;
+ }
+
+ private void doResizePreferredSize(XWidgetCreator comp, Dimension d) {
+ comp.setPreferredSize(d);
+ }
+
+ /**
+ * 加入控件
+ * @param layout 布局
+ * @param wgt 控件
+ * @param constraints 方位
+ */
+ public static void add(WBorderLayout layout, Widget wgt, Object constraints) {
+ if (ComparatorUtils.equals(WBorderLayout.NORTH,constraints)) {
+ layout.addNorth(wgt);
+ } else if (ComparatorUtils.equals(WBorderLayout.SOUTH,constraints)) {
+ layout.addSouth(wgt);
+ } else if (ComparatorUtils.equals(WBorderLayout.EAST,constraints)) {
+ layout.addEast(wgt);
+ } else if (ComparatorUtils.equals(WBorderLayout.WEST,constraints)) {
+ layout.addWest(wgt);
+ } else if (ComparatorUtils.equals(WBorderLayout.CENTER,constraints)) {
+ layout.addCenter(wgt);
+ }
+ }
+
+ /**
+ * 重新计算大小
+ */
+ public void recalculateChildrenSize() {
+ Dimension d = getSize();
+ WBorderLayout layout = toData();
+ layout.setNorthSize(d.height / Num);
+ layout.setSouthSize(d.height / Num);
+ layout.setWestSize(d.width / Num);
+ layout.setEastSize(d.width / Num);
+ }
+
+
+ /**
+ * 在添加的时候需要把可拉伸的方向确定,所以重写了add方法
+ * @param comp 组件
+ * @param constraints 方位
+ */
+ public void add(Component comp, Object constraints) {
+ super.add(comp, constraints);
+ if (comp == null) {
+ return;
+ }
+ XCreator creator = (XCreator) comp;
+ // 添加到北边时可拉伸底部
+ if (ComparatorUtils.equals(BorderLayout.NORTH, constraints)) {
+ creator.setDirections(new int[]{Direction.BOTTOM});
+ // 添加到南部时可拉伸顶部
+ } else if (ComparatorUtils.equals(BorderLayout.SOUTH, constraints)) {
+ creator.setDirections(new int[]{Direction.TOP});
+ // 添加到东部的时候可向左边拉伸
+ } else if (ComparatorUtils.equals(BorderLayout.EAST, constraints)) {
+ creator.setDirections(new int[]{Direction.LEFT});
+ // 添加到西部的时候可向右边拉伸
+ } else if (ComparatorUtils.equals(BorderLayout.WEST, constraints)) {
+ creator.setDirections(new int[]{Direction.RIGHT});
+ }
+ }
+
+ @Override
+ public LayoutAdapter getLayoutAdapter() {
+ return new FRBorderLayoutAdapter(this);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java b/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java
new file mode 100644
index 000000000..bd2b34290
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWFitLayout.java
@@ -0,0 +1,1159 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.ContainerEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.adapters.layout.FRFitLayoutAdapter;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.designer.creator.cardlayout.XWTabFitLayout;
+import com.fr.design.form.layout.FRFitLayout;
+import com.fr.design.mainframe.FormArea;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.form.ui.PaddingMargin;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+import com.fr.form.ui.container.WFitLayout;
+import com.fr.form.ui.container.WLayout;
+import com.fr.general.FRScreen;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author jim
+ * @date 2014-6-23
+ */
+public class XWFitLayout extends XLayoutContainer {
+
+ private static final long serialVersionUID = 8112908607102660176L;
+
+ //由于屏幕分辨率不同,界面上的容器大小可能不是默认的100%,此时拖入组件时,保存的大小按照100%时的计算
+ protected double containerPercent = 1.0;
+ // 布局缩小的时候,考虑最小宽高,若挨着右侧或底侧边框的控件缩小后达到最小宽或高,此时容器大小微调下
+ private int needAddWidth = 0;
+ private int needAddHeight = 0;
+ private int minWidth = WLayout.MIN_WIDTH;
+ private int minHeight = WLayout.MIN_HEIGHT;
+ private int backupGap = 0;
+ protected boolean hasCalGap = false;
+
+
+ public XWFitLayout(){
+ this(new WFitLayout(), new Dimension());
+ }
+
+ public XWFitLayout(WFitLayout widget, Dimension initSize) {
+ super(widget, initSize);
+
+ initPercent();
+ }
+
+ //根据屏幕大小来确定显示的百分比, 1440*900默认100%, 1366*768缩放90%
+ private void initPercent(){
+ Toolkit toolkit = Toolkit.getDefaultToolkit();
+ Dimension scrnsize = toolkit.getScreenSize();
+ double screenValue = FRScreen.getByDimension(scrnsize).getValue();
+ if(screenValue != FormArea.DEFAULT_SLIDER){
+ this.setContainerPercent(screenValue / FormArea.DEFAULT_SLIDER);
+ }
+ }
+
+ @Override
+ public LayoutAdapter getLayoutAdapter() {
+ return new FRFitLayoutAdapter(this);
+ }
+
+ @Override
+ protected void initLayoutManager() {
+ this.setLayout(new FRFitLayout());
+ }
+
+ @Override
+ protected String getIconName() {
+ return "layout_absolute.png";
+ }
+
+ /**
+ * 返回最右侧控件的微调宽度
+ * @return 微调宽度
+ */
+ public int getNeedAddWidth() {
+ return needAddWidth;
+ }
+
+ public void setNeedAddWidth(int needAddWidth) {
+ this.needAddWidth = needAddWidth;
+ }
+
+ /**
+ * 返回最右侧控件的微调高度
+ * @return 微调宽度
+ */
+ public int getNeedAddHeight() {
+ return needAddHeight;
+ }
+
+ public void setNeedAddHeight(int needAddHeight) {
+ this.needAddHeight = needAddHeight;
+ }
+
+ /**
+ * 更新组件的backupBound
+ * 拖动滑块改变容器大小,改变的是界面显示大小,更新bound,再次拖入或拉伸边框用到
+ */
+ private void updateCreatorsBackupBound() {
+ for (int i=0,size=this.getComponentCount(); i margin.getLeft()) {
+ for (int i=1, len=hors.length; i margin.getTop() ) {
+ for (int j=1, num=veris.length; j posX = new ArrayList();
+ // 保存实际大小时,组件大小已经去除内边距,此处也判断下
+ PaddingMargin margin = isActualSize ? new PaddingMargin(0,0,0,0) : toData().getMargin();
+ posX.add(margin.getLeft());
+ int width = this.getWidth() - margin.getLeft() - margin.getRight();
+ int containW = (int) (width / perc);
+ posX.add(containW);
+ for (int i=0, len=this.getComponentCount(); i < len; i++) {
+ int x = this.getComponent(i).getX();
+ int finalX = (int) (x / perc);
+ if (!posX.contains(finalX)) {
+ posX.add(finalX);
+ }
+ }
+ Collections.sort(posX);
+ return ArrayUtils.toPrimitive(posX.toArray(new Integer[]{posX.size()}));
+ }
+
+ /**
+ * 获取内部组件纵坐标值
+ * @param isActualSize 实际大小
+ * @return int[] 纵坐标数组
+ *
+ */
+ public int[] getVeris(boolean isActualSize) {
+ double perc = isActualSize ? containerPercent : 1.0;
+ List posY = new ArrayList();
+ // 保存实际大小时,组件大小已经去除内边距,此处也判断下
+ PaddingMargin margin = isActualSize ? new PaddingMargin(0,0,0,0) : toData().getMargin();
+ posY.add(margin.getTop());
+ int height = this.getHeight() - margin.getTop() - margin.getBottom();
+ int containH = (int) (height / perc);
+ posY.add(containH);
+ for (int i=0, len=this.getComponentCount(); i < len; i++) {
+ int y = this.getComponent(i).getY();
+ int finalY = (int) (y / perc);
+ if (!posY.contains(finalY)) {
+ posY.add(finalY);
+ }
+ }
+ Collections.sort(posY);
+ return ArrayUtils.toPrimitive(posY.toArray(new Integer[]{posY.size()}));
+ }
+
+ /**
+ * 是否能缩小
+ * @param percent 百分比
+ * @return 是则返回true
+ */
+ public boolean canReduce(double percent) {
+ boolean canReduceSize = true;
+ if (percent < 0 && hasCalGap) {
+ // 缩小时考虑间隔的存在是否能缩小
+ canReduceSize = canReduceSize(percent);
+ }
+ return canReduceSize;
+ }
+
+ /**
+ * 按照百分比缩放内部组件宽度
+ *
+ * @param percent 宽度变化的百分比
+ */
+ public void adjustCreatorsWidth(double percent) {
+ if (this.getComponentCount()==0) {
+ // 初始化没有拖入控件时,实际宽度依然调整
+ this.toData().setContainerWidth(this.getWidth());
+ return;
+ }
+ updateWidgetBackupBounds();
+ int gap = toData().getCompInterval();
+ if (gap >0 && hasCalGap) {
+ moveCompInterval(getAcualInterval());
+ }
+ layoutWidthResize(percent);
+ if (percent < 0 && needAddWidth > 0) {
+ this.setSize(this.getWidth()+needAddWidth, this.getHeight());
+ modifyEdgemostCreator(true);
+ }
+ addCompInterval(getAcualInterval());
+ this.toData().setContainerWidth(this.getWidth());
+ updateWidgetBackupBounds();
+ LayoutUtils.layoutContainer(this);
+ }
+
+ // 手动修改宽高时,全部用的实际大小计算,所以最小值不用百分比计算后的
+ protected void layoutWidthResize(double percent) {
+ int[] hroValues= toData().getHorComps();
+ int num=hroValues.length;
+ int x=0;
+ int dw = 0;
+ int nextX = 0;
+ for (int i=0; i comps = getCompsAtX(x);
+ if (comps.isEmpty()) {
+ return;
+ }
+ for (int i=0, size=comps.size(); i0 && hasCalGap) {
+ moveCompInterval(getAcualInterval());
+ }
+ layoutHeightResize(percent);
+ if (percent < 0 && needAddHeight > 0) {
+ this.setSize(this.getWidth(), this.getHeight()+needAddHeight);
+ modifyEdgemostCreator(false);
+ }
+ addCompInterval(getAcualInterval());
+ this.toData().setContainerHeight(this.getHeight());
+ updateWidgetBackupBounds();
+ LayoutUtils.layoutContainer(this);
+ }
+
+ protected void layoutHeightResize(double percent) {
+ int[] vertiValues= toData().getVertiComps();
+ int num=vertiValues.length;
+ int y=0;
+ int dh = 0;
+ int nextY = 0;
+ for (int i=0; i comps = getCompsAtY(y);
+ if (comps.isEmpty()) {
+ return;
+ }
+ for (int i=0, size=comps.size(); i getCompsAtX(int x) {
+ List comps = new ArrayList();
+ int size = toData().getWidgetCount();
+ for (int i=0; i getCompsAtY(int y) {
+ List comps = new ArrayList();
+ for (int i=0,size=this.getComponentCount(); i comps) {
+ //容器高度拉伸时,计算内部组件的最小高度
+ if (comps.isEmpty()) {
+ return 0;
+ }
+ int minH =this.getWidth();
+ for (int i=0, size=comps.size(); icomps.get(i).getHeight() ? comps.get(i).getHeight() : minH;
+ }
+ return minH;
+ }
+
+ /**
+ * 初始化组件大小
+ * @return 默认大小
+ */
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(0, 0);
+ }
+
+ /**
+ * f返回默认组件name
+ * @return 容器名
+ */
+ public String createDefaultName() {
+ return "fit";
+ }
+
+ /**
+ * 返回容器对应的wlayout
+ * @return 同上
+ */
+ @Override
+ public WFitLayout toData() {
+ return (WFitLayout) data;
+ }
+
+ /**
+ * 当前组件zorder位置替换新的控件
+ * @param widget 控件
+ * @param oldcreator 旧组件
+ * @return 组件
+ */
+ @Override
+ public XCreator replace(Widget widget, XCreator oldcreator) {
+ int i = this.getComponentZOrder(oldcreator);
+ if (i != -1) {
+ this.toData().replace(new BoundsWidget(widget, oldcreator.getBounds()),
+ new BoundsWidget(oldcreator.toData(), oldcreator.getBounds()));
+ this.convert();
+ return (XCreator) this.getComponent(i);
+ }
+ return null;
+ }
+
+ @Override
+ public Dimension getMinimumSize() {
+ return toData().getMinDesignSize();
+ }
+
+ /**
+ * 将WLayout转换为XLayoutContainer
+ */
+ public void convert() {
+ isRefreshing = true;
+ WFitLayout layout = this.toData();
+ this.removeAll();
+ for (int i=0, num=layout.getWidgetCount(); i childrenList = creator.getTargetChildrenList();
+ if(!childrenList.isEmpty()){
+ for(int i=0; i 0) {
+ for (int i=1, len=hors.length; i= rec.width) {
+ break;
+ }
+ }
+ if (rec.y > 0) {
+ for (int j=1, num=veris.length; j= rec.height) {
+ break;
+ }
+ }
+ return bound;
+ }
+
+ /**
+ * 组件删除
+ * @param e 容器事件
+ */
+ public void componentRemoved(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ WFitLayout wlayout = this.toData();
+ XWidgetCreator xwc = ((XWidgetCreator) e.getChild());
+ Widget wgt = xwc.toData();
+ BoundsWidget bw = wlayout.getBoundsWidget(wgt);
+ wlayout.removeWidget(bw);
+ updateBoundsWidget();
+ }
+
+ /**
+ * 在添加的时候需要把可拉伸的方向确定,所以重写了add方法
+ * @param comp 组件
+ * @param constraints 属性
+ */
+ public void add(Component comp, Object constraints) {
+ if (comp == null) {
+ return;
+ }
+ super.add(comp, constraints);
+ XCreator creator = (XCreator) comp;
+ dealDirections(creator, false);
+ }
+
+ private void add(Component comp, Object constraints, boolean isInit) {
+ super.add(comp, constraints);
+ XCreator creator = (XCreator) comp;
+ dealDirections(creator, isInit);
+ }
+
+ /**
+ * 处理自适应布局的directions
+ * @param creator 组件
+ */
+ private void dealDirections(XCreator xcreator, boolean isInit) {
+ if (xcreator == null) {
+ return;
+ }
+ // 重新打开模版时,容器还没初始化,大小都还为0
+ int containerWidth = isInit ? toData().getContainerWidth() : this.getWidth();
+ int containerHeight = isInit ? toData().getContainerHeight() : this.getHeight();
+ PaddingMargin margin = isInit ? new PaddingMargin(0,0,0,0) : toData().getMargin();
+ // 再次打开时和初始设计时的区别是没计算过内边距和没按屏幕分辨率调整大小
+ for (int i=0; i directions = new ArrayList();
+ // 只要组件边框没有和container贴着的,都可以拉伸
+ if (x > margin.getLeft()) {
+ directions.add(Direction.LEFT);
+ }
+ if (x+w < containerWidth - margin.getRight()) {
+ directions.add(Direction.RIGHT);
+ }
+ if (y > margin.getTop()) {
+ directions.add(Direction.TOP);
+ }
+ if (y+h < containerHeight - margin.getBottom()) {
+ directions.add(Direction.BOTTOM);
+ }
+ if (directions.isEmpty()) {
+ creator.setDirections(null);
+ }else {
+ creator.setDirections(ArrayUtils.toPrimitive(directions.toArray(new Integer[directions.size()])));
+ }
+ }
+
+ }
+
+
+ /**
+ * 间隔大于0时,界面处加上间隔
+ * 界面的间隔是针对显示,实际保存的大小不受间隔影响
+ * ps:改变布局大小或者拖入、删除、拉伸都要重新考虑间隔
+ * @param gap 间隔
+ */
+ public void addCompInterval(int gap) {
+ if (gap == 0) {
+ return;
+ }
+ int val = gap/2;
+ for (int i=0, len=this.getComponentCount(); i 0) {
+ bound.x += val;
+ bound.width -= val;
+ }
+ if (rec.width+rec.x < this.getWidth()) {
+ bound.width -= val;
+ }
+ if (rec.y > 0) {
+ bound.y += val;
+ bound.height -= val;
+ }
+ if (rec.height+rec.y < this.getHeight()) {
+ bound.height -= val;
+ }
+ comp.setBounds(bound);
+ }
+ this.hasCalGap = true;
+ }
+
+ /**
+ * 去除原有的间隔
+ * @param gap 间隔
+ */
+ public void moveCompInterval(int gap) {
+ if (gap == 0) {
+ return;
+ }
+ int val = gap/2;
+ for (int i=0, len=this.getComponentCount(); i 0) {
+ bound.x -= val;
+ bound.width += val;
+ }
+ if (rec.width+rec.x < this.getWidth()) {
+ bound.width += val;
+ }
+ if (rec.y > 0) {
+ bound.y -= val;
+ bound.height += val;
+ }
+ if (rec.height+rec.y < this.getHeight()) {
+ bound.height += val;
+ }
+ comp.setBounds(bound);
+ }
+ this.hasCalGap = false;
+ }
+
+ /**
+ * 是否可以加入当前间隔
+ * @param interval 间隔
+ * @return 默认返回true
+ */
+ public boolean canAddInterval(int interval) {
+ int val = interval/2;
+ for (int i=0, len=this.getComponentCount(); i 0) {
+ bound.width -= val;
+ }
+ if (rec.width+rec.x < d.width) {
+ bound.width -= val;
+ }
+ if (rec.y > 0) {
+ bound.height -= val;
+ }
+ if (rec.height+rec.y < d.height) {
+ bound.height -= val;
+ }
+ return new Rectangle(bound);
+ }
+
+ /**
+ * 缩小宽度或者高度时 存在间隔的话是否支持缩小
+ */
+ private boolean canReduceSize(double percent) {
+ int val = toData().getCompInterval()/2;
+ for (int i=0, len=this.getComponentCount(); i 1) {
+ getTitleCreator().toData().setWidgetName(WidgetTitle.TITLE_NAME_INDEX + name);
+ }
+ }
+
+ /**
+ * 返回默认组件name
+ *
+ * @return 容器名
+ */
+ @Override
+ public String createDefaultName() {
+ return "titlePanel";
+ }
+
+ /**
+ * 返回标题组件
+ * @return 标题组件
+ */
+ public XCreator getTitleCreator() {
+ for (int i=0; i < getXCreatorCount(); i++) {
+ XCreator creator = getXCreator(i);
+ if (!creator.hasTitleStyle()) {
+ return creator;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 将WLayout转换为XLayoutContainer
+ */
+ @Override
+ public void convert() {
+ isRefreshing = true;
+ WTitleLayout layout = this.toData();
+ this.removeAll();
+ for (int i = 0, num = layout.getWidgetCount(); i < num; i++) {
+ BoundsWidget bw = (BoundsWidget) layout.getWidget(i);
+ if (bw != null) {
+ Rectangle bounds = bw.getBounds();
+ XWidgetCreator comp = (XWidgetCreator) XCreatorUtils.createXCreator(bw.getWidget());
+ String constraint = bw.getWidget().acceptType(Label.class) ? WTitleLayout.TITLE : WTitleLayout.BODY;
+ this.add(comp, constraint);
+ comp.setBounds(bounds);
+ }
+ }
+ isRefreshing = false;
+ }
+
+ /**
+ * 组件增加
+ *
+ * @param e 容器事件
+ */
+ @Override
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ WTitleLayout layout = this.toData();
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ FRTitleLayout lay = (FRTitleLayout) getLayout();
+ Object constraints = lay.getConstraints(creator);
+ if (ComparatorUtils.equals(WTitleLayout.TITLE,constraints)) {
+ layout.addTitle(creator.toData(), creator.getBounds());
+ } else if (ComparatorUtils.equals(WTitleLayout.BODY,constraints)) {
+ layout.addBody(creator.toData(), creator.getBounds());
+ }
+ }
+
+ /**
+ * 组件删除
+ *
+ * @param e
+ * 容器事件
+ */
+ @Override
+ public void componentRemoved(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator xwc = ((XWidgetCreator) e.getChild());
+ Widget wgt = xwc.toData();
+ WTitleLayout wlayout = this.toData();
+ wlayout.removeWidget(wgt);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWVerticalBoxLayout.java b/designer_form/src/com/fr/design/designer/creator/XWVerticalBoxLayout.java
new file mode 100644
index 000000000..438e36eb5
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWVerticalBoxLayout.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ContainerEvent;
+
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.adapters.layout.FRVerticalLayoutAdapter;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.form.layout.FRVerticalLayout;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WVerticalBoxLayout;
+
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XWVerticalBoxLayout extends XLayoutContainer {
+
+ public XWVerticalBoxLayout(WVerticalBoxLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public WVerticalBoxLayout toData() {
+ return (WVerticalBoxLayout) data;
+ }
+
+ @Override
+ public Dimension initEditorSize() {
+ return new Dimension(100, 200);
+ }
+
+ @Override
+ protected void initLayoutManager() {
+ this.setLayout(new FRVerticalLayout(this.toData().getHgap(), this.toData().getVgap()));
+ }
+
+ @Override
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ WVerticalBoxLayout wlayout = this.toData();
+ Widget wgt = creator.toData();
+ for (int i = 0, count = this.getComponentCount(); i < count; i++) {
+ if (creator == this.getComponent(i)) {
+ wlayout.addWidget(wgt, i);
+ wlayout.setHeightAtWidget(wgt, creator.getHeight());
+ }
+ }
+ this.recalculateChildrenPreferredSize();
+ }
+
+ @Override
+ protected Dimension calculatePreferredSize(Widget wgt) {
+ // 注意这里计算PreferredSize的时候需要取当前容器的实际大小
+ return new Dimension(this.getSize().width, this.toData().getHeightAtWidget(wgt));
+ }
+
+ @Override
+ protected String getIconName() {
+ return "boxlayout_v_16.png";
+ }
+
+ @Override
+ public String createDefaultName() {
+ return "vBox";
+ }
+
+ // 在添加的时候需要把可拉伸的方向确定,所以重写了add方法
+ @Override
+ public Component add(Component comp, int index) {
+ super.add(comp, index);
+ if (comp == null) {
+ return null;
+ }
+ XCreator creator = (XCreator) comp;
+ creator.setDirections(new int[]{Direction.TOP, Direction.BOTTOM});
+ return comp;
+ }
+
+ @Override
+ public LayoutAdapter getLayoutAdapter() {
+ return new FRVerticalLayoutAdapter(this);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWVerticalSplitLayout.java b/designer_form/src/com/fr/design/designer/creator/XWVerticalSplitLayout.java
new file mode 100644
index 000000000..043612b80
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWVerticalSplitLayout.java
@@ -0,0 +1,40 @@
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.adapters.layout.FRVerticalSplitLayoutAdapter;
+import com.fr.design.form.layout.FRVerticalSplitLayout;
+import com.fr.form.ui.container.WVerticalSplitLayout;
+
+public class XWVerticalSplitLayout extends XAbstractSplitLayout {
+
+ public XWVerticalSplitLayout(WVerticalSplitLayout widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public WVerticalSplitLayout toData() {
+ return (WVerticalSplitLayout) data;
+ }
+
+ @Override
+ protected void initLayoutManager() {
+ this.setLayout(new FRVerticalSplitLayout(toData().getRatio(), toData().getHgap(), toData().getVgap()));
+ }
+
+ @Override
+ protected String getIconName() {
+ return "separator_16.png";
+ }
+
+ @Override
+ public String createDefaultName() {
+ return "vsplit";
+ }
+
+ @Override
+ public LayoutAdapter getLayoutAdapter() {
+ return new FRVerticalSplitLayoutAdapter(this);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWidgetCreator.java b/designer_form/src/com/fr/design/designer/creator/XWidgetCreator.java
new file mode 100644
index 000000000..3832f35d2
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWidgetCreator.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.*;
+import java.beans.IntrospectionException;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.FRContext;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.form.ui.Widget;
+import com.fr.general.Inter;
+import com.fr.stable.core.PropertyChangeAdapter;
+
+import javax.swing.*;
+
+/**
+ * @author richer
+ * @since 6.5.3 com.fr.rpt.web.ui.Widget的设计组件
+ */
+public abstract class XWidgetCreator extends XCreator {
+
+ protected static final float FULL_OPACITY = 1.0f;
+ protected static final float HALF_OPACITY = 0.4f;
+
+ public XWidgetCreator(Widget widget, Dimension initSize) {
+ super(widget, initSize);
+ setOpaque(false);
+ }
+
+ /**
+ * 待说明
+ * @return 待说明
+ * @throws IntrospectionException
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetName", this.data.getClass()).setI18NName(Inter
+ .getLocText("Form-Widget_Name")),
+ new CRPropertyDescriptor("enabled", this.data.getClass()).setI18NName(Inter.getLocText("FR-Designer_Enabled"))
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ setEnabled(toData().isEnabled());
+ }
+ }),
+ new CRPropertyDescriptor("visible", this.data.getClass()).setI18NName(
+ Inter.getLocText("FR-Designer_Widget-Visible")).setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ makeVisible(toData().isVisible());
+ }
+ }) };
+
+ }
+
+ /**
+ * 待说明
+ * @return 待说明
+ */
+ public Widget toData() {
+ return this.data;
+ }
+
+ /**
+ * 根据Widget的属性值初始化XCreator的属性值
+ */
+ @Override
+ protected void initXCreatorProperties() {
+ this.setEnabled(toData().isEnabled());
+ }
+
+ /**
+ * 待说明
+ */
+ public void recalculateChildrenSize() {
+ }
+
+
+ protected void makeVisible(boolean visible) {
+ }
+
+ public class LimpidButton extends JButton {
+ private String name;
+ private String imagePath;
+ private float opacity = 0.4f;
+ public LimpidButton(String name, String imagePath, float opacity) {
+ this.name = name;
+ this.imagePath = imagePath;
+ this.opacity = opacity;
+ this.draw();
+ }
+
+ public void draw() {
+ try {
+ ImageIcon imageIcon =(ImageIcon) BaseUtils.readIcon(imagePath);
+ Image img = imageIcon.getImage();
+ MediaTracker mt = new MediaTracker(this);
+ int w = 21;
+ int h = 21;
+ mt.addImage(img, 0);
+ mt.waitForAll();
+
+ GraphicsConfiguration gc = new JFrame().getGraphicsConfiguration(); // 本地图形设备
+ Image image = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);//建立透明画布
+ Graphics2D g = (Graphics2D) image.getGraphics(); //在画布上创建画笔
+
+ Composite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f); //指定透明度为半透明90%
+ g.setComposite(alpha);
+ g.drawImage(img, 0, 0, this); //注意是,将image画到g画笔所在的画布上
+ g.setColor(Color.black);//设置颜色为黑色
+ g.drawString(name, 25, 20);//写字
+ g.dispose(); //释放内存
+
+ Composite alpha2 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
+ Image image1 = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
+ g = (Graphics2D) image1.getGraphics();
+ g.setComposite(alpha2);
+ g.drawImage(img, 2, 2, this); //改变图像起始位置,产生动态效果
+ g.setColor(Color.black);
+ g.drawString(name, 25, 20);
+ g.dispose();
+
+ this.setIgnoreRepaint(true);
+ this.setFocusable(false);//设置没有焦点
+ this.setBorder(null);//设置不画按钮边框
+ this.setContentAreaFilled(false);//设置不画按钮背景
+ this.setIcon(new ImageIcon(image1)); //把刚才生成的半透明image变成ImageIcon,贴到按钮上去
+ this.setRolloverIcon(new ImageIcon(image1));
+ this.setPressedIcon(new ImageIcon(image));//按下去的图标
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage());
+ }
+ }
+
+ /**
+ * 待说明
+ * @param visible 待说明
+ */
+ public void makeVisible(boolean visible) {
+ this.opacity = visible ? FULL_OPACITY : HALF_OPACITY;
+ this.draw();
+ }
+ }
+
+ /**
+ * 重命名
+ *
+ * @param designer 表单设计器
+ * @param creator 当前组件
+ *
+ */
+ public void ChangeCreatorName(FormDesigner designer,XCreator creator){
+ String oldName = creator.toData().getWidgetName();
+ String value = JOptionPane.showInputDialog(designer, Inter.getLocText("Form-Change_Widget_Name_Discription"), oldName);
+ if(value != null) {
+ designer.renameCreator(creator, value);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWrapperedFieldEditor.java b/designer_form/src/com/fr/design/designer/creator/XWrapperedFieldEditor.java
new file mode 100644
index 000000000..bbb6b0198
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWrapperedFieldEditor.java
@@ -0,0 +1,69 @@
+/**
+ *
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+
+import javax.swing.JComponent;
+
+import com.fr.form.ui.FieldEditor;
+
+/**
+ *
+ *
+ * @date: 2014-11-25-下午5:08:06
+ */
+public abstract class XWrapperedFieldEditor extends XFieldEditor {
+
+ /**
+ * 构造函数
+ */
+ public XWrapperedFieldEditor(FieldEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ protected abstract JComponent initEditor();
+
+ protected abstract String getIconName();
+
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName){
+ return new XWScaleLayout();
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ this.setSize(width, minHeight);
+ parentPanel.add(this);
+ }
+
+ /**
+ * 此控件在自适应布局要保持原样高度
+ *
+ * @return 是则返回true
+ */
+ @Override
+ public boolean shouldScaleCreator() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/XWriteAbleRepeatEditor.java b/designer_form/src/com/fr/design/designer/creator/XWriteAbleRepeatEditor.java
new file mode 100644
index 000000000..7e3dcdb07
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/XWriteAbleRepeatEditor.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.creator;
+
+import java.awt.Dimension;
+import java.beans.IntrospectionException;
+
+import com.fr.form.ui.WriteAbleRepeatEditor;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class XWriteAbleRepeatEditor extends XDirectWriteEditor {
+
+ public XWriteAbleRepeatEditor(WriteAbleRepeatEditor widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ @Override
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return (CRPropertyDescriptor[]) ArrayUtils.addAll(
+ super.supportedDescriptor(),
+ new CRPropertyDescriptor[]{
+ new CRPropertyDescriptor("removeRepeat", this.data.getClass()).setI18NName(Inter.getLocText("Form-Remove_Repeat")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ new CRPropertyDescriptor("waterMark", this.data.getClass()).setI18NName(Inter.getLocText("WaterMark")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced"),
+ });
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/cardlayout/XCardAddButton.java b/designer_form/src/com/fr/design/designer/creator/cardlayout/XCardAddButton.java
new file mode 100644
index 000000000..652331d1f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/cardlayout/XCardAddButton.java
@@ -0,0 +1,183 @@
+package com.fr.design.designer.creator.cardlayout;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.event.MouseEvent;
+
+import javax.swing.Icon;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.models.SelectionModel;
+import com.fr.design.designer.creator.XButton;
+import com.fr.design.mainframe.EditingMouseListener;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormHierarchyTreePane;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.form.ui.CardAddButton;
+import com.fr.form.ui.CardSwitchButton;
+import com.fr.form.ui.container.cardlayout.WCardTagLayout;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.Inter;
+
+public class XCardAddButton extends XButton{
+
+ private XWCardTagLayout tagLayout;
+ private XWCardLayout cardLayout;
+ private static final int LEFT_GAP = 5;
+ private static final int UP_GAP = 10;
+
+ private static final int START_INDEX = 3;
+ private static final int INDEX = 0;
+
+
+ private static Icon ADD_ICON = BaseUtils.readIcon("/com/fr/design/form/images/add.png");
+ private Icon addIcon = ADD_ICON;
+
+ /**
+ * card布局添加card按钮
+ */
+
+ public XWCardTagLayout getTagLayout() {
+ return tagLayout;
+ }
+
+ public void setTagLayout(XWCardTagLayout tagLayout) {
+ this.tagLayout = tagLayout;
+ }
+
+ public XWCardLayout getCardLayout() {
+ return cardLayout;
+ }
+
+ public void setCardLayout(XWCardLayout cardLayout) {
+ this.cardLayout = cardLayout;
+ }
+
+ /**
+ * 构造函数
+ * @param widget 按钮
+ * @param initSize 大小
+ */
+ public XCardAddButton(CardAddButton widget, Dimension initSize) {
+ super(widget, initSize);
+ }
+
+ /**
+ * 构造函数
+ * @param widget 按钮
+ * @param initSize 大小
+ */
+ public XCardAddButton(CardAddButton widget, Dimension initSize,XWCardTagLayout fit,XWCardLayout cardLayout) {
+ super(widget, initSize);
+ this.tagLayout = fit;
+ this.cardLayout = cardLayout;
+ }
+
+ /**
+ * 响应点击事件
+ * @param editingMouseListener 事件处理器
+ * @param e 点击事件
+ *
+ */
+ public void respondClick(EditingMouseListener editingMouseListener,MouseEvent e){
+ FormDesigner designer = editingMouseListener.getDesigner();
+ designer.fireTargetModified();
+
+ // addbutton对应的XWCardLayout和XWCardTagLayout暂未存入到xml中,重新打开之后先根据父子层获取
+ if(cardLayout == null && tagLayout ==null ){
+ initRalateLayout();
+ }
+ int index = cardLayout.toData().getWidgetCount();
+
+ //添加新的tab,并将原来的设为未选中状态
+ setTabUnselectd();
+ addTab(index);
+ this.tagLayout.adjustComponentWidth();
+
+ if (editingMouseListener.stopEditing()) {
+ ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, this);
+ editingMouseListener.startEditing(this, adapter.getDesignerEditor(), adapter);
+ }
+
+ FormHierarchyTreePane.getInstance().refreshRoot();
+ //将焦点切换到新增的tab对应的tabfitLayout上
+ showNewTab(editingMouseListener,index);
+
+ LayoutUtils.layoutRootContainer(designer.getRootComponent());
+ }
+
+ private void initRalateLayout(){
+ XWCardTitleLayout titleLayout = (XWCardTitleLayout)this.getBackupParent();
+ this.tagLayout = titleLayout.getTagPart();
+
+ XWCardMainBorderLayout borderLayout = (XWCardMainBorderLayout)titleLayout.getBackupParent();
+ this.cardLayout = borderLayout.getCardPart();
+ }
+
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Graphics2D g2d = (Graphics2D) g;
+ drawAddIcon(g2d);
+ }
+
+ private void drawAddIcon(Graphics2D g2d){
+ addIcon.paintIcon(this, g2d,LEFT_GAP,UP_GAP);
+ }
+
+ //将原来的tab页设置为未选中状态
+ private void setTabUnselectd(){
+ for(int i=0;i index) {
+ tempButton.setIndex(--currentIndex);
+ }
+ if (tabFitIndex > index) {
+ layout.setIndex(--tabFitIndex);
+ }
+ }
+ }
+
+
+ //SwitchButton对应的XWCardLayout和XWCardTagLayout暂未存到xml中,重新打开时根据父子层关系获取
+ private void initRalateLayout(XCardSwitchButton button){
+ this.tagLayout = (XWCardTagLayout)this.getBackupParent();
+ XWCardTitleLayout titleLayout = (XWCardTitleLayout) this.tagLayout.getBackupParent();
+ XWCardMainBorderLayout borderLayout = (XWCardMainBorderLayout)titleLayout.getBackupParent();
+ this.cardLayout = borderLayout.getCardPart();
+ }
+
+ //是否进入点击关闭按钮区域
+ private boolean isSeletectedClose(MouseEvent e,FormDesigner designer){
+
+ int diff = designer.getArea().getHorScrollBar().getValue();
+
+ // mouse position
+ int ex = e.getX() + diff;
+ int ey = e.getY();
+
+ //获取tab布局的位置,鼠标相对于tab按钮的位置
+ XLayoutContainer mainLayout = cardLayout.getBackupParent();
+ Point point = mainLayout.getLocation();
+ double mainX = point.getX();
+ double mainY = point.getY();
+
+ // 参数界面对坐标的影响
+ JForm jform = (JForm)HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
+ if(jform.getFormDesign().getParaComponent() != null){
+ ey -= jform.getFormDesign().getParaHeight();
+ }
+
+ //减掉tab布局的相对位置
+ ex -= mainX;
+ ey -= mainY;
+
+ // button position
+ XCardSwitchButton button = this;
+ Point position = button.getLocation();
+ int width = button.getWidth();
+ int height = button.getHeight();
+
+ // 鼠标进入按钮右侧删除图标区域
+ double recX = position.getX() + (width - RIGHT_OFFSET);
+ double recY = position.getY() + (height - TOP_OFFSET);
+
+ return (recX < ex && ex < recX + RIGHT_OFFSET && ey < recY);
+ }
+
+ //将当前switchButton改为选中状态
+ private void changeButtonState(int index){
+ for(int i=0;i 0) {
+ cardLayout.show(this, layout.getShowIndex2Name());
+ }
+ }
+
+ /**
+ * 获取当前XCreator的一个封装父容器
+ *
+ * @param widgetName 当前组件名
+ *
+ * @return 封装的父容器
+ *
+ *
+ * @date 2014-11-25-下午4:47:23
+ *
+ */
+ protected XLayoutContainer getCreatorWrapper(String widgetName) {
+ initStyle();
+ Dimension dimension = new Dimension();
+ //主结构是一个borderlayout, 标签部分是north, card部分为center
+ WCardMainBorderLayout border = new WCardMainBorderLayout();
+ XWCardMainBorderLayout xMainBorder = new XWCardMainBorderLayout(border, dimension);
+ this.setBackupParent(xMainBorder);
+
+ XWCardTitleLayout titlePart = this.initTitlePart(widgetName, xMainBorder);
+ xMainBorder.addTitlePart(titlePart);
+
+ return xMainBorder;
+ }
+
+ //标题栏
+ private XWCardTitleLayout initTitlePart(String widgetName, XWCardMainBorderLayout xMainBorder){
+ Dimension dimension = new Dimension();
+ //标题部分本身也是一个borderlayout布局, tag部分放center, 添加按钮放east
+ WCardTitleLayout titleLayout = new WCardTitleLayout(this.toData().getWidgetName());
+ XWCardTitleLayout xTitle = new XWCardTitleLayout(titleLayout,dimension);
+ xTitle.setBackupParent(xMainBorder);
+
+ //切换card的按钮部分
+ XWCardTagLayout tagPart = initTagPart(widgetName, xTitle);
+ //添加按钮
+ XCardAddButton addBtn = initAddButton(widgetName, xTitle, tagPart);
+
+ //添加顺序很重要,先addBtn再tagPart,后面用到
+ xTitle.addNewButton(addBtn);
+ xTitle.addTagPart(tagPart);
+
+ return xTitle;
+ }
+
+ //添加tab按钮
+ private XCardAddButton initAddButton(String widgetName, XWCardTitleLayout xTitle, XWCardTagLayout tagPart){
+ Dimension dimension = new Dimension();
+ CardAddButton addButton = new CardAddButton(widgetName);
+ XCardAddButton xAddBtn = new XCardAddButton(addButton, dimension, tagPart, this);
+ xAddBtn.setBackupParent(xTitle);
+
+ return xAddBtn;
+ }
+
+ //所有的tab所在的区域
+ private XWCardTagLayout initTagPart(String widgetName, XWCardTitleLayout xTitle){
+ Dimension dimension = new Dimension();
+ //放置标题的tab流式布局
+ WCardTagLayout tagLayout = new WCardTagLayout();
+ XWCardTagLayout xTag = new XWCardTagLayout(tagLayout, dimension, this);
+ xTag.setBackupParent(xTitle);
+
+ XCardSwitchButton xFirstBtn = initFirstButton(widgetName, xTag);
+ xTag.add(xFirstBtn);
+
+ return xTag;
+ }
+
+ //第一个tab
+ private XCardSwitchButton initFirstButton(String widgetName, XWCardTagLayout xTag){
+ CardSwitchButton firstBtn = new CardSwitchButton(widgetName);
+ firstBtn.setText(Inter.getLocText("FR-Designer_Title") + 0);
+ firstBtn.setInitialBackground(ColorBackground.getInstance(Color.WHITE));
+ xTag.setCurrentCard(firstBtn);
+ XCardSwitchButton xFirstBtn = new XCardSwitchButton(firstBtn, new Dimension(CardSwitchButton.DEF_WIDTH, -1),this,xTag);
+ firstBtn.setCustomStyle(true);
+ xFirstBtn.setBackupParent(xTag);
+
+ return xFirstBtn;
+ }
+
+ /**
+ * 设置父容器的名字
+ *
+ * @param parentPanel 当前父容器
+ * @param widgetName 当前控件名
+ *
+ *
+ * @date 2014-11-27-上午9:47:00
+ *
+ */
+ protected void setWrapperName(XLayoutContainer parentPanel, String widgetName) {
+ //先随便set一个, 以后还是要隐藏的
+ parentPanel.toData().setWidgetName("border_card_" + widgetName);
+ }
+
+ /**
+ * 将当前对象添加到父容器中
+ *
+ * @param parentPanel 父容器组件
+ *
+ *
+ * @date 2014-11-25-下午4:57:55
+ *
+ */
+ protected void addToWrapper(XLayoutContainer parentPanel, int width, int minHeight){
+ parentPanel.add(this, WBorderLayout.CENTER);
+ }
+
+ /**
+ * 添加组件的监听事件
+ *
+ * @param e 事件
+ *
+ *
+ * @date 2014-11-25-下午6:20:10
+ *
+ */
+ public void componentAdded(ContainerEvent e) {
+ if (isRefreshing) {
+ return;
+ }
+ XWidgetCreator creator = (XWidgetCreator) e.getChild();
+ creator.setDirections(null);
+ WCardLayout layout = this.toData();
+ Widget w = creator.toData();
+ layout.addWidget(w);
+ }
+
+ @Override
+ public LayoutAdapter getLayoutAdapter() {
+ return new FRCardLayoutAdapter(this);
+ }
+
+ /**
+ * 是否支持标题样式
+ * @return 默认false
+ */
+ public boolean hasTitleStyle() {
+ return true;
+ }
+
+
+ /**
+ * 得到属性名
+ * @return 属性名
+ * @throws IntrospectionException
+ */
+ public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException {
+ return new CRPropertyDescriptor[] {
+ new CRPropertyDescriptor("widgetName", this.data.getClass()).setI18NName(Inter
+ .getLocText("FR-Designer_Form-Widget_Name")).setPropertyChangeListener(new PropertyChangeAdapter(){
+
+ @Override
+ public void propertyChange(){
+ WCardLayout cardLayout = toData();
+ changeRalateSwitchCardname(cardLayout.getWidgetName());
+ }
+ }),
+ new CRPropertyDescriptor("borderStyle", this.data.getClass()).setEditorClass(
+ CardTagWLayoutBorderStyleEditor.class).setRendererClass(LayoutBorderStyleRenderer.class).setI18NName(
+ Inter.getLocText("FR-Engine_Style")).putKeyValue(XCreatorConstants.PROPERTY_CATEGORY, "Advanced")
+ .setPropertyChangeListener(new PropertyChangeAdapter() {
+
+ @Override
+ public void propertyChange() {
+ initStyle();
+ }
+ }),
+ };
+ }
+
+ //初始化样式
+ protected void initStyle() {
+ LayoutBorderStyle style = toData().getBorderStyle();
+ initBorderTitleStyle(style);
+ initBorderStyle();
+ clearOrShowTitleLayout(ComparatorUtils.equals(style.getType(), LayoutBorderStyle.TITLE));
+ }
+
+ private void initBorderTitleStyle(LayoutBorderStyle style){
+ //初始化默认标题样式
+ if(!initFlag){
+ return;
+ }
+
+ style.setType(LayoutBorderStyle.TITLE);
+ style.setBorder(Constants.LINE_THIN);
+ WidgetTitle widgetTitle = style.getTitle();
+ widgetTitle.setBackground(ColorBackground.getInstance(TITLE_COLOR));
+ initFlag = false;
+ }
+
+ //隐藏或显示标题部分
+ protected void clearOrShowTitleLayout(boolean isTitleStyle) {
+ XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout)this.getBackupParent();
+ if(mainLayout != null){
+ XWCardTitleLayout titleLayout = (XWCardTitleLayout) mainLayout.getComponent(NORTH);
+ if(titleLayout != null){
+ WCardTitleLayout layout = (WCardTitleLayout) titleLayout.toData();
+ titleLayout.setVisible(isTitleStyle);
+ layout.setVisible(isTitleStyle);
+ }
+ }
+ }
+
+ //修改相关SwtchButton所绑定的cardLayout控件名
+ private void changeRalateSwitchCardname(String cardLayoutName) {
+ XWCardMainBorderLayout borderLayout = (XWCardMainBorderLayout) this.getBackupParent();
+ WCardMainBorderLayout border = borderLayout.toData();
+ WCardTitleLayout titleLayout = border.getTitlePart();
+ WCardTagLayout tagLayout = titleLayout.getTagPart();
+ for (int i = 0, len = tagLayout.getWidgetCount(); i < len; i++) {
+ CardSwitchButton button = tagLayout.getSwitchButton(i);
+ button.setCardLayoutName(cardLayoutName);
+ }
+ }
+
+ /**
+ * 删除相关组件
+ *
+ * @param creator 当前组件
+ * @param designer 表单设计器
+ *
+ */
+ public void deleteRelatedComponent(XCreator creator,FormDesigner designer){
+ XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) creator.getBackupParent();
+ SelectionModel selectionModel = designer.getSelectionModel();
+ selectionModel.setSelectedCreator(mainLayout);
+ selectionModel.deleteSelection();
+ return;
+ }
+ @Override
+ public void setBorder(Border border) {
+ super.setBorder(border);
+ XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) this.getBackupParent();
+ if(mainLayout != null){
+ mainLayout.setBorder(border);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java b/designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java
new file mode 100644
index 000000000..003bde4a4
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardMainBorderLayout.java
@@ -0,0 +1,191 @@
+/**
+ *
+ */
+package com.fr.design.designer.creator.cardlayout;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.util.ArrayList;
+
+
+
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.form.ui.container.WBorderLayout;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout;
+
+/**
+ * card布局主体框架
+ *
+ *
+ *
+ * @date: 2014-12-9-下午9:59:31
+ */
+public class XWCardMainBorderLayout extends XWBorderLayout{
+
+ private static final int CENTER = 1;
+ private static final int NORTH = 0;
+ public static final Color DEFAULT_BORDER_COLOR = new Color(210,210,210);
+ private static final int LAYOUT_INDEX = 0;
+ private static final int TITLE_STYLE = 2;
+ private static final int NORMAL_STYLE = 1;
+
+ /**
+ * 构造函数
+ */
+ public XWCardMainBorderLayout(WCardMainBorderLayout border, Dimension dimension) {
+ super(border, dimension);
+ }
+
+ /**
+ * 获取当前组件里的控件
+ *
+ * @return 控件
+ *
+ *
+ * @date 2014-12-10-下午1:46:33
+ *
+ */
+ public WCardMainBorderLayout toData() {
+ return (WCardMainBorderLayout) super.toData();
+ }
+
+ /**
+ * 添加标题区域
+ *
+ * @param title 标题区域
+ *
+ *
+ * @date 2014-12-10-下午1:50:56
+ *
+ */
+ public void addTitlePart(XWCardTitleLayout title){
+ this.add(title, WBorderLayout.NORTH);
+ }
+
+ /**
+ * 添加card区域
+ *
+ * @param card card区域
+ *
+ *
+ * @date 2014-12-10-下午1:50:37
+ *
+ */
+ public void addCardPart(XWCardLayout card){
+ this.add(card, WBorderLayout.CENTER);
+ }
+
+ public XWCardLayout getCardPart(){
+ return this.getComponentCount() == TITLE_STYLE ? (XWCardLayout)this.getComponent(CENTER) : (XWCardLayout)this.getComponent(NORTH);
+ }
+
+ public XWCardTitleLayout getTitlePart(){
+ return (XWCardTitleLayout)this.getComponent(NORTH);
+ }
+
+ /**
+ * 控件树里需要隐藏xwcardmainLayout,返回其子组件xwcardLayout;
+ * 标题样式下,this.getComponent(1)==xwcardLayout
+ * 标准样式下,this.getComponent(0)==xwcardLayout
+ * @return 子组件xwcardLayout
+ */
+ @Override
+ public XCreator getXCreator() {
+ switch(this.getComponentCount()){
+ case TITLE_STYLE:
+ return (XCreator)this.getComponent(TITLE_STYLE-1);
+ case NORMAL_STYLE:
+ return (XCreator)this.getComponent(NORMAL_STYLE-1);
+ default:
+ return this;
+ }
+ }
+ /**
+ * 控件树不显示此组件
+ * @param path 控件树list
+ */
+ public void notShowInComponentTree(ArrayList path) {
+ path.remove(LAYOUT_INDEX);
+ }
+
+ @Override
+ public ArrayList getTargetChildrenList() {
+ ArrayList tabLayoutList = new ArrayList();
+ XWCardLayout cardLayout = this.getCardPart();
+ for(int i=0, size=cardLayout.getComponentCount(); i childrenList = this.getTargetChildrenList();
+ int size = childrenList.size();
+ if (size > 0) {
+ for (int j = 0; j < size; j++) {
+ XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList
+ .get(j);
+ tabLayout.setBackupBound(tabLayout.getBounds());
+ int refSize = tabLayout.getWidth();
+ int offest = width - refSize;
+ double percent = (double) offest / refSize;
+ if (percent < 0 && !tabLayout.canReduce(percent)) {
+ return;
+ }
+ tabLayout.setSize(tabLayout.getWidth() + offest,
+ tabLayout.getHeight());
+ for (int m = 0; m < tabLayout.getComponentCount(); m++) {
+ XCreator childCreator = tabLayout.getXCreator(m);
+ BoundsWidget wgt = tabLayout.toData()
+ .getBoundsWidget(childCreator.toData());
+ wgt.setBounds(tabLayout.getComponent(m).getBounds());
+ }
+ tabLayout.adjustCreatorsWidth(percent);
+ }
+ }
+ }
+
+ /**
+ * 重新调整子组件的高度
+ * @param height 高度
+ */
+ public void recalculateChildHeight(int height){
+ ArrayList> childrenList = this.getTargetChildrenList();
+ int size = childrenList.size();
+ if (size > 0) {
+ for (int j = 0; j < size; j++) {
+ XWTabFitLayout tabLayout = (XWTabFitLayout) childrenList
+ .get(j);
+ tabLayout.setBackupBound(tabLayout.getBounds());
+ int refSize = tabLayout.getHeight();
+ int offset = height - refSize - WCardMainBorderLayout.TAB_HEIGHT;
+ if(offset < 0){
+ // 缩放时需要备份原tab布局宽高
+ tabLayout.setReferDim(new Dimension(tabLayout.getWidth(),tabLayout.getHeight()));
+ }
+ double percent = (double) offset / refSize;
+ if (percent < 0 && !tabLayout.canReduce(percent)) {
+ return;
+ }
+ tabLayout.setSize(tabLayout.getWidth(),
+ tabLayout.getHeight() + offset);
+ for (int m = 0; m < tabLayout.getComponentCount(); m++) {
+ XCreator childCreator = tabLayout.getXCreator(m);
+ BoundsWidget wgt = tabLayout.toData()
+ .getBoundsWidget(childCreator.toData());
+ wgt.setBounds(tabLayout.getComponent(m).getBounds());
+ }
+ tabLayout.adjustCreatorsHeight(percent);
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java b/designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java
new file mode 100644
index 000000000..bd844b53e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/creator/cardlayout/XWCardTagLayout.java
@@ -0,0 +1,217 @@
+/**
+ *
+ */
+package com.fr.design.designer.creator.cardlayout;
+
+import java.awt.Dimension;
+import java.awt.event.ContainerEvent;
+import java.awt.event.MouseEvent;
+
+import javax.swing.border.Border;
+
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.models.SelectionModel;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XWHorizontalBoxLayout;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.design.mainframe.EditingMouseListener;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.form.ui.CardSwitchButton;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WCardLayout;
+import com.fr.form.ui.container.cardlayout.WCardTagLayout;
+import com.fr.form.ui.container.cardlayout.WTabFitLayout;
+
+/**
+ *
+ *
+ * @date: 2014-11-25-下午3:11:14
+ */
+public class XWCardTagLayout extends XWHorizontalBoxLayout {
+
+ private static final int MIN_SIZE = 1;
+
+ private String tagName = "Tab";
+
+ //增加一个tabNameIndex防止tabFitLayout重名
+ private int tabFitIndex = 0;
+ private CardSwitchButton currentCard;
+
+ public CardSwitchButton getCurrentCard() {
+ return currentCard;
+ }
+
+ public void setCurrentCard(CardSwitchButton currentCard) {
+ this.currentCard = currentCard;
+ }
+
+ public int getTabFitIndex() {
+ return tabFitIndex;
+ }
+
+ public void setTabFitIndex(int tabFitIndex) {
+ this.tabFitIndex = tabFitIndex;
+ }
+
+ public String getTagName() {
+ return tagName;
+ }
+
+ public void setTagName(String tagName) {
+ this.tagName = tagName;
+ }
+
+ private XWCardLayout cardLayout;
+
+ public XWCardTagLayout(WCardTagLayout widget, Dimension initSize){
+ super(widget, initSize);
+ }
+
+ /**
+ * 构造函数
+ */
+ public XWCardTagLayout(WCardTagLayout widget, Dimension initSize, XWCardLayout cardLayout) {
+ super(widget, initSize);
+
+ this.cardLayout = cardLayout;
+ }
+
+ /**
+ * 添加组件的监听事件
+ *
+ * @param e 事件
+ *
+ *
+ * @date 2014-11-25-下午6:20:10
+ *
+ */
+ public void componentAdded(ContainerEvent e) {
+ super.componentAdded(e);
+
+ if(this.cardLayout == null){
+ initCardLayout();
+ }
+
+ int index = this.cardLayout.toData().getWidgetCount();
+ //新加一个card
+ String widgetName = tagName+getTabNameIndex();
+ WTabFitLayout fitLayout = new WTabFitLayout(widgetName,tabFitIndex,currentCard);
+ fitLayout.setTabNameIndex(getTabNameIndex());
+ XWTabFitLayout tabFitLayout = new XWTabFitLayout(fitLayout, new Dimension());
+ tabFitLayout.setBackupParent(cardLayout);
+ cardLayout.add(tabFitLayout, widgetName);
+ this.cardLayout.toData().setShowIndex(index);
+ cardLayout.showCard();
+ }
+
+ private void initCardLayout(){
+ XWCardTitleLayout titleLayout = (XWCardTitleLayout)this.getBackupParent();
+ XWCardMainBorderLayout borderLayout = (XWCardMainBorderLayout)titleLayout.getBackupParent();
+
+ this.cardLayout = borderLayout.getCardPart();
+ }
+
+ /**
+ * 将WLayout转换为XLayoutContainer
+ */
+ public void convert() {
+ isRefreshing = true;
+ WCardTagLayout layout = (WCardTagLayout)this.toData();
+ this.removeAll();
+ for (int i = 0; i < layout.getWidgetCount(); i++) {
+ Widget wgt = layout.getWidget(i);
+ if (wgt != null) {
+ XWidgetCreator comp = (XWidgetCreator) XCreatorUtils.createXCreator(wgt, calculatePreferredSize(wgt));
+ this.add(comp, i);
+ comp.setBackupParent(this);
+ }
+ }
+ isRefreshing = false;
+ }
+
+ /**
+ * 切换到非添加状态
+ *
+ * @return designer 表单设计器
+ */
+ public void stopAddingState(FormDesigner designer){
+ designer.stopAddingState();
+ return;
+ }
+
+ //新增时去tabFitLayout名字中最大的Index+1,防止重名
+ private int getTabNameIndex(){
+ int tabNameIndex = 0;
+ WCardLayout layout = this.cardLayout.toData();
+ int size = layout.getWidgetCount();
+ if(size < MIN_SIZE){
+ return tabNameIndex;
+ }
+ for(int i=0;i index){
+ button.setIndex(--buttonIndex);
+ }
+ if(currentFitIndex > index){
+ tempFitLayout.setIndex(--currentFitIndex);
+ }
+ }
+ }
+
+ /**
+ * tab布局里切换到相应的tab按钮
+ * @param comp 当前组件
+ * void
+ */
+ public void seleteRelatedComponent(XCreator comp){
+ XWTabFitLayout fitLayout = (XWTabFitLayout)comp;
+ WTabFitLayout fit = (WTabFitLayout) fitLayout.toData();
+ int index = fit.getIndex();
+ XWCardLayout cardLayout = (XWCardLayout) fitLayout.getBackupParent();
+ XWCardMainBorderLayout mainLayout = (XWCardMainBorderLayout) cardLayout.getBackupParent();
+ XWCardTitleLayout titleLayout = mainLayout.getTitlePart();
+ XWCardTagLayout tagLayout = titleLayout.getTagPart();
+ WCardTagLayout layout = (WCardTagLayout) tagLayout.toData();
+ for(int i=0;i0 && hasCalGap) {
+ moveCompInterval(getAcualInterval());
+ updateCompsWidget();
+ }
+ layoutWidthResize(percent);
+ if (percent < 0 && this.getNeedAddWidth() > 0) {
+ this.setSize(this.getWidth()+this.getNeedAddWidth(), this.getHeight());
+ modifyEdgemostCreator(true);
+ }
+ addCompInterval(getAcualInterval());
+ // 本次缩放结束,参照宽高清掉
+ this.setReferDim(null);
+ updateCompsWidget();
+ this.toData().setContainerWidth(this.getWidth());
+ updateWidgetBackupBounds();
+ LayoutUtils.layoutContainer(this);
+ }
+
+
+ /**
+ * 布局容器高度手动修改时,
+ * 同时调整容器内的组件们,缩小时需要考虑有的组件高度不满足缩小高度
+ * @param percent 高度变化的百分比
+ */
+ public void adjustCreatorsHeight(double percent) {
+ if (this.getComponentCount()==0) {
+ //调整高度后,wlayout那边记录下
+ this.toData().setContainerHeight(this.getHeight());
+ return;
+ }
+ updateWidgetBackupBounds();
+ int gap = toData().getCompInterval();
+ if (gap >0 && hasCalGap) {
+ moveCompInterval(getAcualInterval());
+ updateCompsWidget();
+ }
+ layoutHeightResize(percent);
+ if (percent < 0 && this.getNeedAddHeight() > 0) {
+ this.setSize(this.getWidth(), this.getHeight()+this.getNeedAddHeight());
+ modifyEdgemostCreator(false);
+ }
+ addCompInterval(getAcualInterval());
+ updateCompsWidget();
+ this.toData().setContainerHeight(this.getHeight());
+ updateWidgetBackupBounds();
+ LayoutUtils.layoutContainer(this);
+ }
+
+ public XLayoutContainer getOuterLayout(){
+ XWCardLayout cardLayout = (XWCardLayout) this.getBackupParent();
+ return cardLayout.getBackupParent();
+ }
+
+ // 更新内部组件的widget
+ private void updateCompsWidget(){
+ for(int m=0;m 0) {
+ bound.x -= val;
+ bound.width += val;
+ }
+ if (rec.width+rec.x < referWidth) {
+ bound.width += val;
+ }
+ if (rec.y > 0) {
+ bound.y -= val;
+ bound.height += val;
+ }
+ if (rec.height+rec.y < referHeight) {
+ bound.height += val;
+ }
+ comp.setBounds(bound);
+ }
+
+ this.hasCalGap = false;
+ }
+
+ private double getReferWidth(){
+ if(referDim != null){
+ return referDim.getWidth();
+ }else{
+ return this.getWidth();
+ }
+ }
+
+ private double getReferHeight(){
+ if(referDim != null){
+ return referDim.getHeight();
+ }else{
+ return this.getHeight();
+ }
+ }
+
+
+ /**
+ * 间隔大于0时,界面处加上间隔
+ * 界面的间隔是针对显示,实际保存的大小不受间隔影响
+ * ps:改变布局大小或者拖入、删除、拉伸都要重新考虑间隔
+ * @param gap 间隔
+ */
+ public void addCompInterval(int gap) {
+ if (gap == 0) {
+ return;
+ }
+ int val = gap/2;
+ double referWidth = getReferWidth();
+ double referHeight = getReferHeight();
+ for (int i=0, len=this.getComponentCount(); i 0) {
+ bound.x += val;
+ bound.width -= val;
+ }
+ if (rec.width+rec.x < referWidth) {
+ bound.width -= val;
+ }
+ if (rec.y > 0) {
+ bound.y += val;
+ bound.height -= val;
+ }
+ if (rec.height+rec.y < referHeight) {
+ bound.height -= val;
+ }
+ comp.setBounds(bound);
+ }
+
+ this.hasCalGap = true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/BoundsGroupModel.java b/designer_form/src/com/fr/design/designer/properties/BoundsGroupModel.java
new file mode 100644
index 000000000..4c20d0467
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/BoundsGroupModel.java
@@ -0,0 +1,139 @@
+package com.fr.design.designer.properties;
+
+import java.awt.Rectangle;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XWAbsoluteLayout;
+import com.fr.form.ui.container.WAbsoluteLayout;
+
+/**
+ * 绝对布局时候的属性组
+ */
+public class BoundsGroupModel implements ConstraintsGroupModel {
+ private static final int MINHEIGHT = 21;
+ private static final int FOUR = 4;
+
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor editor;
+ private XCreator component;
+ private XWAbsoluteLayout parent;
+
+ public BoundsGroupModel(XWAbsoluteLayout parent, XCreator comp) {
+ this.parent = parent;
+ component = comp;
+ renderer = new DefaultTableCellRenderer();
+ editor = new PropertyCellEditor(new IntegerPropertyEditor());
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Form-Component_Bounds");
+ }
+
+ @Override
+ public int getRowCount() {
+ return FOUR;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ return renderer;
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ return editor;
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("FR-Designer_X_Coordinate");
+ case 1:
+ return Inter.getLocText("FR-Designer_Y_Coordinate");
+ case 2:
+ return Inter.getLocText("FR-Designer_Widget_Width");
+ default:
+ return Inter.getLocText("FR-Designer_Widget_Height");
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return component.getX();
+ case 1:
+ return component.getY();
+ case 2:
+ return component.getWidth();
+ default:
+ return component.getHeight();
+ }
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 1) {
+ int v = value == null ? 0 : ((Number) value).intValue();
+ Rectangle bounds = new Rectangle(component.getBounds());
+ switch (row) {
+ case 0:
+ if (bounds.x == v){
+ return false;
+ }
+ bounds.x = v;
+ break;
+ case 1:
+ if (bounds.y == v){
+ return false;
+ }
+ bounds.y = v;
+ break;
+ case 2:
+ if (bounds.width == v){
+ return false;
+ }
+ bounds.width = v;
+ break;
+ case 3:
+ if(v < MINHEIGHT){
+ JOptionPane.showMessageDialog(null, Inter.getLocText("FR-Designer_Min_Height") + "21");
+ v = component.getHeight();
+ }
+ if (bounds.height == v){
+ return false;
+ }
+ bounds.height = v;
+ break;
+ }
+ WAbsoluteLayout wabs = parent.toData();
+ wabs.setBounds(component.toData(),bounds);
+ component.setBounds(bounds);
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * 属性组是否可编辑
+ * @param row 第几行
+ * @return 组件可编辑
+ */
+ @Override
+ public boolean isEditable(int row) {
+ //这里不需要为自定义按钮屏蔽大小属性
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/CardDefaultShowEditor.java b/designer_form/src/com/fr/design/designer/properties/CardDefaultShowEditor.java
new file mode 100644
index 000000000..6f7ba9d75
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/CardDefaultShowEditor.java
@@ -0,0 +1,11 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.designer.properties.items.LayoutIndexItems;
+import com.fr.form.ui.container.WCardLayout;
+
+public class CardDefaultShowEditor extends EnumerationEditor {
+
+ public CardDefaultShowEditor(WCardLayout layout) {
+ super(new LayoutIndexItems(layout, false));
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/CardDefaultShowRenderer.java b/designer_form/src/com/fr/design/designer/properties/CardDefaultShowRenderer.java
new file mode 100644
index 000000000..e4613053a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/CardDefaultShowRenderer.java
@@ -0,0 +1,11 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.mainframe.widget.renderer.EncoderCellRenderer;
+import com.fr.form.ui.container.WCardLayout;
+
+public class CardDefaultShowRenderer extends EncoderCellRenderer {
+
+ public CardDefaultShowRenderer(WCardLayout layout) {
+ super(new CardDefaultShowWrapper(layout));
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/CardDefaultShowWrapper.java b/designer_form/src/com/fr/design/designer/properties/CardDefaultShowWrapper.java
new file mode 100644
index 000000000..37b7e77ed
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/CardDefaultShowWrapper.java
@@ -0,0 +1,11 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.designer.properties.items.LayoutIndexItems;
+import com.fr.form.ui.container.WCardLayout;
+
+public class CardDefaultShowWrapper extends ItemWrapper {
+
+ public CardDefaultShowWrapper(WCardLayout layout) {
+ super(new LayoutIndexItems(layout, false));
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/CardLayoutConstraints.java b/designer_form/src/com/fr/design/designer/properties/CardLayoutConstraints.java
new file mode 100644
index 000000000..2ca24c8e6
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/CardLayoutConstraints.java
@@ -0,0 +1,86 @@
+package com.fr.design.designer.properties;
+
+import java.awt.Component;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WCardLayout;
+import com.fr.general.Inter;
+
+public class CardLayoutConstraints implements ConstraintsGroupModel {
+
+ private DefaultTableCellRenderer renderer;
+ private FRCardConstraintsEditor editor1;
+ private Widget widget;
+ private WCardLayout layout;
+ private XWCardLayout container;
+
+ public CardLayoutConstraints(XWCardLayout parent, Component comp) {
+ this.layout = parent.toData();
+ this.container = parent;
+ this.widget = ((XWidgetCreator) comp).toData();
+ this.editor1 = new FRCardConstraintsEditor(layout);
+ this.renderer = new DefaultTableCellRenderer();
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("FR-Designer_Layout_Constraints");
+ }
+
+ @Override
+ public int getRowCount() {
+ return 1;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ return this.renderer;
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ return this.editor1;
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ return Inter.getLocText("FR-Designer_Layout-Index");
+ } else {
+ return layout.getWidgetIndex(widget) + 1;
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 1) {
+ layout.setWidgetIndex(widget, value == null ? 0 : (((Number) value).intValue() - 1));
+ container.convert();
+ //TODO:convert后丢失焦点
+ return true;
+ }
+ return true;
+ }
+
+ /**
+ * 是否可编辑
+ *
+ * @param row 当前行
+ *
+ * @return 是否可编辑
+ *
+ *
+ * @date 2014-12-30-下午5:14:31
+ *
+ */
+ public boolean isEditable(int row) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/CardLayoutPropertiesGroupModel.java b/designer_form/src/com/fr/design/designer/properties/CardLayoutPropertiesGroupModel.java
new file mode 100644
index 000000000..67188521d
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/CardLayoutPropertiesGroupModel.java
@@ -0,0 +1,125 @@
+package com.fr.design.designer.properties;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+import com.fr.design.form.layout.FRCardLayout;
+import com.fr.form.ui.container.WCardLayout;
+
+public class CardLayoutPropertiesGroupModel implements GroupModel {
+
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor editor;
+ private CardDefaultShowRenderer defaultShowRenderer;
+ private CardDefaultShowEditor defaultShowEditor;
+ private WCardLayout layout;
+ private XWCardLayout xLayout;
+
+ public CardLayoutPropertiesGroupModel(XWCardLayout Container) {
+ this.layout = Container.toData();
+ this.xLayout = Container;
+ this.renderer = new DefaultTableCellRenderer();
+ this.editor = new PropertyCellEditor(new IntegerPropertyEditor());
+ this.defaultShowRenderer = new CardDefaultShowRenderer(layout);
+ this.defaultShowEditor = new CardDefaultShowEditor(layout);
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("FR-Engine-Tab_Layout_Widget_Size");
+ }
+
+ @Override
+ public int getRowCount() {
+ return 2;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ switch (row) {
+ case 0:
+ return renderer;
+ case 1:
+ return renderer;
+ default:
+ return defaultShowRenderer;
+ }
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ switch (row) {
+ case 0:
+ return editor;
+ case 1:
+ return editor;
+ default:
+ return defaultShowEditor;
+ }
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("FR-Engine-Tab_Layout_Width");
+ default:
+ return Inter.getLocText("FR-Engine-Tab_Layout_Height");
+
+
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return (int)xLayout.getSize().getHeight();
+ default:
+ return (int)xLayout.getSize().getWidth();
+ }
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 0) {
+ return false;
+ } else {
+ int v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ switch (row) {
+ case 0:
+ layout.setHgap(v);
+ ((FRCardLayout)xLayout.getLayout()).setHgap(v);
+ return true;
+ case 1:
+ layout.setVgap(v);
+ ((FRCardLayout)xLayout.getLayout()).setVgap(v);
+ return true;
+ case 2:
+ layout.setShowIndex(v);
+ xLayout.showCard();
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ /**
+ * 是否可以编辑
+ * @param 列
+ * @return 是否可以编辑
+ */
+ @Override
+ public boolean isEditable(int row) {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/Decoder.java b/designer_form/src/com/fr/design/designer/properties/Decoder.java
new file mode 100644
index 000000000..f3c0d15df
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/Decoder.java
@@ -0,0 +1,14 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.Exception.ValidationException;
+
+/**
+ * 将字符串转化成控件控件属性,辅以判断该字符串是否合乎属性规则
+ * @since 6.5.2
+ */
+public interface Decoder {
+
+ T decode(String txt);
+
+ void validate(String txt) throws ValidationException;
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/DelegateEditor.java b/designer_form/src/com/fr/design/designer/properties/DelegateEditor.java
new file mode 100644
index 000000000..88a8c59b8
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/DelegateEditor.java
@@ -0,0 +1,123 @@
+package com.fr.design.designer.properties;
+
+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.AbstractCellEditor;
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.table.TableCellEditor;
+
+public class DelegateEditor extends AbstractCellEditor implements TableCellEditor {
+
+ protected JComponent editorComponent;
+ protected EditorDelegate delegate;
+ protected int clickCountToStart = 1;
+
+ public Component getComponent() {
+ return editorComponent;
+ }
+
+ public void setClickCountToStart(int count) {
+ clickCountToStart = count;
+ }
+
+ public int getClickCountToStart() {
+ return clickCountToStart;
+ }
+
+ @Override
+ public Object getCellEditorValue() {
+ return delegate.getCellEditorValue();
+ }
+
+ @Override
+ public boolean isCellEditable(EventObject anEvent) {
+ return delegate.isCellEditable(anEvent);
+ }
+
+ @Override
+ public boolean shouldSelectCell(EventObject anEvent) {
+ return delegate.shouldSelectCell(anEvent);
+ }
+
+ @Override
+ public boolean stopCellEditing() {
+ return delegate.stopCellEditing();
+ }
+
+ @Override
+ public void cancelCellEditing() {
+ delegate.cancelCellEditing();
+ }
+
+ @Override
+ public Component getTableCellEditorComponent(JTable table, Object value,
+ boolean isSelected, int row, int column) {
+ delegate.setValue(value);
+ return editorComponent;
+ }
+
+ protected class EditorDelegate implements ActionListener, ItemListener, ChangeListener,
+ Serializable {
+
+ protected Object value;
+
+ public Object getCellEditorValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public boolean isCellEditable(EventObject anEvent) {
+ if (anEvent instanceof MouseEvent) {
+ return ((MouseEvent) anEvent).getClickCount() >= clickCountToStart;
+ }
+ return true;
+ }
+
+ public boolean shouldSelectCell(EventObject anEvent) {
+ return true;
+ }
+
+ public boolean startCellEditing(EventObject anEvent) {
+ return true;
+ }
+
+ public boolean stopCellEditing() {
+ fireEditingStopped();
+ return true;
+ }
+
+ public void cancelCellEditing() {
+ fireEditingCanceled();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ DelegateEditor.this.stopCellEditing();
+ }
+
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ DelegateEditor.this.stopCellEditing();
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ DelegateEditor.this.stopCellEditing();
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/Encoder.java b/designer_form/src/com/fr/design/designer/properties/Encoder.java
new file mode 100644
index 000000000..636d92cec
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/Encoder.java
@@ -0,0 +1,10 @@
+package com.fr.design.designer.properties;
+
+/**
+ * 将控件属性 转化成字符串
+ * @since 6.5.2
+ */
+public interface Encoder {
+
+ String encode(T v);
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/EnumerationEditor.java b/designer_form/src/com/fr/design/designer/properties/EnumerationEditor.java
new file mode 100644
index 000000000..c56483e56
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/EnumerationEditor.java
@@ -0,0 +1,88 @@
+package com.fr.design.designer.properties;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseEvent;
+import java.util.Enumeration;
+import java.util.EventObject;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComponent;
+
+import com.fr.design.gui.icombobox.UIComboBox;
+import com.fr.design.designer.properties.items.Item;
+import com.fr.design.designer.properties.items.ItemProvider;
+
+public class EnumerationEditor extends DelegateEditor {
+
+ public EnumerationEditor(ItemProvider provider) {
+ this(provider.getItems());
+ }
+
+ public EnumerationEditor(Item[] items) {
+ DefaultComboBoxModel model = new DefaultComboBoxModel();
+ for (Item item : items) {
+ model.addElement(item);
+ }
+ init(new UIComboBox(model));
+ }
+
+ public EnumerationEditor(Iterable- items) {
+ DefaultComboBoxModel model = new DefaultComboBoxModel();
+ for (Item item : items) {
+ model.addElement(item);
+ }
+ init(new UIComboBox(model));
+ }
+
+ public EnumerationEditor(Enumeration
- items) {
+ DefaultComboBoxModel model = new DefaultComboBoxModel();
+ while (items.hasMoreElements()) {
+ model.addElement(items.nextElement());
+ }
+ init(new UIComboBox(model));
+ }
+
+ public EnumerationEditor(UIComboBox comboBox) {
+ init(comboBox);
+ }
+
+ private void init(final UIComboBox comboBox) {
+ editorComponent = comboBox;
+ comboBox.putClientProperty("UIComboBox.isTableCellEditor", Boolean.TRUE);
+ delegate = new EditorDelegate() {
+
+ @Override
+ public void setValue(Object value) {
+ Item item = new Item(null, value);
+ comboBox.setSelectedItem(item);
+ }
+
+ @Override
+ public Object getCellEditorValue() {
+ Item item = (Item) comboBox.getSelectedItem();
+ return item.getValue();
+ }
+
+ @Override
+ public boolean shouldSelectCell(EventObject anEvent) {
+ if (anEvent instanceof MouseEvent) {
+ MouseEvent e = (MouseEvent) anEvent;
+ return e.getID() != MouseEvent.MOUSE_DRAGGED;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean stopCellEditing() {
+ if (comboBox.isEditable()) {
+ comboBox.actionPerformed(new ActionEvent(
+ EnumerationEditor.this, 0, ""));
+ }
+ return super.stopCellEditing();
+ }
+ };
+ ((JComponent) comboBox.getEditor().getEditorComponent()).setBorder(null);
+ editorComponent.setBorder(null);
+ comboBox.addActionListener(delegate);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/EventPropertyTable.java b/designer_form/src/com/fr/design/designer/properties/EventPropertyTable.java
new file mode 100644
index 000000000..bec1b44f8
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/EventPropertyTable.java
@@ -0,0 +1,482 @@
+package com.fr.design.designer.properties;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.FRContext;
+import com.fr.design.actions.UpdateAction;
+import com.fr.design.gui.frpane.ListenerUpdatePane;
+import com.fr.design.gui.ilist.JNameEdList;
+import com.fr.design.gui.itoolbar.UIToolbar;
+import com.fr.design.javascript.EmailPane;
+import com.fr.design.javascript.JavaScriptActionPane;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.menu.MenuDef;
+import com.fr.design.menu.ShortCut;
+import com.fr.design.menu.ToolBarDef;
+import com.fr.design.write.submit.DBManipulationPane;
+import com.fr.design.dialog.BasicDialog;
+import com.fr.design.dialog.BasicPane;
+import com.fr.design.dialog.DialogActionAdapter;
+import com.fr.design.editor.ValueEditorPaneFactory;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.form.event.Listener;
+import com.fr.design.form.javascript.FormEmailPane;
+import com.fr.form.ui.Widget;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.Inter;
+import com.fr.general.NameObject;
+import com.fr.js.JavaScriptImpl;
+import com.fr.stable.Nameable;
+import com.fr.design.utils.gui.GUICoreUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.IOException;
+
+public class EventPropertyTable extends BasicPane {
+
+ private ShortCut[] shorts;
+ private XCreator creator;
+ private JNameEdList nameableList;
+ private ToolBarDef toolbarDef;
+ private AddItemMenuDef itemMenu;
+ private ShortCut editItemAction;
+ private ShortCut copyItemAction;
+ private ShortCut removeItemAction;
+ private UIToolbar toolbar;
+ private ListenerUpdatePane listenerPane;
+ private FormDesigner designer;
+
+ public EventPropertyTable(FormDesigner designer) {
+ super();
+ this.designer = designer;
+ this.initComponents();
+ }
+
+ protected void initComponents() {
+ this.setLayout(new BorderLayout());
+ nameableList = new JNameEdList(new DefaultListModel());
+ this.add(new JScrollPane(nameableList), BorderLayout.CENTER);
+
+ nameableList.setCellRenderer(new NameableListCellRenderer());
+ nameableList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
+ nameableList.addMouseListener(listMouseListener);
+ nameableList.setTransferHandler(new DnDTransferHandler());
+ nameableList.setDropMode(DropMode.INSERT);
+ nameableList.setDragEnabled(true);
+
+ toolbarDef = new ToolBarDef();
+ shorts = new ShortCut[] { itemMenu = new AddItemMenuDef(), editItemAction = new EditItemMenuDef(),
+ copyItemAction = new CopyItemAction(), removeItemAction = new RemoveItemAction() };
+ for (ShortCut sj : shorts) {
+ toolbarDef.addShortCut(sj);
+ }
+ toolbar = ToolBarDef.createJToolBar();
+ toolbarDef.updateToolBar(toolbar);
+ this.add(toolbar, BorderLayout.NORTH);
+ }
+
+ /**
+ * 指定索引添加对象
+ * @param nameObject 对象名
+ * @param index 索引
+ */
+ public void addNameObject(NameObject nameObject, int index) {
+ DefaultListModel model = (DefaultListModel) nameableList.getModel();
+
+ model.add(index, nameObject);
+ nameableList.setSelectedIndex(index);
+ nameableList.ensureIndexIsVisible(index);
+
+ nameableList.repaint();
+ }
+
+ /**
+ * 刷新控件
+ * @param strings 字符数组
+ */
+ public void refreshNameableCreator(String[] strings) {
+ itemMenu.populate(strings);
+
+ toolbarDef.updateToolBar(toolbar);
+ toolbar.validate();
+ toolbar.repaint();
+ this.repaint();
+ }
+
+ private void checkButtonEnabled() {
+ boolean enable = nameableList.getSelectedValue() instanceof NameObject;
+ itemMenu.setEnabled(this.creator != null && itemMenu.getShortCutCount() > 0);
+ editItemAction.setEnabled(enable);
+ copyItemAction.setEnabled(enable);
+ removeItemAction.setEnabled(enable);
+ }
+
+ private MouseListener listMouseListener = new MouseAdapter() {
+ @Override
+ public void mouseReleased(MouseEvent evt) {
+ checkButtonEnabled();
+ if (evt.getClickCount() >= 2 && SwingUtilities.isLeftMouseButton(evt)) {
+ NameObject object = (NameObject) nameableList.getSelectedValue();
+ showEventPane(object);
+ }
+ }
+ };
+
+ private void showEventPane(final NameObject object) {
+ if (listenerPane == null) {
+ listenerPane = new ListenerUpdatePane() {
+
+ @Override
+ protected JavaScriptActionPane createJavaScriptActionPane() {
+ return new JavaScriptActionPane() {
+
+ @Override
+ protected DBManipulationPane createDBManipulationPane() {
+ return new DBManipulationPane(ValueEditorPaneFactory.formEditors());
+ }
+
+ @Override
+ protected String title4PopupWindow() {
+ return Inter.getLocText("Set_Callback_Function");
+ }
+ @Override
+ protected EmailPane initEmaiPane() {
+ return new FormEmailPane();
+ }
+ @Override
+ public boolean isForm() {
+ return true;
+ }
+
+ protected String[] getDefaultArgs() {
+ return new String[0];
+ }
+
+ };
+ }
+ @Override
+ protected boolean supportCellAction() {
+ return false;
+ }
+
+ };
+ }
+ listenerPane.populateBean((Listener) object.getObject());
+ BasicDialog dialog = listenerPane.showWindow(SwingUtilities.getWindowAncestor(this));
+ dialog.addDialogActionListener(new DialogActionAdapter() {
+ @Override
+ public void doOk() {
+ object.setObject(listenerPane.updateBean());
+ updateWidgetListener(creator);
+ }
+ });
+ dialog.setVisible(true);
+ }
+
+ private 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 NameObject) {
+ Nameable wrappee = (NameObject) value;
+ this.setText(wrappee.getName());
+ }
+ return this;
+ }
+ }
+
+ /*
+ * 增加项的MenuDef
+ */
+ protected class AddItemMenuDef extends MenuDef {
+ public AddItemMenuDef() {
+ this.setName(Inter.getLocText("Add"));
+ this.setMnemonic('A');
+ this.setIconPath("/com/fr/design/images/control/addPopup.png");
+ }
+
+ public void populate(String[] eventNames) {
+ this.clearShortCuts();
+ for (int i = 0; i < eventNames.length; i++) {
+ final String eventname = eventNames[i];
+
+ this.addShortCut(new UpdateAction() {
+ {
+ this.setName(switchLang(eventname));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ NameObject nameable = new NameObject(createUnrepeatedName(switchLang(eventname)), new Listener(
+ eventname,new JavaScriptImpl()));
+
+ EventPropertyTable.this.addNameObject(nameable, EventPropertyTable.this.nameableList.getModel()
+ .getSize());
+ updateWidgetListener(creator);
+ }
+ });
+ }
+ }
+ }
+
+ protected class EditItemMenuDef extends UpdateAction {
+ public EditItemMenuDef() {
+ this.setName(Inter.getLocText("Edit"));
+ this.setMnemonic('E');
+ this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/control/edit.png"));
+ }
+
+ public void actionPerformed(ActionEvent evt) {
+ if (nameableList.getSelectedValue() instanceof NameObject) {
+ showEventPane((NameObject) nameableList.getSelectedValue());
+ }
+ }
+ }
+
+ private String switchLang(String eventName) {
+ return Inter.getLocText("Event-" + eventName);
+ }
+
+ /**
+ * 刷新
+ */
+ public void refresh() {
+ int selectionSize = designer.getSelectionModel().getSelection().size();
+ if (selectionSize == 0 || selectionSize == 1) {
+ this.creator = selectionSize == 0 ? designer.getRootComponent() : designer.getSelectionModel()
+ .getSelection().getSelectedCreator();
+ } else {
+ this.creator = null;
+ ((DefaultListModel) nameableList.getModel()).removeAllElements();
+ checkButtonEnabled();
+ return;
+ }
+ Widget widget = creator.toData();
+
+ refreshNameableCreator(widget.supportedEvents());
+
+ ((DefaultListModel) nameableList.getModel()).removeAllElements();
+ for (int i = 0, size = widget.getListenerSize(); i < size; i++) {
+ Listener listener = widget.getListener(i);
+ if (!listener.isDefault()) {
+ addNameObject(new NameObject(switchLang(listener.getEventName()) + (i + 1), listener), i);
+ }
+ }
+ checkButtonEnabled();
+ this.repaint();
+ }
+
+ /**
+ * 更新控件事件
+ * @param creator 控件
+ */
+ public void updateWidgetListener(XCreator creator) {
+ DefaultListModel listModel = (DefaultListModel) this.nameableList.getModel();
+ (creator.toData()).clearListeners();
+ for (int i = 0, len = listModel.getSize(); i < len; i++) {
+ (creator.toData()).addListener((Listener) ((NameObject) listModel.getElementAt(i)).getObject());
+ }
+ designer.fireTargetModified();
+ checkButtonEnabled();
+ }
+
+ private class RemoveItemAction extends UpdateAction {
+ public RemoveItemAction() {
+ this.setName(Inter.getLocText("Remove"));
+ this.setMnemonic('R');
+ this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/remove.png"));
+ }
+
+ public void actionPerformed(ActionEvent evt) {
+ GUICoreUtils.removeJListSelectedNodes(SwingUtilities.getWindowAncestor(EventPropertyTable.this),
+ nameableList);
+ updateWidgetListener(creator);
+ }
+
+ }
+
+ /*
+ * CopyItem
+ */
+ private class CopyItemAction extends UpdateAction {
+ public CopyItemAction() {
+ this.setName(Inter.getLocText("Copy"));
+ this.setMnemonic('C');
+ this.setSmallIcon(BaseUtils.readIcon("/com/fr/base/images/cell/control/copy.png"));
+ }
+
+ public void actionPerformed(ActionEvent evt) {
+ NameObject selectedNameObject = (NameObject) nameableList.getSelectedValue();
+
+ // p: 用反射机制实现
+ try {
+ NameObject newNameObject = (NameObject) BaseUtils.cloneObject(selectedNameObject);
+ newNameObject.setName("CopyOf" + selectedNameObject.getName());
+
+ EventPropertyTable.this.addNameObject(newNameObject, nameableList.getSelectedIndex() + 1);
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ }
+ updateWidgetListener(creator);
+ }
+ }
+
+ @Override
+ protected String title4PopupWindow() {
+ return "Event";
+ }
+
+ /**
+ * 生成不重复名字
+ * @param prefix 字符
+ * @return 返回
+ */
+ public String createUnrepeatedName(String prefix) {
+ DefaultListModel model = (DefaultListModel) nameableList.getModel();
+ Nameable[] all = new Nameable[model.getSize()];
+ for (int i = 0; i < model.size(); i++) {
+ all[i] = (Nameable) model.get(i);
+ }
+ int count = 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++;
+ }
+ }
+
+ private class DnDTransferHandler extends TransferHandler {
+ private int action;
+
+ public DnDTransferHandler() {
+ this(TransferHandler.MOVE);
+ }
+
+ public DnDTransferHandler(int action) {
+ this.action = action;
+ }
+
+ @Override
+ public int getSourceActions(JComponent comp) {
+ return action;
+ }
+
+ @Override
+ public Transferable createTransferable(JComponent comp) {
+
+ int index = nameableList.getSelectedIndex();
+ if (index < 0 || index >= nameableList.getModel().getSize()) {
+ return null;
+ }
+
+ return new DnDListItem((NameObject) nameableList.getSelectedValue());
+ }
+
+ @Override
+ public boolean canImport(TransferSupport support) {
+ if (!support.isDrop()) {
+ return false;
+ }
+
+ if (!support.isDataFlavorSupported(DnDListItem.FLAVOR)) {
+ return false;
+ }
+
+ boolean actionSupported = (action & support.getSourceDropActions()) == action;
+ if (actionSupported) {
+ support.setDropAction(action);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean importData(TransferHandler.TransferSupport support) {
+ if (!canImport(support)) {
+ return false;
+ }
+ JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();
+
+ int importIndex = dl.getIndex();
+
+ try {
+ NameObject item = (NameObject) support.getTransferable().getTransferData(DnDListItem.FLAVOR);
+ JList list = (JList) support.getComponent();
+ DefaultListModel model = (DefaultListModel) list.getModel();
+ for (int i = 0; i <= importIndex; i++) {
+ if (ComparatorUtils.equals(item,model.getElementAt(i))) {
+ importIndex--;
+ break;
+ }
+ }
+ model.removeElement(item);
+ model.insertElementAt(item, importIndex);
+ updateWidgetListener(creator);
+ } catch (UnsupportedFlavorException e) {
+ return false;
+ } catch (java.io.IOException e) {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ public static class DnDListItem implements Transferable {
+ private NameObject no;
+ public static final DataFlavor FLAVOR = new DataFlavor(DnDListItem.class, "DnDListItem.class");
+
+ public DnDListItem(NameObject no) {
+ this.no = no;
+ }
+
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { FLAVOR };
+ }
+
+ @Override
+ /**
+ *是否支持 dataFlavor
+ *@param DataFlavor类
+ *@return 支持返回true
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ if (ComparatorUtils.equals(flavor,FLAVOR)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+ if (ComparatorUtils.equals(flavor,FLAVOR)) {
+ return no;
+ }
+
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/FRBorderConstraintsEditor.java b/designer_form/src/com/fr/design/designer/properties/FRBorderConstraintsEditor.java
new file mode 100644
index 000000000..dd9e60c33
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/FRBorderConstraintsEditor.java
@@ -0,0 +1,10 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.designer.properties.items.FRBorderConstraintsItems;
+
+public class FRBorderConstraintsEditor extends EnumerationEditor {
+
+ public FRBorderConstraintsEditor(String[] directions) {
+ super(new FRBorderConstraintsItems(directions));
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraints.java b/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraints.java
new file mode 100644
index 000000000..dfa633c23
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraints.java
@@ -0,0 +1,213 @@
+package com.fr.design.designer.properties;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.stable.StringUtils;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.mainframe.widget.editors.StringEditor;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.form.ui.FreeButton;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.container.WBorderLayout;
+
+public class FRBorderLayoutConstraints implements ConstraintsGroupModel {
+
+ private FRBorderLayoutConstraintsRenderer renderer0;
+ private DefaultTableCellRenderer renderer;
+ private FRBorderConstraintsEditor editor1;
+ private PropertyCellEditor editor2;
+ private PropertyCellEditor editor3;
+ private Widget widget;
+ private WBorderLayout layout;
+ private XWBorderLayout container;
+
+ public FRBorderLayoutConstraints(Container parent, Component comp) {
+ this.container = ((XWBorderLayout) parent);
+ this.layout = ((XWBorderLayout) parent).toData();
+ this.widget = ((XWidgetCreator) comp).toData();
+ this.renderer0 = new FRBorderLayoutConstraintsRenderer();
+ this.renderer = new DefaultTableCellRenderer();
+ this.editor1 = new FRBorderConstraintsEditor(layout.getDirections());
+ this.editor2 = new PropertyCellEditor(new StringEditor());
+ this.editor3 = new PropertyCellEditor(new IntegerPropertyEditor());
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Layout_Constraints");
+ }
+
+ @Override
+ public int getRowCount() {
+ Object obj = layout.getConstraints(widget);
+ if (obj == null) {
+ return 0;
+ }
+ return BorderLayout.CENTER.equals(obj) ? 2 : 3;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ if (row == 0) {
+ return this.renderer0;
+ }
+ return renderer;
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ switch (row) {
+ case 0:
+ return editor1;
+ case 1:
+ return editor2;
+ default:
+ return editor3;
+ }
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("BorderLayout-Constraints");
+ case 1:
+ return Inter.getLocText("Title");
+ default:
+ return getSizeDisplayName();
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return getChildPositionDisplayName();
+ case 1:
+ return getChildTitle();
+ default:
+ return getChildSize();
+ }
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 1) {
+ switch (row) {
+ case 0:
+ return switchWidgets(value);
+ case 1:
+ return setChildTitle(value);
+ default:
+ return setChildSize(value);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isEditable(int row) {
+ if(row == 2) {
+ return !(widget instanceof FreeButton && ((FreeButton) widget).isCustomStyle());
+ }
+ return true;
+ }
+
+ private String getSizeDisplayName() {
+ Object obj = layout.getConstraints(widget);
+ if (BorderLayout.NORTH.equals(obj) || BorderLayout.SOUTH.equals(obj)) {
+ return Inter.getLocText("Tree-Height");
+ } else if (BorderLayout.WEST.equals(obj) || BorderLayout.EAST.equals(obj)) {
+ return Inter.getLocText("Tree-Width");
+ } else {
+ return StringUtils.EMPTY;
+ }
+ }
+
+ private String getChildPositionDisplayName() {
+ Object obj = layout.getConstraints(widget);
+ //return Inter.getLocText("BorderLayout-" + obj);
+ return obj.toString();
+ }
+
+ private boolean switchWidgets(Object value) {
+ Widget nwidget = layout.getLayoutWidget(value);
+ if (nwidget == null) {
+ layout.removeWidget(widget);
+ XWBorderLayout.add(layout, widget, value);
+ } else {
+ Object constraints = layout.getConstraints(widget);
+ layout.removeWidget(widget);
+ layout.removeWidget(nwidget);
+ XWBorderLayout.add(layout, widget, value);
+ XWBorderLayout.add(layout, nwidget, constraints);
+ }
+ container.convert();
+ //TODO:convert后丢失焦点
+ return true;
+ }
+
+ private int getChildSize() {
+ Object obj = layout.getConstraints(widget);
+ try {
+ Method m = layout.getClass().getDeclaredMethod("get" + obj + "Size");
+ Object v = m.invoke(layout);
+ if (v instanceof Number) {
+ return ((Number) v).intValue();
+ }
+ } catch (Exception ex) {
+ Logger.getLogger(FRBorderLayoutConstraints.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return 0;
+ }
+
+ private boolean setChildSize(Object value) {
+ int v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ Object constraints = layout.getConstraints(widget);
+ try {
+ Method m = layout.getClass().getDeclaredMethod("set" + constraints + "Size", int.class);
+ m.invoke(layout, v);
+ container.recalculateChildrenPreferredSize();
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ private String getChildTitle() {
+ Object obj = layout.getConstraints(widget);
+ try {
+ Method m = layout.getClass().getDeclaredMethod("get" + obj + "Title");
+ return (String) m.invoke(layout);
+ } catch (Exception ex) {
+ Logger.getLogger(FRBorderLayoutConstraints.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ return StringUtils.EMPTY;
+ }
+
+ private boolean setChildTitle(Object value) {
+ Object constraints = layout.getConstraints(widget);
+ try {
+ Method m = layout.getClass().getDeclaredMethod("set" + constraints + "Title",String.class);
+ m.invoke(layout, value);
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraintsRenderer.java b/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraintsRenderer.java
new file mode 100644
index 000000000..cca2a068f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutConstraintsRenderer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.properties;
+
+import java.awt.Component;
+
+import com.fr.design.gui.ilable.UILabel;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FRBorderLayoutConstraintsRenderer extends UILabel implements TableCellRenderer {
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ if (value != null) {
+ this.setText(Inter.getLocText("BorderLayout-" + value));
+ }
+ return this;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutPropertiesGroupModel.java b/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutPropertiesGroupModel.java
new file mode 100644
index 000000000..b6bd87905
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/FRBorderLayoutPropertiesGroupModel.java
@@ -0,0 +1,144 @@
+package com.fr.design.designer.properties;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.widget.editors.BorderLayoutDirectionEditor;
+import com.fr.design.mainframe.widget.editors.ExtendedPropertyEditor;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.mainframe.widget.renderer.PropertyCellRenderer;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.designer.properties.items.Item;
+import com.fr.design.form.layout.FRBorderLayout;
+import com.fr.form.ui.container.WBorderLayout;
+
+public class FRBorderLayoutPropertiesGroupModel implements GroupModel {
+
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor gapEditor;
+ private PropertyCellEditor directionEditor;
+ private PropertyCellRenderer directionRenderer;
+ private WBorderLayout layout;
+ private XWBorderLayout xbl;
+
+ public FRBorderLayoutPropertiesGroupModel(XWBorderLayout xbl) {
+ this.xbl = xbl;
+ this.layout = xbl.toData();
+ renderer = new DefaultTableCellRenderer();
+ gapEditor = new PropertyCellEditor(new IntegerPropertyEditor());
+ final ExtendedPropertyEditor propertyeditor = new BorderLayoutDirectionEditor();
+// propertyeditor.addPropertyChangeListener(new PropertyChangeAdapter() {
+// public void propertyChange(PropertyChangeEvent evt) {
+// Object val = propertyeditor.getValue();
+// if (val instanceof Object[]) {
+// Object[] dirs = (Object[]) val;
+// String[] directions = new String[dirs.length];
+// for (int i=0; i 0) {
+ for (int i = 0; i < widgets.length; i++) {
+ widgets[i].changeVisibleAuthorityState(selectedRoles, widgetVisible.isSelected());
+ }
+ }
+ doAfterAuthority();
+ }
+ };
+
+
+ private ItemListener usableItemListener = new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ String selectedRoles = ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName();
+ if (ComparatorUtils.equals(selectedRoles, Inter.getLocText("FR-Engine_Role"))) {
+ return;
+ }
+ if (selectedRoles == null) {
+ return;
+ }
+ if (widgets != null && widgets.length > 0) {
+ for (int i = 0; i < widgets.length; i++) {
+ widgets[i].changeUsableAuthorityState(selectedRoles, widgetAvailable.isSelected());
+ }
+ }
+ doAfterAuthority();
+ }
+ };
+
+ public FormWidgetAuthorityEditPane(FormDesigner designer) {
+ super(designer);
+ this.designer = designer;
+ widgetAvailable.addItemListener(usableItemListener);
+ widgetVisible.addItemListener(visibleItemListener);
+ }
+
+
+ private void doAfterAuthority() {
+ designer.repaint();
+ HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().fireTargetModified();
+ RolesAlreadyEditedPane.getInstance().refreshDockingView();
+ RolesAlreadyEditedPane.getInstance().setReportAndFSSelectedRoles();
+ RolesAlreadyEditedPane.getInstance().repaint();
+ checkCheckBoxes();
+ }
+
+ /**
+ * 更新类型面板
+ *
+ *
+ * @date 2014-12-21-下午6:19:43
+ *
+ */
+ public void populateType() {
+ type.setText(Inter.getLocText("Widget-Form_Widget_Config"));
+ }
+
+ /**
+ * 更新名称面板
+ *
+ *
+ * @date 2014-12-21-下午7:12:27
+ *
+ */
+ public void populateName() {
+ String nameText = "";
+ if (widgets == null || widgets.length <= 0) {
+ return;
+ }
+ for (int i = 0; i < widgets.length; i++) {
+ nameText += "," + widgets[i].getClass().getSimpleName();
+ }
+ name.setText(nameText.substring(1));
+ }
+
+ /**
+ * 更新checkbox所在的面板
+ *
+ * @return 面板
+ *
+ *
+ * @date 2014-12-21-下午6:19:03
+ *
+ */
+ public JPanel populateCheckPane() {
+ checkPane.add(populateWidgetCheckPane(), BorderLayout.WEST);
+ return checkPane;
+ }
+
+ private JPanel populateWidgetCheckPane() {
+ double f = TableLayout.FILL;
+ double p = TableLayout.PREFERRED;
+ Component[][] components = new Component[][]{
+ new Component[]{new UILabel(Inter.getLocText("FR-Designer_Widget"), SwingConstants.LEFT), widgetVisible, widgetAvailable}
+ };
+ double[] rowSize = {p};
+ double[] columnSize = {p, p, f};
+ int[][] rowCount = {{1, 1, 1}};
+ return TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.VGAP_MEDIUM, LayoutConstants.VGAP_MEDIUM);
+ }
+
+
+ /**
+ * 对单元格区域进行操作时的权限编辑页面
+ */
+ public void populateDetials() {
+ //更新说明要是JWorkBook的话,说明鼠标焦点又改变了
+ HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().setAuthorityMode(true);
+ signelSelection();
+
+ refreshCreator();
+ //如果是布局选中不支持的元素则显示“该元素不支持权限控制”
+ populateType();
+ populateName();
+ checkPane.removeAll();
+ populateCheckPane();
+ checkPane.setBorder(BorderFactory.createEmptyBorder(ALIGNMENT_GAP, 0, 0, 0));
+ checkCheckBoxes();
+ }
+
+ private void checkCheckBoxes() {
+ String selected = ReportAndFSManagePane.getInstance().getRoleTree().getSelectedRoleName();
+ widgetVisible.removeItemListener(visibleItemListener);
+ widgetAvailable.removeItemListener(usableItemListener);
+ populateWidgetButton(selected);
+ widgetVisible.addItemListener(visibleItemListener);
+ widgetAvailable.addItemListener(usableItemListener);
+ }
+
+ private void populateWidgetButton(String selected){
+ if (widgets == null || widgets.length == 0) {
+ return;
+ }
+
+ //选中多个, 界面上只取第一个
+ Widget widget = widgets[0];
+
+ if(widget.isVisible()){
+ widgetVisible.setSelected(!widget.isDoneVisibleAuthority(selected));
+ }else{
+ widgetVisible.setSelected(widget.isVisibleAuthority(selected));
+ }
+
+ if(widget.isEnabled()){
+ widgetAvailable.setSelected(!widget.isDoneUsableAuthority(selected));
+ }else{
+ widgetAvailable.setSelected(widget.isUsableAuthority(selected));
+ }
+ }
+
+
+ //实现单选
+
+ private void signelSelection() {
+ if (HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().isJWorkBook()) {
+ //清工具栏
+ JComponent component = DesignerContext.getDesignerFrame().getToolbarComponent();
+ if (component instanceof AuthorityEditToolBarComponent) {
+ ((AuthorityEditToolBarComponent) component).removeSelection();
+ }
+
+ //清空报表主体的单元格选择
+ HistoryTemplateListPane.getInstance().getCurrentEditingTemplate().removeTemplateSelection();
+ }
+ }
+
+ private void refreshCreator() {
+ int size = designer.getSelectionModel().getSelection().size();
+ widgets = size == 0 ? null : designer.getSelectionModel().getSelection().getSelectedWidgets();
+ }
+
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HVLayoutConstraints.java b/designer_form/src/com/fr/design/designer/properties/HVLayoutConstraints.java
new file mode 100644
index 000000000..2eba72e59
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HVLayoutConstraints.java
@@ -0,0 +1,65 @@
+package com.fr.design.designer.properties;
+
+import java.awt.Component;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.form.ui.FreeButton;
+import com.fr.form.ui.Widget;
+
+public abstract class HVLayoutConstraints implements ConstraintsGroupModel {
+
+ protected DefaultTableCellRenderer renderer;
+ protected LayoutConstraintsEditor editor1;
+ protected PropertyCellEditor editor2;
+ protected Widget widget;
+ protected XLayoutContainer parent;
+
+ public HVLayoutConstraints(XLayoutContainer parent, Component comp) {
+ this.parent = parent;
+ this.widget = ((XWidgetCreator) comp).toData();
+ this.renderer = new DefaultTableCellRenderer();
+
+ this.editor2 = new PropertyCellEditor(new IntegerPropertyEditor());
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Layout_Constraints");
+ }
+
+ @Override
+ public int getRowCount() {
+ return 2;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ return this.renderer;
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ if (row == 0) {
+ return this.editor1;
+ } else {
+ return this.editor2;
+ }
+ }
+
+ @Override
+ public boolean isEditable(int row) {
+ if(row == 1) {
+ return !(widget instanceof FreeButton && ((FreeButton) widget).isCustomStyle());
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentEditor.java b/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentEditor.java
new file mode 100644
index 000000000..0f489902a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentEditor.java
@@ -0,0 +1,10 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.designer.properties.items.HorizontalAlignmentItems;
+
+public class HorizontalAlignmentEditor extends EnumerationEditor {
+
+ public HorizontalAlignmentEditor() {
+ super(new HorizontalAlignmentItems());
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentRenderer.java b/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentRenderer.java
new file mode 100644
index 000000000..dd8c1b3c0
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentRenderer.java
@@ -0,0 +1,10 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.mainframe.widget.renderer.EncoderCellRenderer;
+
+public class HorizontalAlignmentRenderer extends EncoderCellRenderer {
+
+ public HorizontalAlignmentRenderer() {
+ super(new HorizontalAlignmentWrapper());
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentWrapper.java b/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentWrapper.java
new file mode 100644
index 000000000..e03f4d7f9
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HorizontalAlignmentWrapper.java
@@ -0,0 +1,10 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.designer.properties.items.HorizontalAlignmentItems;
+
+public class HorizontalAlignmentWrapper extends ItemWrapper {
+
+ public HorizontalAlignmentWrapper() {
+ super(new HorizontalAlignmentItems());
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HorizontalLayoutConstraints.java b/designer_form/src/com/fr/design/designer/properties/HorizontalLayoutConstraints.java
new file mode 100644
index 000000000..05688f6c5
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HorizontalLayoutConstraints.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.properties;
+
+import java.awt.Component;
+
+import com.fr.general.Inter;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWHorizontalBoxLayout;
+import com.fr.form.ui.container.WHorizontalBoxLayout;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class HorizontalLayoutConstraints extends HVLayoutConstraints{
+ WHorizontalBoxLayout layout;
+
+ public HorizontalLayoutConstraints(XLayoutContainer parent, Component comp) {
+ super(parent, comp);
+ this.layout = ((XWHorizontalBoxLayout) parent).toData();
+ this.editor1 = new LayoutConstraintsEditor(layout);
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("Layout-Index");
+ default:
+ return Inter.getLocText("Tree-Width");
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return layout.getWidgetIndex(widget) + 1;
+ default:
+ return layout.getWidthAtWidget(widget);
+ }
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 1) {
+ XWHorizontalBoxLayout wLayout = (XWHorizontalBoxLayout) parent;
+ switch (row) {
+ case 0:
+ layout.setWidgetIndex(widget, value == null ? 0 : (((Number) value).intValue() - 1));
+ wLayout.convert();
+ //TODO:
+ return true;
+ default:
+ layout.setWidthAtWidget(widget, value == null ? 0 : ((Number) value).intValue());
+ wLayout.recalculateChildrenPreferredSize();
+ return true;
+ }
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HorizontalLayoutPropertiesGroupModel.java b/designer_form/src/com/fr/design/designer/properties/HorizontalLayoutPropertiesGroupModel.java
new file mode 100644
index 000000000..5da6026d6
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HorizontalLayoutPropertiesGroupModel.java
@@ -0,0 +1,127 @@
+package com.fr.design.designer.properties;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.designer.creator.XWHorizontalBoxLayout;
+import com.fr.design.form.layout.FRHorizontalLayout;
+import com.fr.form.ui.container.WHorizontalBoxLayout;
+
+/**
+ * 流式布局的属性组
+ * @author richer
+ * @since 6.5.3
+ */
+public class HorizontalLayoutPropertiesGroupModel implements GroupModel {
+
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor editor;
+ private HorizontalAlignmentRenderer alignmentRenderer;
+ private HorizontalAlignmentEditor alignmentEditor;
+ private WHorizontalBoxLayout layout;
+ private XWHorizontalBoxLayout wLayout;
+
+ public HorizontalLayoutPropertiesGroupModel(XWHorizontalBoxLayout container) {
+ wLayout = container;
+ this.layout = container.toData();
+ renderer = new DefaultTableCellRenderer();
+ editor = new PropertyCellEditor(new IntegerPropertyEditor());
+ alignmentRenderer = new HorizontalAlignmentRenderer();
+ alignmentEditor = new HorizontalAlignmentEditor();
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Layout-HBox");
+ }
+
+ @Override
+ public int getRowCount() {
+ return 3;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ switch (row) {
+ case 0:
+ return renderer;
+ case 1:
+ return renderer;
+ default:
+ return alignmentRenderer;
+ }
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ switch (row) {
+ case 0:
+ return editor;
+ case 1:
+ return editor;
+ default:
+ return alignmentEditor;
+ }
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("Hgap");
+ case 1:
+ return Inter.getLocText("Vgap");
+ default:
+ return Inter.getLocText("Alignment");
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return layout.getHgap();
+ case 1:
+ return layout.getVgap();
+ default:
+ return layout.getAlignment();
+ }
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 0) {
+ return false;
+ } else {
+ int v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ switch (row) {
+ case 0:
+ layout.setHgap(v);
+ ((FRHorizontalLayout)wLayout.getLayout()).setHgap(v);
+ return true;
+ case 1:
+ layout.setVgap(v);
+ ((FRHorizontalLayout)wLayout.getLayout()).setVgap(v);
+ return true;
+ case 2:
+ layout.setAlignment(v);
+ ((FRHorizontalLayout)wLayout.getLayout()).setAlignment(v);
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public boolean isEditable(int row) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/HorizontalSplitProperties.java b/designer_form/src/com/fr/design/designer/properties/HorizontalSplitProperties.java
new file mode 100644
index 000000000..c2c26ff71
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/HorizontalSplitProperties.java
@@ -0,0 +1,15 @@
+package com.fr.design.designer.properties;
+
+import com.fr.general.Inter;
+import com.fr.form.ui.container.WSplitLayout;
+
+public class HorizontalSplitProperties extends VerticalSplitProperties {
+ public HorizontalSplitProperties(WSplitLayout wLayout) {
+ super(wLayout);
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Horizontal-Split_Layout");
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/IconCellEditor.java b/designer_form/src/com/fr/design/designer/properties/IconCellEditor.java
new file mode 100644
index 000000000..00cc1d908
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/IconCellEditor.java
@@ -0,0 +1,24 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.mainframe.widget.accessibles.AccessibleIconEditor;
+
+public class IconCellEditor extends DelegateEditor {
+
+ public IconCellEditor() {
+ final AccessibleIconEditor iconEditor = new AccessibleIconEditor();
+ editorComponent = iconEditor;
+ delegate = new EditorDelegate() {
+
+ @Override
+ public void setValue(Object value) {
+ iconEditor.setValue(value);
+ }
+
+ @Override
+ public Object getCellEditorValue() {
+ return iconEditor.getValue();
+ }
+ };
+ iconEditor.addChangeListener(delegate);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/ItemWrapper.java b/designer_form/src/com/fr/design/designer/properties/ItemWrapper.java
new file mode 100644
index 000000000..746d75ea2
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/ItemWrapper.java
@@ -0,0 +1,48 @@
+package com.fr.design.designer.properties;
+
+import com.fr.design.Exception.ValidationException;
+import com.fr.design.designer.properties.items.Item;
+import com.fr.design.designer.properties.items.ItemProvider;
+
+public class ItemWrapper implements Encoder, Decoder {
+
+ private Item[] items;
+
+ public ItemWrapper(ItemProvider provider) {
+ this(provider.getItems());
+ }
+
+ public ItemWrapper(Item[] items) {
+ this.items = items;
+ }
+
+ @Override
+ public Object decode(String txt) {
+ for (Item item : items) {
+ if (txt.equals(item.getName())) {
+ return item.getValue();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String encode(Object v) {
+ for (Item item : items) {
+ if (item.getValue().equals(v)) {
+ return item.getName();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void validate(String txt) throws ValidationException {
+ for (Item item : items) {
+ if (txt.equals(item.getName())) {
+ return;
+ }
+ }
+ throw new ValidationException("No such element:" + txt);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/LayoutConstraintsEditor.java b/designer_form/src/com/fr/design/designer/properties/LayoutConstraintsEditor.java
new file mode 100644
index 000000000..20bbb2f4e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/LayoutConstraintsEditor.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.properties;
+
+import com.fr.design.designer.properties.items.LayoutIndexItems;
+import com.fr.form.ui.container.WLayout;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class LayoutConstraintsEditor extends EnumerationEditor {
+ public LayoutConstraintsEditor(WLayout layout) {
+ super(new LayoutIndexItems(layout, true));
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/MultiSelectionBoundsModel.java b/designer_form/src/com/fr/design/designer/properties/MultiSelectionBoundsModel.java
new file mode 100644
index 000000000..97ab0407f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/MultiSelectionBoundsModel.java
@@ -0,0 +1,121 @@
+package com.fr.design.designer.properties;
+
+import java.awt.Rectangle;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormSelection;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.designer.beans.ConstraintsGroupModel;
+
+/**
+ * 多个组件时候的属性组
+ *
+ */
+public class MultiSelectionBoundsModel implements ConstraintsGroupModel {
+
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor editor;
+ private FormDesigner designer;
+
+ public MultiSelectionBoundsModel(FormDesigner designer) {
+ this.designer = designer;
+ renderer = new DefaultTableCellRenderer();
+ editor = new PropertyCellEditor(new IntegerPropertyEditor());
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ return editor;
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Form-Component_Bounds");
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ return renderer;
+ }
+
+ @Override
+ public int getRowCount() {
+ return 4;
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("X-Coordinate");
+ case 1:
+ return Inter.getLocText("Y-Coordinate");
+ case 2:
+ return Inter.getLocText("Tree-Width");
+ default:
+ return Inter.getLocText("Tree-Height");
+ }
+ } else {
+ Rectangle rec = designer.getSelectionModel().getSelection().getSelctionBounds();
+ switch (row) {
+ case 0:
+ return rec.x;
+ case 1:
+ return rec.y;
+ case 2:
+ return rec.width;
+ default:
+ return rec.height;
+ }
+ }
+ }
+
+ @Override
+ public boolean isEditable(int row) {
+ return true;
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 1) {
+ FormSelection selection = designer.getSelectionModel().getSelection();
+ int v = value == null ? 0 : ((Number) value).intValue();
+ Rectangle bounds = selection.getSelctionBounds();
+ switch (row) {
+ case 0:
+ if (bounds.x == v)
+ return false;
+ bounds.x = v;
+ break;
+ case 1:
+ if (bounds.y == v)
+ return false;
+ bounds.y = v;
+ break;
+ case 2:
+ if (bounds.width == v)
+ return false;
+ bounds.width = v;
+ break;
+ case 3:
+ if (bounds.height == v)
+ return false;
+ bounds.height = v;
+ break;
+ }
+ selection.backupBounds();
+ selection.setSelectionBounds(bounds, designer);
+ selection.fixCreator(designer);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/NameWithListeners.java b/designer_form/src/com/fr/design/designer/properties/NameWithListeners.java
new file mode 100644
index 000000000..4d890c947
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/NameWithListeners.java
@@ -0,0 +1,33 @@
+package com.fr.design.designer.properties;
+
+import com.fr.general.ComparatorUtils;
+import com.fr.form.event.Listener;
+
+public class NameWithListeners {
+
+ private String name;
+ private Listener[] ls;
+
+ public NameWithListeners(String name, Listener[] ls) {
+ this.name = name;
+ this.ls = ls == null ? new Listener[0] : ls;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public Listener[] getListeners() {
+ return this.ls;
+ }
+
+ public int getCountOfListeners4ThisName() {
+ int count = 0;
+ for (int i = 0; i < ls.length; i++) {
+ if (ComparatorUtils.equals(name, ls[i].getEventName())) {
+ count++;
+ }
+ }
+ return count;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/VerticalBoxProperties.java b/designer_form/src/com/fr/design/designer/properties/VerticalBoxProperties.java
new file mode 100644
index 000000000..6a344541a
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/VerticalBoxProperties.java
@@ -0,0 +1,102 @@
+package com.fr.design.designer.properties;
+
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.designer.creator.XWVerticalBoxLayout;
+import com.fr.design.form.layout.FRVerticalLayout;
+import com.fr.form.ui.container.WVerticalBoxLayout;
+
+public class VerticalBoxProperties implements GroupModel {
+
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor editor;
+ private WVerticalBoxLayout layout;
+ private XWVerticalBoxLayout wLayout;
+
+ public VerticalBoxProperties(XWVerticalBoxLayout container) {
+ wLayout = container;
+ this.layout = container.toData();
+ renderer = new DefaultTableCellRenderer();
+ editor = new PropertyCellEditor(new IntegerPropertyEditor());
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("VerticalBoxLayout");
+ }
+
+ @Override
+ public int getRowCount() {
+ return 2;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ return renderer;
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ return editor;
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("Hgap");
+ case 1:
+ return Inter.getLocText("Vgap");
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return layout.getHgap();
+ case 1:
+ return layout.getVgap();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 0) {
+ return false;
+ } else {
+ switch (row) {
+ case 0:
+ int v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ layout.setHgap(v);
+ ((FRVerticalLayout)wLayout.getLayout()).setHgap(v);
+ return true;
+ case 1:
+ v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ layout.setVgap(v);
+ ((FRVerticalLayout)wLayout.getLayout()).setVgap(v);
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public boolean isEditable(int row) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/VerticalLayoutConstraints.java b/designer_form/src/com/fr/design/designer/properties/VerticalLayoutConstraints.java
new file mode 100644
index 000000000..f0ed8e731
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/VerticalLayoutConstraints.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.properties;
+
+import java.awt.Component;
+
+import com.fr.general.Inter;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWVerticalBoxLayout;
+import com.fr.form.ui.container.WVerticalBoxLayout;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class VerticalLayoutConstraints extends HVLayoutConstraints {
+ WVerticalBoxLayout layout;
+
+ public VerticalLayoutConstraints(XLayoutContainer parent, Component comp) {
+ super(parent, comp);
+ this.layout = ((XWVerticalBoxLayout) parent).toData();
+ this.editor1 = new LayoutConstraintsEditor(layout);
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("Layout-Index");
+ default:
+ return Inter.getLocText("Tree-Height");
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return layout.getWidgetIndex(widget) + 1;
+ default:
+ return layout.getHeightAtWidget(widget);
+ }
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 1) {
+ XWVerticalBoxLayout wLayout = (XWVerticalBoxLayout) parent;
+ switch (row) {
+ case 0:
+ layout.setWidgetIndex(widget, value == null ? 0 : (((Number) value).intValue() - 1));
+ wLayout.convert();
+ //TODO
+ return true;
+ default:
+ layout.setHeightAtWidget(widget, value == null ? 0 : ((Number) value).intValue());
+ wLayout.recalculateChildrenPreferredSize();
+ return true;
+ }
+ }
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/VerticalSplitProperties.java b/designer_form/src/com/fr/design/designer/properties/VerticalSplitProperties.java
new file mode 100644
index 000000000..73f288264
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/VerticalSplitProperties.java
@@ -0,0 +1,105 @@
+package com.fr.design.designer.properties;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.general.Inter;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.widget.editors.DoubleEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.form.ui.container.WSplitLayout;
+
+public class VerticalSplitProperties implements GroupModel {
+ private DefaultTableCellRenderer renderer;
+ private PropertyCellEditor editor;
+ private WSplitLayout layout;
+
+ public VerticalSplitProperties(WSplitLayout wLayout) {
+ this.layout = wLayout;
+ renderer = new DefaultTableCellRenderer();
+ editor = new PropertyCellEditor(new DoubleEditor());
+ }
+
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText("Vertical-Split_Layout");
+ }
+
+ @Override
+ public int getRowCount() {
+ return 3;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ return renderer;
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ return editor;
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ switch (row) {
+ case 0:
+ return Inter.getLocText("Ratio");
+ case 1:
+ return Inter.getLocText("Hgap");
+ case 2:
+ return Inter.getLocText("Vgap");
+ }
+ } else {
+ switch (row) {
+ case 0:
+ return layout.getRatio();
+ case 1:
+ return layout.getHgap();
+ case 2:
+ return layout.getVgap();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 0) {
+ return false;
+ } else {
+ switch (row) {
+ case 0:
+ double r = 0.5;
+ if (value != null) {
+ r = ((Number) value).doubleValue();
+ }
+ layout.setRatio(r);
+ return true;
+ case 1:
+ int v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ layout.setHgap(v);
+ return true;
+ case 2:
+ v = 0;
+ if (value != null) {
+ v = ((Number) value).intValue();
+ }
+ layout.setVgap(v);
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public boolean isEditable(int row) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/WidgetPropertyTable.java b/designer_form/src/com/fr/design/designer/properties/WidgetPropertyTable.java
new file mode 100644
index 000000000..9f53dddcc
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/WidgetPropertyTable.java
@@ -0,0 +1,119 @@
+package com.fr.design.designer.properties;
+
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.JTable;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableModel;
+
+import com.fr.design.beans.GroupModel;
+import com.fr.design.gui.itable.AbstractPropertyTable;
+import com.fr.design.gui.itable.PropertyGroup;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.LayoutAdapter;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWFitLayout;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.design.designer.creator.cardlayout.XWCardLayout;
+
+public class WidgetPropertyTable extends AbstractPropertyTable {
+
+ private FormDesigner designer;
+
+ public WidgetPropertyTable(FormDesigner designer) {
+ super();
+ setDesigner(designer);
+ }
+
+ public static ArrayList getCreatorPropertyGroup(FormDesigner designer, XCreator source) {
+ ArrayList groups = new ArrayList();
+ ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, source);
+ ArrayList groupModels = adapter.getXCreatorPropertyModel();
+ for (GroupModel model : groupModels) {
+ groups.add(new PropertyGroup(model));
+ }
+ XLayoutContainer container = XCreatorUtils.getParentXLayoutContainer(source);
+ if (source.acceptType(XWFitLayout.class) || source.acceptType(XWParameterLayout.class)) {
+ container = null;
+ }
+ if (container != null && !(source instanceof XWCardLayout)) {
+ LayoutAdapter containerAdapter = container.getLayoutAdapter();
+ GroupModel m = containerAdapter.getLayoutConstraints(source);
+ if (m != null) {
+ groups.add(new PropertyGroup(m));
+ }
+ }
+ if (source instanceof XLayoutContainer) {
+ LayoutAdapter layoutAdapter = ((XLayoutContainer)source).getLayoutAdapter();
+ if(layoutAdapter != null){
+ GroupModel m = layoutAdapter.getLayoutProperties();
+ if (m != null) {
+ groups.add(new PropertyGroup(m));
+ }
+ }
+
+ }
+ return groups;
+ }
+
+ /**
+ * 初始化属性表组
+ * @param source 控件
+ */
+ public void initPropertyGroups(Object source) {
+ int size = designer.getSelectionModel().getSelection().size();
+ if (size == 0 || size == 1) {
+ XCreator creator = size == 0 ? designer.getRootComponent() : designer.getSelectionModel().getSelection()
+ .getSelectedCreator();
+ if (designer.isRoot(creator)) {
+ groups = designer.getDesignerMode().createRootDesignerPropertyGroup();
+ } else {
+ groups = getCreatorPropertyGroup(designer, creator);
+ }
+ } else {
+ groups = new ArrayList();
+ GroupModel multiModel = new MultiSelectionBoundsModel(designer);
+ groups.add(new PropertyGroup(multiModel));
+ }
+ TableModel model = new BeanTableModel();
+ setModel(model);
+ this.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+ TableColumn tc = this.getColumn(this.getColumnName(0));
+ tc.setPreferredWidth(30);
+ this.repaint();
+ }
+
+ private void setDesigner(FormDesigner designer) {
+ this.designer = designer;
+ }
+
+
+ /**
+ * 单元格tooltip
+ * 属性名悬浮提示
+ *
+ * @param 鼠标点击事件
+ * @return 单元格tooltip
+ */
+ public String getToolTipText(MouseEvent event) {
+ int row = WidgetPropertyTable.super.rowAtPoint(event.getPoint());
+ int column = WidgetPropertyTable.super.columnAtPoint(event.getPoint());
+ if(row != -1 && column == 0){
+ return String.valueOf(this.getValueAt(row, column));
+ }
+ return null;
+ }
+
+ /**
+ * 待说明
+ */
+ public void firePropertyEdit() {
+ designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/FRBorderConstraintsItems.java b/designer_form/src/com/fr/design/designer/properties/items/FRBorderConstraintsItems.java
new file mode 100644
index 000000000..9fef88199
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/FRBorderConstraintsItems.java
@@ -0,0 +1,37 @@
+package com.fr.design.designer.properties.items;
+
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+import com.fr.form.ui.container.WBorderLayout;
+
+public class FRBorderConstraintsItems implements ItemProvider {
+
+ private Item[] VALUE_ITEMS;
+
+ public FRBorderConstraintsItems(String[] directions) {
+ Item[] item = createItems(directions);
+ VALUE_ITEMS = (Item[]) ArrayUtils.add(item, new Item(Inter.getLocText("BorderLayout-Center"),
+ WBorderLayout.CENTER));
+ }
+
+ @Override
+ public Item[] getItems() {
+ return VALUE_ITEMS;
+ }
+
+ public static Item[] createItems(String[] directions) {
+ Item[] items = new Item[directions.length];
+ for (int i = 0; i < directions.length; i++) {
+ if (WBorderLayout.NORTH == directions[i]) {
+ items[i] = new Item(Inter.getLocText("BorderLayout-North"), WBorderLayout.NORTH);
+ } else if (WBorderLayout.SOUTH == directions[i]) {
+ items[i] = new Item(Inter.getLocText("BorderLayout-South"), WBorderLayout.SOUTH);
+ } else if (WBorderLayout.WEST == directions[i]) {
+ items[i] = new Item(Inter.getLocText("BorderLayout-West"), WBorderLayout.WEST);
+ } else if (WBorderLayout.EAST == directions[i]) {
+ items[i] = new Item(Inter.getLocText("BorderLayout-East"), WBorderLayout.EAST);
+ }
+ }
+ return items;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/FRFitConstraintsItems.java b/designer_form/src/com/fr/design/designer/properties/items/FRFitConstraintsItems.java
new file mode 100644
index 000000000..6ae6f22c8
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/FRFitConstraintsItems.java
@@ -0,0 +1,23 @@
+/**
+ *
+ */
+package com.fr.design.designer.properties.items;
+
+import com.fr.form.ui.container.WFitLayout;
+import com.fr.general.Inter;
+
+/**
+ * @author jim
+ * @date 2014-7-31
+ */
+public class FRFitConstraintsItems implements ItemProvider{
+
+ public static final Item[] ITEMS = new Item[] {
+ new Item(Inter.getLocText("Adaptive_Full_Area"), WFitLayout.STATE_FULL),
+ new Item(Inter.getLocText("Adaptive_Original_Scale"), WFitLayout.STATE_ORIGIN)};
+
+ public Item[] getItems() {
+ return ITEMS;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/HorizontalAlignmentItems.java b/designer_form/src/com/fr/design/designer/properties/items/HorizontalAlignmentItems.java
new file mode 100644
index 000000000..a0b06380f
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/HorizontalAlignmentItems.java
@@ -0,0 +1,19 @@
+package com.fr.design.designer.properties.items;
+
+import java.awt.FlowLayout;
+
+import com.fr.general.Inter;
+
+public class HorizontalAlignmentItems implements ItemProvider {
+
+ private static Item[] VALUE_ITEMS = {
+ new Item(Inter.getLocText("Left"), FlowLayout.LEFT),
+ new Item(Inter.getLocText("Right"), FlowLayout.RIGHT),
+ new Item(Inter.getLocText("Center"), FlowLayout.CENTER)
+ };
+
+ @Override
+ public Item[] getItems() {
+ return VALUE_ITEMS;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/Item.java b/designer_form/src/com/fr/design/designer/properties/items/Item.java
new file mode 100644
index 000000000..31ae4a070
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/Item.java
@@ -0,0 +1,47 @@
+package com.fr.design.designer.properties.items;
+
+public class Item {
+
+ private Object value;
+ private String name;
+
+ public Item(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (o instanceof Item) {
+ Item a = (Item) o;
+ Object av = a.getValue();
+ if (value == null) {
+ return av == null;
+ } else {
+ if (av == null) {
+ return false;
+ } else {
+ return value.equals(av);
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/ItemProvider.java b/designer_form/src/com/fr/design/designer/properties/items/ItemProvider.java
new file mode 100644
index 000000000..64838361e
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/ItemProvider.java
@@ -0,0 +1,7 @@
+package com.fr.design.designer.properties.items;
+
+
+public interface ItemProvider {
+
+ Item[] getItems();
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/LabelHorizontalAlignmentItems.java b/designer_form/src/com/fr/design/designer/properties/items/LabelHorizontalAlignmentItems.java
new file mode 100644
index 000000000..852f3b1ad
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/LabelHorizontalAlignmentItems.java
@@ -0,0 +1,19 @@
+package com.fr.design.designer.properties.items;
+
+import javax.swing.SwingConstants;
+
+import com.fr.general.Inter;
+
+public class LabelHorizontalAlignmentItems implements ItemProvider {
+
+ private static Item[] VALUE_ITEMS = {
+ new Item(Inter.getLocText("Left"), SwingConstants.LEFT),
+ new Item(Inter.getLocText("Right"), SwingConstants.RIGHT),
+ new Item(Inter.getLocText("Center"), SwingConstants.CENTER)
+ };
+
+ @Override
+ public Item[] getItems() {
+ return VALUE_ITEMS;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/LayoutIndexItems.java b/designer_form/src/com/fr/design/designer/properties/items/LayoutIndexItems.java
new file mode 100644
index 000000000..4e8592307
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/LayoutIndexItems.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.designer.properties.items;
+
+import com.fr.base.Utils;
+import com.fr.form.ui.container.WLayout;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class LayoutIndexItems implements ItemProvider {
+
+ private WLayout layout;
+ private boolean chooseIndexNotName;
+
+ public LayoutIndexItems(WLayout layout, boolean chooseIndexNotName) {
+ this.layout = layout;
+ this.chooseIndexNotName = chooseIndexNotName;
+ }
+
+ @Override
+ public Item[] getItems() {
+ int count = layout.getWidgetCount();
+ Item[] items = new Item[count];
+ for (int i = 0; i < count; i ++) {
+ if (chooseIndexNotName) {
+ items[i] = new Item(Utils.doubleToString(i + 1), i + 1);
+ } else {
+ items[i] = new Item(layout.getWidget(i).getWidgetName(), i);
+ }
+ }
+ return items;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/UnderlineItems.java b/designer_form/src/com/fr/design/designer/properties/items/UnderlineItems.java
new file mode 100644
index 000000000..2edad98da
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/UnderlineItems.java
@@ -0,0 +1,17 @@
+package com.fr.design.designer.properties.items;
+
+import com.fr.general.Inter;
+
+public class UnderlineItems implements ItemProvider {
+
+ private static Item[] VALUE_ITEMS = {
+ new Item(Inter.getLocText("DataFunction-None"), ""),
+ new Item(Inter.getLocText("StyleAlignment-Top"), "overline"),
+ new Item(Inter.getLocText("Center"), "line-through"),
+ new Item(Inter.getLocText("StyleAlignment-Bottom"), "underline")};
+
+ @Override
+ public Item[] getItems() {
+ return VALUE_ITEMS;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/properties/items/WidgetDisplayPositionItems.java b/designer_form/src/com/fr/design/designer/properties/items/WidgetDisplayPositionItems.java
new file mode 100644
index 000000000..bd02c56ee
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/properties/items/WidgetDisplayPositionItems.java
@@ -0,0 +1,24 @@
+package com.fr.design.designer.properties.items;
+
+import com.fr.general.Inter;
+import com.fr.report.stable.FormConstants;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: zx
+ * Date: 14-8-13
+ * Time: 下午2:13
+ */
+public class WidgetDisplayPositionItems implements ItemProvider{
+ //这里为了和web端一致,只好设置成012了
+ private static Item[] VALUE_ITEMS = {
+ new Item(Inter.getLocText("StyleAlignment-Left"), FormConstants.LEFTPOSITION),
+ new Item(Inter.getLocText("Center"), FormConstants.CENTERPOSITION),
+ new Item(Inter.getLocText("StyleAlignment-Right"), FormConstants.RIGHTPOSITION)
+ };
+
+ @Override
+ public Item[] getItems() {
+ return VALUE_ITEMS;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/treeview/ComponentTreeCellRenderer.java b/designer_form/src/com/fr/design/designer/treeview/ComponentTreeCellRenderer.java
new file mode 100644
index 000000000..103b372bc
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/treeview/ComponentTreeCellRenderer.java
@@ -0,0 +1,57 @@
+package com.fr.design.designer.treeview;
+
+import java.awt.Component;
+import java.awt.Dimension;
+
+import javax.swing.Icon;
+
+import com.fr.design.constants.UIConstants;
+import com.fr.design.gui.ilable.UILabel;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+
+public class ComponentTreeCellRenderer extends DefaultTreeCellRenderer {
+
+ public ComponentTreeCellRenderer() {
+ }
+
+ @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 (value instanceof XCreator) {
+ setText(((XCreator) value).toData().getWidgetName());
+ Icon icon = XCreatorUtils.getCreatorIcon((XCreator) value);
+ if (icon != null) {
+ setIcon(icon);
+ }
+ }
+ 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);
+ return this;
+ }
+
+ @Override
+ public Icon getClosedIcon() {
+ return getIcon();
+ }
+
+ @Override
+ public Icon getLeafIcon() {
+ return getIcon();
+ }
+
+ @Override
+ public Icon getOpenIcon() {
+ return getIcon();
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/designer/treeview/ComponentTreeModel.java b/designer_form/src/com/fr/design/designer/treeview/ComponentTreeModel.java
new file mode 100644
index 000000000..f189bcada
--- /dev/null
+++ b/designer_form/src/com/fr/design/designer/treeview/ComponentTreeModel.java
@@ -0,0 +1,138 @@
+package com.fr.design.designer.treeview;
+
+import java.awt.Component;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+import com.fr.base.FRContext;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWidgetCreator;
+import com.fr.form.ui.Widget;
+
+public class ComponentTreeModel implements TreeModel {
+
+ private ArrayList listeners = new ArrayList();
+ private Component root;
+ private FormDesigner designer;
+
+ public ComponentTreeModel(FormDesigner designer, Component root) {
+ this.designer = designer;
+ this.root = root;
+ }
+
+ @Override
+ public Object getRoot() {
+ return root;
+ }
+
+ @Override
+ public Object getChild(Object parent, int index) {
+ if (parent != null && parent instanceof XLayoutContainer) {
+ XLayoutContainer xlayout = (XLayoutContainer) parent;
+ XCreator creator = xlayout.getXCreator(index);
+ return creator.getXCreator();
+ }
+ return null;
+ }
+ /**
+ * 设置根节点
+ *
+ * @param root 根节点
+ */
+ public void setRoot(Component root){
+ this.root=root;
+ }
+
+ @Override
+ public int getChildCount(Object parent) {
+ if (parent != null && parent instanceof XLayoutContainer) {
+ XLayoutContainer xlayout = (XLayoutContainer) parent;
+ return xlayout.getXCreatorCount();
+ }
+ return 0;
+ }
+
+ /**
+ * 是否为叶子节点
+ * @param node 对象
+ * @return 是则返回true
+ */
+ @Override
+ public boolean isLeaf(Object node) {
+ if (node != null && node instanceof XCreator) {
+ return ((XCreator) node).isComponentTreeLeaf();
+ }
+ return true;
+ }
+
+ /**
+ * 树节点值改变
+ * @param path 树结构路径
+ * @param newValue 新值
+ */
+ @Override
+ public void valueForPathChanged(TreePath path, Object newValue) {
+ Object lastObject = path.getLastPathComponent();
+ if (lastObject != newValue) {
+ if (newValue instanceof String) {
+ // Change varaible name
+ XCreator component = (XCreator) lastObject;
+ Widget wgt = ((XWidgetCreator)component).toData();
+ wgt.setWidgetName((String)newValue);
+ designer.getEditListenerTable().fireCreatorModified(component, DesignerEvent.CREATOR_EDITED);
+ }
+ TreeModelEvent event = new TreeModelEvent(this, path.getPath());
+ fireEvent("treeNodesChanged", event);
+ }
+ }
+
+ @Override
+ public int getIndexOfChild(Object parent, Object child) {
+ if (parent != null && parent instanceof XLayoutContainer) {
+ return ((XLayoutContainer)parent).getIndexOfChild(child);
+ }
+ return -1;
+ }
+
+ /**
+ * 添加树事件
+ * @param l 事件
+ */
+ @Override
+ public void addTreeModelListener(TreeModelListener l) {
+ if (!listeners.contains(l)) {
+ listeners.add(l);
+ }
+ }
+
+ /**
+ * 删除树事件
+ * @param l 事件
+ */
+ @Override
+ public void removeTreeModelListener(TreeModelListener l) {
+ if (listeners.contains(l)) {
+ listeners.remove(l);
+ }
+ }
+
+ protected void fireEvent(String eventName, TreeModelEvent evt) {
+ try {
+ Method m = TreeModelListener.class.getMethod(eventName, TreeModelEvent.class);
+
+ for (TreeModelListener listener : listeners) {
+ m.invoke(listener, evt);
+ }
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/images/add.png b/designer_form/src/com/fr/design/form/images/add.png
new file mode 100644
index 000000000..d2eea63d4
Binary files /dev/null and b/designer_form/src/com/fr/design/form/images/add.png differ
diff --git a/designer_form/src/com/fr/design/form/images/delete_hover&click.png b/designer_form/src/com/fr/design/form/images/delete_hover&click.png
new file mode 100644
index 000000000..b62e65679
Binary files /dev/null and b/designer_form/src/com/fr/design/form/images/delete_hover&click.png differ
diff --git a/designer_form/src/com/fr/design/form/images/delete_normal.png b/designer_form/src/com/fr/design/form/images/delete_normal.png
new file mode 100644
index 000000000..ff002c64d
Binary files /dev/null and b/designer_form/src/com/fr/design/form/images/delete_normal.png differ
diff --git a/designer_form/src/com/fr/design/form/javascript/FormEmailPane.java b/designer_form/src/com/fr/design/form/javascript/FormEmailPane.java
new file mode 100644
index 000000000..1230279c1
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/javascript/FormEmailPane.java
@@ -0,0 +1,34 @@
+package com.fr.design.form.javascript;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.gui.itextfield.UITextField;
+import com.fr.design.javascript.EmailPane;
+import com.fr.design.layout.TableLayoutHelper;
+import com.fr.general.Inter;
+
+/**
+ * 表单的邮件pane
+ *
+ * @author jim
+ *
+ */
+public class FormEmailPane extends EmailPane{
+
+ @Override
+ protected void initCenterPane(UILabel mainTextLabel, JScrollPane scrollPane, double fill, double preferred) {
+ double[] rowSize = { preferred, preferred, preferred, preferred, preferred, fill, preferred};
+ double[] columnSize = { preferred, fill};
+ centerPane = TableLayoutHelper.createCommonTableLayoutPane(new JComponent[][]{
+ {new UILabel(), tipsPane1},
+ createLinePane(Inter.getLocText("HJS-Mail_to"), maitoEditor = new UITextField()),
+ createLinePane(Inter.getLocText("HJS-CC_to"), ccEditor = new UITextField()),
+ createLinePane(Inter.getLocText("EmailPane-BCC"), bccEditor = new UITextField()),
+ createLinePane(Inter.getLocText("EmailPane-mailSubject"), titleEditor = new UITextField()),
+ {mainTextLabel, scrollPane},
+ {new UILabel(), tipsPane2}},rowSize, columnSize, 7);
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRAbsoluteLayout.java b/designer_form/src/com/fr/design/form/layout/FRAbsoluteLayout.java
new file mode 100644
index 000000000..c27e76408
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRAbsoluteLayout.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+
+/**
+ * @author richer
+ * @since 6.5.4 创建于2011-5-25
+ */
+public class FRAbsoluteLayout implements FRLayoutManager {
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+
+ }
+
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ return new Dimension(10, 10);
+ }
+
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ return new Dimension(10, 10);
+ }
+
+ @Override
+ public void layoutContainer(Container parent) {
+
+ }
+
+ @Override
+ public boolean isResizable() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRBorderLayout.java b/designer_form/src/com/fr/design/form/layout/FRBorderLayout.java
new file mode 100644
index 000000000..8bf2504ba
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRBorderLayout.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+import java.awt.BorderLayout;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FRBorderLayout extends BorderLayout implements FRLayoutManager {
+
+ public FRBorderLayout() {
+ this(0, 0);
+ }
+
+ public FRBorderLayout(int hgap, int vgap) {
+ super(hgap, vgap);
+ }
+
+ @Override
+ public boolean isResizable() {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRCardLayout.java b/designer_form/src/com/fr/design/form/layout/FRCardLayout.java
new file mode 100644
index 000000000..82557c988
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRCardLayout.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+import java.awt.CardLayout;
+import java.awt.Container;
+
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.form.ui.container.WLayout;
+import com.fr.general.ComparatorUtils;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FRCardLayout extends CardLayout implements FRLayoutManager{
+
+ public FRCardLayout() {
+ super();
+ }
+
+ public FRCardLayout(int hgap, int vgap) {
+ super(hgap, vgap);
+ }
+
+ /**
+ * 是否可重置大小
+ *
+ * @return 是否可重置大小
+ *
+ */
+ @Override
+ public boolean isResizable() {
+ return false;
+ }
+
+ /**
+ * 展现当前card
+ *
+ * @param parent 父容器
+ * @param name 当前card
+ *
+ */
+ public void show(Container parent, String name) {
+ synchronized (parent.getTreeLock()) {
+ int ncomponents = parent.getComponentCount();
+ for (int i = 0; i < ncomponents; i++) {
+ XLayoutContainer container = (XLayoutContainer) parent.getComponent(i);
+ WLayout layout = container.toData();
+ if (ComparatorUtils.equals(layout.getWidgetName(), name)) {
+ container.setVisible(true);
+ continue;
+ }
+ container.setVisible(false);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRFitLayout.java b/designer_form/src/com/fr/design/form/layout/FRFitLayout.java
new file mode 100644
index 000000000..2f65b59df
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRFitLayout.java
@@ -0,0 +1,139 @@
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Point;
+import java.awt.Rectangle;
+
+import com.fr.form.ui.container.WLayout;
+
+public class FRFitLayout implements FRLayoutManager, LayoutManager{
+
+ private int interval;
+ // 上次的布局内边距
+ private Insets lastInset;
+
+ public FRFitLayout() {
+ this(0);
+ }
+
+ public FRFitLayout(int interval) {
+ this.interval = interval;
+ }
+
+ public void setInterVal(int val) {
+ this.interval = val;
+ }
+
+ /**
+ * 增加组件
+ * @param name 名字
+ * @param comp 组件
+ */
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+
+ }
+
+ /**
+ * 移除组件
+ * @param comp 组件
+ */
+ @Override
+ public void removeLayoutComponent(Component comp) {
+
+ }
+
+ /**
+ * 最优大小
+ * @param parent 父容器
+ * @return 默认大小
+ */
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ return new Dimension(WLayout.DEFAULT_WIDTH, WLayout.DEFAULT_HEIGHT);
+ }
+
+ /**
+ * 最小大小
+ * @param parent 父容器
+ * @return 默认初始大小
+ */
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ return new Dimension(WLayout.DEFAULT_WIDTH, WLayout.MIN_HEIGHT);
+ }
+
+ /**
+ * 布局刷新
+ * @param target 容器
+ */
+ @Override
+ public void layoutContainer(Container target) {
+ synchronized (target.getTreeLock()) {
+ Insets insets = target.getInsets();
+ int width = target.getWidth();
+ int height = target.getHeight();
+ calculateLastInset(target, width, height);
+ if (insetNotChange(insets, lastInset)) {
+ return;
+ }
+ // 设置内边距时已经判断过,此处直接加上内边距
+ for (int i=0, len=target.getComponentCount(); i map = new HashMap();
+
+ public FRGridLayout() {
+ this(1, 1, 0, 0);
+
+ }
+
+ public FRGridLayout(int rows, int cols) {
+ this(rows, cols, 0, 0);
+ }
+
+ public FRGridLayout(int rows, int cols, int hgap, int vgap) {
+ super(rows, cols, hgap, vgap);
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+ for (int r = 0; r < getRows(); r++) {
+ for (int c = 0; c < getColumns(); c++) {
+ Point key = new Point(c, r);
+ if (ComparatorUtils.equals(comp, map.get(key))) {
+ map.remove(key);
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * 将组件添加到指定的位置上
+ * @param comp
+ * @param constraints new FRGridLayout.Grid(2, 3);
+ */
+ @Override
+ public void addLayoutComponent(Component comp, Object constraints) {
+ // 如果没有指定添加位置,就从第一排开始逐个添加
+ if (constraints == null) {
+ for (int r = 0; r < getRows(); r++) {
+ for (int c = 0; c < getColumns(); c++) {
+ Point key = new Point(c, r);
+ if (map.get(key) == null) {
+ map.put(key, comp);
+ return;
+ }
+ }
+ }
+ // 如果指定位置了,就不管原来位置上有没有组件都直接覆盖
+ } else {
+ Point point = (Point) constraints;
+ if (point.x > getColumns() - 1 || point.y > getRows() - 1) {
+ throw new IllegalArgumentException("Component cannot be add at this point!");
+ }
+ map.put(point, comp);
+ }
+ }
+
+ public Point getPoint(Component comp) {
+ Iterator it = map.keySet().iterator();
+ while (it.hasNext()) {
+ Point key = (Point) it.next();
+ if (ComparatorUtils.equals(map.get(key), comp)) {
+ return key;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public float getLayoutAlignmentX(Container target) {
+ return 0.5f;
+ }
+
+ @Override
+ public float getLayoutAlignmentY(Container target) {
+ return 0.5f;
+ }
+
+ @Override
+ public void invalidateLayout(Container target) {
+ }
+
+ @Override
+ public void layoutContainer(Container parent) {
+ synchronized (parent.getTreeLock()) {
+ Insets insets = parent.getInsets();
+ int w = parent.getWidth() - (insets.left + insets.right);
+ int h = parent.getHeight() - (insets.top + insets.bottom);
+ w = (w - (getColumns() - 1) * getHgap()) / getColumns();
+ h = (h - (getRows() - 1) * getVgap()) / getRows();
+ Iterator it = map.keySet().iterator();
+ while (it.hasNext()) {
+ Point key = it.next();
+ int row = key.y;
+ int column = key.x;
+ map.get(key).setBounds(column * (w + getHgap()) + insets.left, row * (h + getVgap()) + insets.top, w, h);
+ }
+ }
+ }
+
+ @Override
+ public boolean isResizable() {
+ return false;
+ }
+
+ public static void main(String[] args) {
+ JFrame f = new JFrame();
+ JPanel p = (JPanel) f.getContentPane();
+ p.setLayout(FRGUIPaneFactory.createBorderLayout());
+ FRGridLayout layout = new FRGridLayout(3, 4, 10, 4);
+ JPanel pp = new JPanel(layout);
+ p.add(pp, BorderLayout.CENTER);
+ pp.add(new UIButton("1111"));
+ pp.add(new UIButton("111122"));
+ pp.add(new UITextField("1111222"), new Point(3, 2));
+ f.setSize(400, 400);
+ f.setVisible(true);
+ }
+
+ @Override
+ public Dimension maximumLayoutSize(Container target) {
+ return new Dimension(0, 0);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRHorizontalLayout.java b/designer_form/src/com/fr/design/form/layout/FRHorizontalLayout.java
new file mode 100644
index 000000000..f5795d35d
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRHorizontalLayout.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Insets;
+
+/**
+ * @author richer
+ * @since 6.5.3 水平布局 所有布局内的控件的高度将和容器的高度一样,宽度以及对齐方式可以自由设置
+ */
+public class FRHorizontalLayout extends FRFlowLayout {
+
+ public static final int LEFT = 0;
+ public static final int CENTER = 1;
+ public static final int RIGHT = 2;
+
+ public FRHorizontalLayout() {
+ this(CENTER);
+ }
+
+ public FRHorizontalLayout(int align) {
+ super(0, 0);
+ setAlignment(align);
+ }
+
+
+ public FRHorizontalLayout(int alignment, int hgap, int vgap) {
+ super(alignment,hgap,vgap);
+ }
+
+ @Override
+ protected void moveComponents(Container target, Insets insets, int total) {
+ int width = target.getWidth() - total - insets.left - insets.right;
+ int x = insets.left;
+ switch (alignment) {
+ case LEFT:
+ x += 0;
+ break;
+ case CENTER:
+ x += width / 2;
+ break;
+ case RIGHT:
+ x += width;
+ break;
+ }
+ int ey = insets.top + vgap;
+ for (int i = 0; i < target.getComponentCount(); i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ m.setLocation(x, ey);
+ x += m.getPreferredSize().width + hgap;
+ }
+ }
+
+ }
+
+ @Override
+ protected int reSizeComponents(Container target, Insets insets) {
+ int eachHeight = target.getHeight() - insets.top - insets.bottom - 2 * vgap;
+ int total = 0;
+ for (int i = 0; i < target.getComponentCount(); i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ m.setSize(m.getPreferredSize().width, eachHeight);
+ total += m.getPreferredSize().width + hgap;
+ }
+ }
+ return total;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRHorizontalSplitLayout.java b/designer_form/src/com/fr/design/form/layout/FRHorizontalSplitLayout.java
new file mode 100644
index 000000000..91377e356
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRHorizontalSplitLayout.java
@@ -0,0 +1,77 @@
+package com.fr.design.form.layout;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import com.fr.design.gui.itextfield.UITextField;
+
+/**
+ * @author richer
+ * @since 6.5.4 水平方向上的均分布局,左右组件宽度比为ratio : (1 - ratio)
+ */
+public class FRHorizontalSplitLayout extends FRSplitLayout {
+ public FRHorizontalSplitLayout() {
+ super();
+ }
+
+ public FRHorizontalSplitLayout(double ratio) {
+ super(ratio);
+ }
+
+ public FRHorizontalSplitLayout(double ratio, int hgap, int vgap) {
+ super(ratio, hgap, vgap);
+ }
+
+ @Override
+ protected Dimension calculateAppropriateSize(Container target, Dimension asideDim, Dimension centerDim) {
+ Dimension dim = new Dimension(0, 0);
+ Insets insets = target.getInsets();
+ dim.width += insets.left + insets.right + hgap;
+ dim.height += insets.top + insets.bottom + vgap * 2;
+ int totalWidth = 0;
+ if (asideDim != null) {
+ totalWidth = (int) (asideDim.getWidth() / ratio);
+ }
+ if (centerDim != null) {
+ int totalWidthFromCenter = (int) (centerDim.getWidth() / (1 - ratio));
+ if (totalWidthFromCenter > totalWidth) {
+ totalWidth = totalWidthFromCenter;
+ }
+ }
+ dim.width += totalWidth;
+ return dim;
+ }
+
+ @Override
+ public void layoutContainer(Container target) {
+ synchronized (target.getTreeLock()) {
+ Insets insets = target.getInsets();
+ // 这个布局只有两个组件
+ int availableWidth = target.getWidth() - insets.left - insets.right - hgap;
+ int availableHeight = target.getHeight() - insets.top - insets.bottom - 2 * vgap;
+ int asideWidth = 0;
+ if (aside != null) {
+ asideWidth = (int) (availableWidth * ratio);
+ aside.setBounds(insets.left, insets.top + vgap, asideWidth, availableHeight);
+ }
+ if (center != null) {
+ center.setBounds(insets.left + asideWidth + hgap, insets.top + vgap, availableWidth - asideWidth, availableHeight);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ JFrame f = new JFrame("水平均分布局测试");
+ JPanel p = (JPanel) f.getContentPane();
+ p.setLayout(new FRHorizontalSplitLayout(0.8, 2, 2));
+ UITextField f1 = new UITextField("左边");
+ p.add(f1, FRSplitLayout.ASIDE);
+ UITextField f2 = new UITextField("右边");
+ p.add(f2, FRSplitLayout.CENTER);
+ f.setSize(300, 200);
+ f.setVisible(true);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRLayoutManager.java b/designer_form/src/com/fr/design/form/layout/FRLayoutManager.java
new file mode 100644
index 000000000..4d0b03e21
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRLayoutManager.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+import java.awt.LayoutManager;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ * 统一的布局管理器
+ */
+public interface FRLayoutManager extends LayoutManager{
+ public boolean isResizable();
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRPolyReportLayout.java b/designer_form/src/com/fr/design/form/layout/FRPolyReportLayout.java
new file mode 100644
index 000000000..659b01597
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRPolyReportLayout.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class FRPolyReportLayout extends FRFormLayout{
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRScaleLayout.java b/designer_form/src/com/fr/design/form/layout/FRScaleLayout.java
new file mode 100644
index 000000000..d27d3f5d9
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRScaleLayout.java
@@ -0,0 +1,87 @@
+/**
+ *
+ */
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+
+import com.fr.form.ui.container.WFitLayout;
+import com.fr.form.ui.container.WLayout;
+
+/**
+ * @author jim
+ * @date 2014-9-23
+ */
+public class FRScaleLayout implements FRLayoutManager{
+
+ /**
+ * 增加组件
+ * @param name 名字
+ * @param comp 组件
+ */
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+
+ }
+
+ /**
+ * 移除组件
+ * @param comp 组件
+ */
+ @Override
+ public void removeLayoutComponent(Component comp) {
+
+ }
+
+ /**
+ * 最优大小
+ * @param parent 父容器
+ * @return 默认大小
+ */
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ return new Dimension(WLayout.MIN_WIDTH, WFitLayout.MIN_HEIGHT);
+ }
+
+ /**
+ * 最小大小
+ * @param parent 父容器
+ * @return 默认初始大小
+ */
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ return new Dimension(WLayout.MIN_WIDTH, WFitLayout.MIN_HEIGHT);
+ }
+
+ /**
+ * 布局刷新
+ * @param target 容器
+ */
+ @Override
+ public void layoutContainer(Container parent) {
+ synchronized (parent.getTreeLock()) {
+ if (parent.getComponentCount() < 1) {
+ return;
+ }
+ // 考虑布局用内边距,所以文本框都控件特殊用的当前layout刷新下子控件
+ Component comp = parent.getComponent(0);
+ if (comp != null) {
+ Rectangle rec = parent.getBounds();
+ comp.setBounds(0, 0, rec.width, comp.getHeight());
+ }
+ }
+ }
+
+ /**
+ * 是否重置大小
+ * @return 是
+ */
+ @Override
+ public boolean isResizable() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRSplitLayout.java b/designer_form/src/com/fr/design/form/layout/FRSplitLayout.java
new file mode 100644
index 000000000..bd1b3cd79
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRSplitLayout.java
@@ -0,0 +1,180 @@
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.LayoutManager2;
+
+public abstract class FRSplitLayout implements FRLayoutManager, LayoutManager2, java.io.Serializable {
+ public static final String CENTER = "center";
+ public static final String ASIDE = "aside";
+ // 分割比率
+ protected double ratio;
+ protected int hgap;
+ protected int vgap;
+
+ protected Component center;
+ protected Component aside;
+
+ public FRSplitLayout() {
+ this(0.5);
+ }
+
+ public FRSplitLayout(double ratio) {
+ this(ratio, 0, 0);
+ }
+
+ public FRSplitLayout(double ratio, int hgap, int vgap) {
+ this.ratio = ratio;
+ this.hgap = hgap;
+ this.vgap = vgap;
+ }
+
+ public double getRatio() {
+ return ratio;
+ }
+
+ public void setRatio(double ratio) {
+ if (ratio < 0 || ratio > 1) {
+ throw new IllegalArgumentException("Ratio must be in [0, 1]");
+ }
+ this.ratio = ratio;
+ }
+
+ public int getHgap() {
+ return hgap;
+ }
+
+ public void setHgap(int hgap) {
+ this.hgap = hgap;
+ }
+
+ public int getVgap() {
+ return vgap;
+ }
+
+ public void setVgap(int vgap) {
+ this.vgap = vgap;
+ }
+
+ public Object getConstraints(Component comp) {
+ if (comp == center) {
+ return CENTER;
+ } else if (comp == aside) {
+ return ASIDE;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void addLayoutComponent(Component comp, Object constraints) {
+ synchronized (comp.getTreeLock()) {
+ if (constraints == null || constraints instanceof String) {
+ addLayoutComponent((String) constraints, comp);
+ }
+ }
+ }
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+ synchronized (comp.getTreeLock()) {
+ if (name == null) {
+ name = CENTER;
+ }
+ if (CENTER.equals(name)) {
+ center = comp;
+ } else if (ASIDE.equals(name)) {
+ aside = comp;
+ }
+ }
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+ synchronized (comp.getTreeLock()) {
+ if (comp == center) {
+ center = null;
+ } else if (comp == aside) {
+ aside = null;
+ }
+ }
+ }
+
+ public Component getLayoutComponent(Object constraints) {
+ if (CENTER.equals(constraints)) {
+ return center;
+ } else if (ASIDE.equals(constraints)) {
+ return aside;
+ } else {
+ throw new IllegalArgumentException("error " + constraints + "!");
+ }
+ }
+
+ @Override
+ public boolean isResizable() {
+ return false;
+ }
+
+ @Override
+ public Dimension preferredLayoutSize(Container target) {
+ synchronized (target.getTreeLock()) {
+ Dimension asideDim = null;
+ if (aside != null) {
+ asideDim = aside.getPreferredSize();
+ }
+ Dimension centerDim = null;
+ if (center != null) {
+ centerDim = center.getPreferredSize();
+ }
+ return calculateAppropriateSize(target, asideDim, centerDim);
+ }
+ }
+
+ @Override
+ public Dimension minimumLayoutSize(Container target) {
+ synchronized (target.getTreeLock()) {
+ Dimension asideDim = null;
+ if (aside != null) {
+ asideDim = aside.getMinimumSize();
+ }
+ Dimension centerDim = null;
+ if (center != null) {
+ centerDim = center.getMinimumSize();
+ }
+ return calculateAppropriateSize(target, asideDim, centerDim);
+ }
+ }
+
+ @Override
+ public Dimension maximumLayoutSize(Container target) {
+ synchronized (target.getTreeLock()) {
+ Dimension asideDim = null;
+ if (aside != null) {
+ asideDim = aside.getMaximumSize();
+ }
+ Dimension centerDim = null;
+ if (center != null) {
+ centerDim = center.getMaximumSize();
+ }
+ return calculateAppropriateSize(target, asideDim, centerDim);
+ }
+ }
+
+ protected abstract Dimension calculateAppropriateSize(Container target, Dimension asideDim, Dimension centerDim);
+
+ @Override
+ public float getLayoutAlignmentX(Container target) {
+ return 0.5f;
+ }
+
+ @Override
+ public float getLayoutAlignmentY(Container target) {
+ return 0.5f;
+ }
+
+ @Override
+ public void invalidateLayout(Container target) {
+
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRTitleLayout.java b/designer_form/src/com/fr/design/form/layout/FRTitleLayout.java
new file mode 100644
index 000000000..9fdf49865
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRTitleLayout.java
@@ -0,0 +1,160 @@
+/**
+ *
+ */
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.LayoutManager;
+
+import com.fr.form.ui.container.WLayout;
+import com.fr.form.ui.container.WTitleLayout;
+import com.fr.general.ComparatorUtils;
+
+/**
+ * 布局管理器,主要为一些需要加标题的组件用,如报表块、图表块
+ *
+ * @author jim
+ * @date 2014-9-25
+ */
+public class FRTitleLayout implements FRLayoutManager, LayoutManager{
+
+ public static final String TITLE = "Title";
+
+ public static final String BODY = "Body";
+
+ // 标题控件,默认为文本框
+ private Component title;
+ // 主体控件,有表单报表块、图表块
+ private Component body;
+ private int gap;
+
+ /**
+ * 构造函数
+ */
+ public FRTitleLayout() {
+ this(0);
+ }
+
+ /**
+ * 标题和主体间隙gap的布局
+ * @param gap 间隙值
+ */
+ public FRTitleLayout(int gap) {
+ this.gap = gap;
+ }
+
+ /**
+ * 返回
+ * Returns the gap between components.
+ */
+ public int getGap() {
+ return gap;
+ }
+
+ /**
+ * 设置
+ * Sets the gap between components.
+ * @param the gap between components
+ */
+ public void setGap(int gap) {
+ this.gap = gap;
+ }
+
+ /**
+ * 增加组件
+ * @param name 名字
+ * @param comp 组件
+ */
+ public void addLayoutComponent(String name, Component comp) {
+ synchronized (comp.getTreeLock()) {
+ if (ComparatorUtils.equals(name, null)) {
+ name = BODY;
+ }
+ if (ComparatorUtils.equals(name, BODY)) {
+ body = comp;
+ } else if (ComparatorUtils.equals(name, TITLE)) {
+ title = comp;
+ }
+ }
+ }
+
+ /**
+ * 移除组件
+ * @param comp 组件
+ */
+ @Override
+ public void removeLayoutComponent(Component comp) {
+ synchronized (comp.getTreeLock()) {
+ if (comp == title) {
+ title = null;
+ }
+ }
+ }
+
+ /**
+ * 最优大小
+ * @param parent 父容器
+ * @return 默认大小
+ */
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ return new Dimension(WLayout.MIN_WIDTH, WLayout.MIN_HEIGHT*2);
+ }
+
+ /**
+ * 最小大小
+ * @param parent 父容器
+ * @return 默认初始大小
+ */
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ // 有标题时,最小高度为两个组件高度
+ return new Dimension(WLayout.MIN_WIDTH, title==null? WLayout.MIN_HEIGHT : WLayout.MIN_HEIGHT+WTitleLayout.TITLE_HEIGHT);
+ }
+
+ /**
+ * 布局刷新
+ * @param target 容器
+ */
+ @Override
+ public void layoutContainer(Container target) {
+ synchronized (target.getTreeLock()) {
+ int width = target.getWidth();
+ int height = target.getHeight();
+ int titleH = title==null ? 0 : WTitleLayout.TITLE_HEIGHT;
+ for (int i=0; i< target.getComponentCount(); i++) {
+ Component comp = target.getComponent(i);
+ if (comp == title) {
+ comp.setBounds(0, 0, width, WTitleLayout.TITLE_HEIGHT);
+ } else if (comp == body) {
+ int y = titleH+gap;
+ comp.setBounds(0, y, width, height-y);
+ }
+ }
+ }
+ }
+
+ public Object getConstraints(Component comp) {
+ if (comp == null){
+ return null;
+ }
+ if (comp == title) {
+ return TITLE;
+ } else if (comp == body) {
+ return BODY;
+ }
+ return null;
+ }
+
+ /**
+ * 是否重置大小
+ * @return 是
+ */
+ @Override
+ public boolean isResizable() {
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRVerticalLayout.java b/designer_form/src/com/fr/design/form/layout/FRVerticalLayout.java
new file mode 100644
index 000000000..920177381
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRVerticalLayout.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Insets;
+
+
+/**
+ * @author richer
+ * @since 6.5.3 垂直布局 所有布局内的控件的宽度将和容器的宽度一样
+ */
+public class FRVerticalLayout extends FRFlowLayout {
+
+ public static final int TOP = 0;
+ public static final int CENTER = 1;
+ public static final int BOTTOM = 2;
+
+ public FRVerticalLayout() {
+ this(0,0);
+ }
+
+ public FRVerticalLayout(int align) {
+ this(align,0,0);
+ }
+
+ public FRVerticalLayout(int hgap, int vgap) {
+ this(TOP,hgap,vgap);
+ }
+
+ public FRVerticalLayout(int alignment, int hgap, int vgap) {
+ super(alignment,hgap,vgap);
+ }
+
+ @Override
+ protected void moveComponents(Container target, Insets insets, int total) {
+ int height = target.getHeight() - total - insets.top - insets.bottom;
+ int y = insets.top;
+ switch (alignment) {
+ case TOP:
+ y += 0;
+ break;
+ case CENTER:
+ y += height / 2;
+ break;
+ case BOTTOM:
+ y += height;
+ break;
+ }
+ int ex = insets.left + hgap;
+ for (int i = 0; i < target.getComponentCount(); i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ m.setLocation(ex, y);
+ y += m.getPreferredSize().height + vgap;
+ }
+ }
+
+ }
+
+ @Override
+ protected int reSizeComponents(Container target, Insets insets) {
+ int eachWidth = target.getWidth() - insets.left - insets.right - 2 * hgap;
+ int total = 0;
+ for (int i = 0; i < target.getComponentCount(); i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ m.setSize(eachWidth, m.getPreferredSize().height);
+ total += m.getPreferredSize().height + vgap;
+ }
+ }
+ return total;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/layout/FRVerticalSplitLayout.java b/designer_form/src/com/fr/design/form/layout/FRVerticalSplitLayout.java
new file mode 100644
index 000000000..eb579b04c
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/layout/FRVerticalSplitLayout.java
@@ -0,0 +1,78 @@
+package com.fr.design.form.layout;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import com.fr.design.gui.itextfield.UITextField;
+
+/**
+ * @author richer
+ * @since 6.5.4 垂直方向上的均分布局,上下组件高度比为ratio : (1 - ratio)
+ */
+public class FRVerticalSplitLayout extends FRSplitLayout {
+ public FRVerticalSplitLayout() {
+ super();
+ }
+
+ public FRVerticalSplitLayout(double ratio) {
+ super(ratio);
+ }
+
+ public FRVerticalSplitLayout(double ratio, int hgap, int vgap) {
+ super(ratio, hgap, vgap);
+ }
+
+ @Override
+ protected Dimension calculateAppropriateSize(Container target, Dimension asideDim, Dimension centerDim) {
+ Dimension dim = new Dimension(0, 0);
+ Insets insets = target.getInsets();
+ dim.width += insets.left + insets.right + hgap * 2;
+ dim.height += insets.top + insets.bottom + vgap;
+ int totalHeight = 0;
+ if (asideDim != null) {
+ totalHeight = (int) (asideDim.getHeight() / ratio);
+ }
+ if (centerDim != null) {
+ int totalHeightFromCenter = (int) (centerDim.getHeight() / (1 - ratio));
+ if (totalHeightFromCenter > totalHeight) {
+ totalHeight = totalHeightFromCenter;
+ }
+ }
+ dim.height += totalHeight;
+ return dim;
+ }
+
+ @Override
+ public void layoutContainer(Container target) {
+ Insets insets = target.getInsets();
+ // 这个布局只有两个组件
+ int availableWidth = target.getWidth() - insets.left - insets.right - hgap * 2;
+ int availableHeight = target.getHeight() - insets.top - insets.bottom - vgap;
+ int asideHeight = 0;
+ if (aside != null) {
+ asideHeight = (int) (availableHeight * ratio);
+ aside.setBounds(insets.left + hgap, insets.top + vgap, availableWidth, asideHeight);
+ }
+ if (center != null) {
+ center.setBounds(insets.left + hgap, insets.top + asideHeight + vgap, availableWidth, availableHeight - asideHeight);
+ }
+ }
+
+ public static void main(String[] args) {
+ JFrame f = new JFrame("垂直均分布局测试");
+ JPanel p = (JPanel) f.getContentPane();
+ p.setLayout(new FRVerticalSplitLayout(0.2, 2, 2));
+ UITextField f1 = new UITextField("上边");
+ p.add(f1, FRSplitLayout.ASIDE);
+ UITextField f2 = new UITextField("下边");
+ p.add(f2, FRSplitLayout.CENTER);
+ f.setSize(300, 210);
+ f.setVisible(true);
+ System.out.println(f1.getSize());
+ System.out.println(f2.getSize());
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java b/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java
new file mode 100644
index 000000000..f46334dd5
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/parameter/FormParaDesigner.java
@@ -0,0 +1,685 @@
+/*
+ * Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.parameter;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.Parameter;
+import com.fr.base.parameter.ParameterUI;
+import com.fr.design.DesignModelAdapter;
+import com.fr.design.designer.beans.actions.CopyAction;
+import com.fr.design.designer.beans.actions.CutAction;
+import com.fr.design.designer.beans.actions.FormDeleteAction;
+import com.fr.design.designer.beans.actions.PasteAction;
+import com.fr.design.designer.beans.adapters.layout.FRAbsoluteLayoutAdapter;
+import com.fr.design.designer.beans.events.DesignerEditListener;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWAbsoluteLayout;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.design.designer.properties.FormWidgetAuthorityEditPane;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.mainframe.AuthorityEditPane;
+import com.fr.design.mainframe.DesignerContext;
+import com.fr.design.mainframe.EastRegionContainerPane;
+import com.fr.design.mainframe.FormArea;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.FormDesignerModeForSpecial;
+import com.fr.design.mainframe.FormParaPane;
+import com.fr.design.mainframe.FormWidgetDetailPane;
+import com.fr.design.mainframe.WidgetPropertyPane;
+import com.fr.design.mainframe.WidgetToolBarPane;
+import com.fr.design.parameter.ParaDefinitePane;
+import com.fr.design.parameter.ParameterDesignerProvider;
+import com.fr.design.parameter.ParameterPropertyPane;
+import com.fr.form.main.Form;
+import com.fr.form.main.parameter.FormParameterUI;
+import com.fr.form.parameter.FormSubmitButton;
+import com.fr.form.ui.EditorHolder;
+import com.fr.form.ui.WidgetValue;
+import com.fr.form.ui.container.WAbsoluteLayout;
+import com.fr.form.ui.container.WLayout;
+import com.fr.form.ui.container.WParameterLayout;
+import com.fr.general.Inter;
+import com.fr.stable.ArrayUtils;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User : Richer
+ * Version: 6.5.5
+ * Date : 11-7-5
+ * Time : 下午7:46
+ * 表单类型的参数设计器
+ */
+// TODO ALEX_SEP FormDesigner和FormParaDesignEditor应该共用Form的编辑,但是FormParaDesignEditor不应该直接就是FormDesigner
+public class FormParaDesigner extends FormDesigner implements ParameterDesignerProvider {
+ private static final int NUM_IN_A_LINE = 4;
+ private static final int H_COMPONENT_GAP = 165;
+ private static final int V_COMPONENT_GAP = 25;
+ private static final int FIRST_V_LOCATION = 35;
+ private static final int FIRST_H_LOCATION = 90;
+ private static final int SECOND_H_LOCATION = 170;
+ private static final int ADD_HEIGHT = 20;
+ private static final int H_GAP = 105;
+
+ private static Image paraImage = BaseUtils.readImage("/com/fr/design/images/form/parameter.png");
+
+ public FormParaDesigner() {
+ this(new FormParameterUI());
+ }
+
+ public FormParaDesigner(FormParameterUI ui) {
+ super(gen(ui));
+ }
+
+ private static Form gen(Form form) {
+ WLayout container = form.getContainer();
+ if (container == null) {
+ container = new WParameterLayout();
+ }
+ container.setWidgetName("para");
+ form.setContainer(container);
+ return form;
+ }
+
+ protected FormDesignerModeForSpecial> createFormDesignerTargetMode() {
+ return new FormParaTargetMode(this);
+ }
+
+ /**
+ * 开始编辑参数面板的时候进行的初始化
+ */
+ public void initBeforeUpEdit() {
+ WidgetToolBarPane.getInstance(this);
+ EastRegionContainerPane.getInstance().replaceDownPane(
+ FormWidgetDetailPane.getInstance(this));
+ if (!BaseUtils.isAuthorityEditing()) {
+ EastRegionContainerPane.getInstance().replaceUpPane(
+ WidgetPropertyPane.getInstance(this));
+ } else {
+ showAuthorityEditPane();
+ }
+
+ }
+
+ /**
+ * 创建权限编辑面板
+ * @return 面板
+ */
+ public AuthorityEditPane createAuthorityEditPane() {
+ return new FormWidgetAuthorityEditPane(this);
+ }
+
+ /**
+ * 内容属性表面板
+ * @return 内容属性表面板
+ */
+ public JPanel getEastUpPane() {
+ return WidgetPropertyPane.getInstance(this);
+ }
+
+ /**
+ * 参数属性表
+ * @return 参数属性表
+ */
+
+ public JPanel getEastDownPane() {
+ return FormWidgetDetailPane.getInstance(this);
+ }
+
+ /**
+ * 权限编辑面板
+ * @return 权限编辑面板
+ */
+ public AuthorityEditPane getAuthorityEditPane() {
+ FormWidgetAuthorityEditPane formWidgetAuthorityEditPane = new FormWidgetAuthorityEditPane(this);
+ formWidgetAuthorityEditPane.populateDetials();
+ return formWidgetAuthorityEditPane;
+ }
+
+ /**
+ * 给包含此FormParaDesigner的ParameterDefinitePane添加事件
+ *
+ * @param paraDefinitePane 面板
+ */
+ public void addListener(final ParaDefinitePane paraDefinitePane) {
+ this.getEditListenerTable().addListener(new DesignerEditListener() {
+
+ @Override
+ public void fireCreatorModified(DesignerEvent evt) {
+ if (evt.getCreatorEventID() == DesignerEvent.CREATOR_ADDED
+ || evt.getCreatorEventID() == DesignerEvent.CREATOR_CUTED
+ || evt.getCreatorEventID() == DesignerEvent.CREATOR_PASTED
+ || evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED
+ || evt.getCreatorEventID() == DesignerEvent.CREATOR_EDITED
+ || evt.getCreatorEventID() == DesignerEvent.CREATOR_RENAMED) {
+ paraDefinitePane.setParameterArray(
+ paraDefinitePane.getNoRepeatParas(DesignModelAdapter.getCurrentModelAdapter().getParameters()));
+ paraDefinitePane.refreshParameter();
+ }
+ }
+ });
+ }
+
+ /**
+ * 包裹一层FormArea
+ *
+ * @return 区域
+ */
+ public Component createWrapper() {
+ FormArea area = new FormArea(this, false);
+ area.setBorder(BorderFactory.createEmptyBorder(0, 13, 0, 0));
+ return area;
+ }
+
+ /**
+ * 刷新控件
+ */
+ public void refreshAllNameWidgets() {
+ XCreatorUtils.refreshAllNameWidgets(this.getRootComponent());
+ }
+
+ /**
+ * 刷新tableData
+ *
+ * @param oldName 旧名称
+ * @param newName 新名称
+ */
+ public void refresh4TableData(String oldName, String newName) {
+ this.getTarget().renameTableData(oldName, newName);
+ this.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_SELECTED);
+ }
+
+ /**
+ * 刷新参数
+ *
+ * @param p 参数面板
+ */
+ public void refreshParameter(ParaDefinitePane p) {
+ XLayoutContainer rootContainer = this.getRootComponent();
+ java.util.List namelist = getAllXCreatorNameList(rootContainer);
+ // parameterArray是报表的所有参数, nameList是已经在参数面板添加过控件的参数名
+ // 与已有的参数列表比较 如果已经存在 就除去
+ Parameter[] ps = p.getParameterArray();
+ if (ps != null) {
+ for (Parameter parameter : ps) {
+ for (String name : namelist) {
+ if (name.equalsIgnoreCase(parameter.getName())) {
+ p.setParameterArray((Parameter[]) ArrayUtils.removeElement(p.getParameterArray(), parameter));
+ }
+ }
+ }
+ }
+ ParameterPropertyPane.getInstance().getParameterToolbarPane().populateBean(
+ p.getParameterArray() == null ? new Parameter[0] : p.getParameterArray());
+ ParameterPropertyPane.getInstance().repaintContainer();
+ }
+
+ /**
+ * 判断这个参数面板是否没有控件
+ *
+ * @return 参数面板是否没有控件
+ */
+ public boolean isBlank() {
+ XLayoutContainer rootContainer = this.getRootComponent();
+ List xx = getAllXCreatorNameList(rootContainer);
+ return xx.isEmpty();
+ }
+
+ protected void setToolbarButtons(boolean flag) {
+ DesignerContext.getDesignerFrame().checkCombineUp(!flag, NAME_ARRAY_LIST);
+ }
+
+ /**
+ * 看看参数面板中的控件是否有和模板参数同名的
+ *
+ * @param allParameters 参数
+ * @return 是否有同名
+ */
+ public boolean isWithoutParaXCreator(Parameter[] allParameters) {
+ XLayoutContainer rootContainer = this.getRootComponent();
+ List xx = getAllXCreatorNameList(rootContainer);
+ for (Parameter parameter : allParameters) {
+ for (String name : xx) {
+ if (name.equalsIgnoreCase(parameter.getName())) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * 参数面板控件的名字
+ *
+ * @return 名字
+ */
+ public List getAllXCreatorNameList() {
+ XLayoutContainer rootContainer = this.getRootComponent();
+ List namelist = new ArrayList();
+ for (int i = 0; i < rootContainer.getXCreatorCount(); i++) {
+ if (rootContainer.getXCreator(i) instanceof XLayoutContainer) {
+ namelist.addAll(getAllXCreatorNameList((XLayoutContainer) rootContainer.getXCreator(i)));
+ } else {
+ namelist.add(rootContainer.getXCreator(i).toData().getWidgetName());
+ }
+ }
+ return namelist;
+ }
+
+ private List getAllXCreatorNameList(XLayoutContainer rootContainer) {
+ List namelist = new ArrayList();
+ for (int i = 0; i < rootContainer.getXCreatorCount(); i++) {
+ if (rootContainer.getXCreator(i) instanceof XLayoutContainer) {
+ namelist.addAll(getAllXCreatorNameList((XLayoutContainer) rootContainer.getXCreator(i)));
+ } else {
+ namelist.add(rootContainer.getXCreator(i).toData().getWidgetName());
+ }
+ }
+ return namelist;
+ }
+
+ /**
+ * 是否有查询按钮
+ *
+ * @return 有无查询按钮
+ */
+ public boolean isWithQueryButton() {
+ XLayoutContainer rootContainer = this.getRootComponent();
+ return SearchQueryCreators(rootContainer);
+ }
+
+ /**
+ * 返回复制粘贴删除等动作
+ * @return 同上
+ */
+ public Action[] getActions() {
+ if (designer_actions == null) {
+ designer_actions = new Action[]{new CutAction(this), new CopyAction(this), new PasteAction(this),
+ new FormDeleteAction(this)};
+ }
+ return designer_actions;
+ }
+
+ private boolean SearchQueryCreators(XLayoutContainer rootContainer) {
+ boolean b = false;
+ for (int i = 0; i < rootContainer.getXCreatorCount(); i++) {
+ if (rootContainer.getXCreator(i) instanceof XLayoutContainer) {
+ b = SearchQueryCreators((XLayoutContainer) rootContainer.getXCreator(i));
+ } else if (rootContainer.getXCreator(i) instanceof XFormSubmit) {
+ b = true;
+ }
+ }
+ return b;
+ }
+
+ /**
+ * 就是getTarget 为了返回ParameterUI接口而不冲突另写个
+ *
+ * @return
+ */
+ public ParameterUI getParaTarget() {
+ return (FormParameterUI) super.getTarget();
+ }
+
+ /**
+ * ParameterDefinitePane通过ParaDesigner来调用ParameterPropertyPane
+ *
+ * @param p 面板
+ */
+ public void populateParameterPropertyPane(ParaDefinitePane p) {
+ ParameterPropertyPane.getInstance().populateBean(p);
+ }
+
+ /**
+ * 初始化
+ */
+ public void initWidgetToolbarPane() {
+ WidgetToolBarPane.getInstance(this);
+ }
+
+ /**
+ * populate
+ *
+ * @param ui
+ */
+ public void populate(ParameterUI ui) {
+ if (ui == null) {
+ return;
+ }
+ if (this.getTarget() == ui) {
+ repaint();
+ return;
+ }
+ this.setTarget((FormParameterUI) ui.convert());
+ this.refreshRoot();
+ }
+
+ /**
+ * 报表直接判断底层是否是绝对布局
+ * @return 是则返回true
+ */
+ public boolean hasWAbsoluteLayout() {
+ return this.getTarget().getContainer() instanceof WAbsoluteLayout;
+ }
+
+ /**
+ * 刷新底层容器
+ */
+ public void refreshRoot() {
+ XLayoutContainer layoutContainer = (XLayoutContainer) XCreatorUtils.createXCreator(this.getTarget()
+ .getContainer());
+ if (layoutContainer == null) {
+ layoutContainer = new XWParameterLayout();
+ }
+ layoutContainer.setSize(LARGE_PREFERRED_SIZE);
+ setRootComponent(layoutContainer);
+ }
+
+ /**
+ * 是否是报表的参数面板
+ * @return 是
+ */
+ public boolean isFormParaDesigner(){
+ return true;
+ }
+
+ public XLayoutContainer getParaComponent() {
+ return getRootComponent();
+ }
+
+ private void paintLinkParameters(Graphics clipg) {
+ Parameter[] paras = DesignModelAdapter.getCurrentModelAdapter().getParameters();
+ if (paras == null || paras.length == 0) {
+ return;
+ }
+ Graphics g = clipg.create();
+ g.setColor(Color.RED);
+ if (!(this.getRootComponent() instanceof XWAbsoluteLayout)) {
+ return;
+ }
+ XWAbsoluteLayout layout = (XWAbsoluteLayout) this.getRootComponent();
+ for (int i = 0; i < layout.getXCreatorCount(); i++) {
+ XCreator creator = layout.getXCreator(i);
+ if (!creator.isVisible()) {
+ continue;
+ }
+ for (Parameter p : paras) {
+ if (p.getName().equalsIgnoreCase(creator.toData().getWidgetName())) {
+ g.drawImage(paraImage, creator.getX() - 4, creator.getY() + 2, null);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * 得到合适的大小
+ *
+ * @return
+ */
+ public Dimension getPreferredSize() {
+ return getDesignSize();
+ }
+
+ public Dimension getDesignSize() {
+ return ((FormParameterUI) getTarget()).getDesignSize();
+ }
+
+ /**
+ * 设置高度
+ *
+ * @param height
+ */
+ public void setDesignHeight(int height) {
+ Dimension dim = getPreferredSize();
+ dim.height = height;
+ ((FormParameterUI) getTarget()).setDesignSize(dim);
+ }
+
+ /**
+ * paintContent
+ *
+ * @param clipg
+ */
+ public void paintContent(Graphics clipg) {
+ Dimension dim;
+ dim = ((FormParameterUI) getTarget()).getDesignSize();
+ getRootComponent().setSize(dim);
+ getRootComponent().paint(clipg);
+ paintLinkParameters(clipg);
+ paintOp(clipg, getOutlineBounds());
+ }
+
+ private void paintOp(Graphics offg, Rectangle bounds) {
+ Color oldColor = offg.getColor();
+ Insets insets = getOutlineInsets();
+ offg.setColor(XCreatorConstants.OP_COLOR);
+ offg.fillRect(bounds.x, bounds.y + bounds.height, bounds.width + insets.right, insets.bottom);
+ offg.fillRect(bounds.x + bounds.width, bounds.y, insets.right, bounds.height);
+ offg.setColor(oldColor);
+ }
+
+ protected void setRootComponent(XLayoutContainer component) {
+ component.setDirections(new int[]{Direction.BOTTOM, Direction.RIGHT});
+ super.setRootComponent(component);
+ }
+
+ /**
+ * 刷新尺寸
+ */
+ public void populateRootSize() {
+ ((FormParameterUI) getTarget()).setDesignSize(getRootComponent().getSize());
+ if (getParaComponent().acceptType(XWParameterLayout.class)) {
+ WParameterLayout layout = (WParameterLayout)getParaComponent().toData();
+ layout.setDesignWidth(getRootComponent().getWidth());
+ }
+ }
+
+ /**
+ * 保存参数界面的宽度
+ *
+ * @param width 指定的宽度
+ */
+ public void updateWidth(int width) {
+ FormParameterUI parameterUI = ((FormParameterUI) getTarget());
+ parameterUI.setDesignSize(new Dimension(width, parameterUI.getDesignSize().height));
+ }
+
+ /**
+ * 保存参数界面的高度
+ *
+ * @param height 指定的高度
+ */
+ public void updateHeight(int height) {
+ FormParameterUI parameterUI = ((FormParameterUI) getTarget());
+ parameterUI.setDesignSize(new Dimension(parameterUI.getDesignSize().width, height));
+ }
+
+ /**
+ * 在参数很多时,全部添加的时候,可以向下一次排版,若去掉就会在参数面板堆到一起
+ *
+ * @param creator 组件 z
+ * @param x 长度
+ * @param y 长度 c
+ * @param layout 布局
+ * @return 是否扩展
+ */
+ public boolean prepareForAdd(XCreator creator, int x, int y, XWAbsoluteLayout layout) {
+ // 参数界面,自动扩展
+ if (!isRoot(layout)) {
+ return false;
+ }
+
+ Dimension size = layout.getSize();
+ Boolean needResize = false;
+
+ if (creator.getWidth() / 2 + x > layout.getWidth()) {
+ size.width = creator.getWidth() / 2 + x + ADD_HEIGHT;
+ needResize = true;
+ }
+ if (creator.getHeight() / 2 + y > layout.getHeight()) {
+ size.height = creator.getHeight() / 2 + y + ADD_HEIGHT;
+ needResize = true;
+ }
+ if (needResize) {
+ layout.setSize(size);
+ populateRootSize();
+ }
+ return true;
+ }
+
+ /**
+ * 加入参数
+ * @param parameter 参数 c
+ * @param currentIndex 位置 w
+ * @return 是否加入 s
+ */
+ public boolean addingParameter2Editor(Parameter parameter, int currentIndex) {
+ com.fr.form.ui.Label label = new com.fr.form.ui.Label();
+ String name = parameter.getName();
+ label.setWidgetName("Label" + name);
+ label.setWidgetValue(new WidgetValue(name + ":"));
+ XCreator xCreator = XCreatorUtils.createXCreator(label);
+ if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE)
+ + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
+ return false;
+ }
+ EditorHolder editor = new EditorHolder(parameter);
+ xCreator = XCreatorUtils.createXCreator(editor);
+ if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE)
+ + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * 加入参数
+ * @param parameter 参数 c
+ * @param currentIndex 位置 w
+ * @return 是否加入 s
+ */
+ public boolean addingParameter2EditorWithQueryButton(Parameter parameter, int currentIndex) {
+ com.fr.form.ui.Label label = new com.fr.form.ui.Label();
+ String name = parameter.getName();
+ label.setWidgetName("Label" + name);
+ label.setWidgetValue(new WidgetValue(name + ":"));
+ XCreator xCreator = XCreatorUtils.createXCreator(label);
+ if (!(this.autoAddComponent(xCreator, FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP
+ * (currentIndex / NUM_IN_A_LINE)))) {
+ return false;
+ }
+ EditorHolder editor = new EditorHolder(parameter);
+ editor.setWidgetName(name);
+ xCreator = XCreatorUtils.createXCreator(editor);
+ if (!(this.autoAddComponent(xCreator, SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP
+ * (currentIndex / NUM_IN_A_LINE)))) {
+ return false;
+ }
+ FormSubmitButton formSubmitButton = new FormSubmitButton();
+ formSubmitButton.setWidgetName("Search");
+ formSubmitButton.setText(Inter.getLocText("FR-Designer_Query"));
+ xCreator = XCreatorUtils.createXCreator(formSubmitButton);
+ if (!(this.autoAddComponent(xCreator, 270, FIRST_V_LOCATION + V_COMPONENT_GAP
+ * (currentIndex / NUM_IN_A_LINE)))) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 加入参数
+ * @param parameterArray 参数 c
+ * @param currentIndex 位置 w
+ * @return 是否加入 s
+ */
+ public void addingAllParameter2Editor(Parameter[] parameterArray, int currentIndex) {
+ for (int i = 0; i < parameterArray.length; i++) {
+ com.fr.form.ui.Label label = new com.fr.form.ui.Label();
+ label.setWidgetName("Label" + parameterArray[i].getName());
+ label.setWidgetValue(new WidgetValue(parameterArray[i].getName() + ":"));
+ XCreator xCreator = XCreatorUtils.createXCreator(label);
+
+ if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE)
+ + FIRST_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
+ break;
+ }
+ // 每行显示5组
+ EditorHolder editor = new EditorHolder(parameterArray[i]);
+ editor.setWidgetName(parameterArray[i].getName());
+ xCreator = XCreatorUtils.createXCreator(editor);
+ if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * (currentIndex % NUM_IN_A_LINE)
+ + SECOND_H_LOCATION, FIRST_V_LOCATION + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
+ break;
+ }
+ currentIndex++;
+ }
+ if (!isWithQueryButton()) {
+ FormSubmitButton formSubmitButton = new FormSubmitButton();
+ formSubmitButton.setWidgetName("Search");
+ formSubmitButton.setText(Inter.getLocText("FR-Designer_Query"));
+ XCreator xCreator = XCreatorUtils.createXCreator(formSubmitButton);
+ if (!(this.autoAddComponent(xCreator, H_COMPONENT_GAP * 3 + H_GAP, FIRST_V_LOCATION
+ + V_COMPONENT_GAP * (currentIndex / NUM_IN_A_LINE)))) {
+ return;
+ }
+ }
+ }
+
+ /**
+ * 自动添加
+ *
+ * @param xCreator 组件 z
+ * @param x 位置 w
+ * @param y 位置
+ * @return 是否添加 s
+ */
+ public boolean autoAddComponent(XCreator xCreator, int x, int y) {
+ XWAbsoluteLayout layout = (XWAbsoluteLayout) this.getRootComponent();
+ FRAbsoluteLayoutAdapter adapter = (FRAbsoluteLayoutAdapter) layout.getLayoutAdapter();
+ if (prepareForAdd(xCreator, x, y, layout)) {
+ adapter.addBean(xCreator, x, y);
+ }
+ this.getSelectionModel().setSelectedCreator(xCreator);
+ repaint();
+ return true;
+ }
+
+ /**
+ * 工具栏
+ * @return 工具栏面板 g
+ */
+ public JPanel[] toolbarPanes4Form() {
+ return new JPanel[]{FormParaPane.getInstance(this)};
+ }
+
+ /**
+ * 复制等按钮
+ * @return 按钮组 a
+ */
+ public JComponent[] toolBarButton4Form() {
+ return new JComponent[]{new CutAction(this).createToolBarComponent(), new CopyAction(this).createToolBarComponent(), new PasteAction(this).createToolBarComponent(),
+ new FormDeleteAction(this).createToolBarComponent()};
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/parameter/FormParaTargetMode.java b/designer_form/src/com/fr/design/form/parameter/FormParaTargetMode.java
new file mode 100644
index 000000000..76f0dadd8
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/parameter/FormParaTargetMode.java
@@ -0,0 +1,52 @@
+package com.fr.design.form.parameter;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.properties.WidgetPropertyTable;
+import com.fr.design.gui.core.WidgetOption;
+import com.fr.design.gui.core.WidgetOptionFactory;
+import com.fr.design.gui.itable.PropertyGroup;
+import com.fr.design.mainframe.FormDesignerModeForSpecial;
+import com.fr.form.main.parameter.FormParameterUI;
+import com.fr.form.parameter.FormSubmitButton;
+import com.fr.general.Inter;
+
+import java.util.ArrayList;
+
+public class FormParaTargetMode extends FormDesignerModeForSpecial {
+
+ static {
+ XCreatorUtils.objectMap.put(FormSubmitButton.class, XFormSubmit.class);
+ }
+
+ public FormParaTargetMode(FormParaDesigner designer) {
+ super(designer);
+ }
+
+ @Override
+ public WidgetOption[] getPredefinedWidgetOptions() {
+ return new WidgetOption[]{
+ WidgetOptionFactory.createByWidgetClass(Inter.getLocText(new String[]{"Query", "Form-Button"}),
+ BaseUtils.readIcon("/com/fr/web/images/form/resources/preview_16.png"), FormSubmitButton.class)};
+ }
+
+ @Override
+ public ArrayList createRootDesignerPropertyGroup() {
+ return WidgetPropertyTable.getCreatorPropertyGroup(this.getTarget(), this.getTarget().getRootComponent());
+ }
+
+ @Override
+ public boolean isFormParameterEditor() {
+ return true;
+ }
+
+ @Override
+ public int getMinDesignHeight() {
+ return ((FormParameterUI) this.getTarget().getTarget()).getDesignSize().height + 20;
+ }
+
+ @Override
+ public int getMinDesignWidth() {
+ return ((FormParameterUI) this.getTarget().getTarget()).getDesignSize().width + 20;
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/parameter/RootDesignGroupModel.java b/designer_form/src/com/fr/design/form/parameter/RootDesignGroupModel.java
new file mode 100644
index 000000000..50ae3ec3d
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/parameter/RootDesignGroupModel.java
@@ -0,0 +1 @@
+/*
* Copyright(c) 2001-2011, FineReport Inc, All Rights Reserved.
*/
package com.fr.design.form.parameter;
import java.awt.Component;
import com.fr.design.designer.beans.ConstraintsGroupModel;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
import com.fr.general.Inter;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
/**
* Created by IntelliJ IDEA.
* User : Richer
* Version: 6.5.5
* Date : 11-7-5
* Time : 下午2:56
*/
public class RootDesignGroupModel implements ConstraintsGroupModel {
private DefaultTableCellRenderer renderer;
private PropertyCellEditor editor;
private XWParameterLayout root;
public RootDesignGroupModel(XWParameterLayout root) {
this.root = root;
renderer = new DefaultTableCellRenderer();
editor = new PropertyCellEditor(new IntegerPropertyEditor());
//初始值为参数面板的初始宽度
if (root.toData().getDesignWidth() == 0){
root.toData().setDesignWidth(root.getWidth());
}
}
@Override
public String getGroupName() {
return Inter.getLocText("Form-Design_Size");
}
@Override
public int getRowCount() {
return 1;
}
@Override
public TableCellRenderer getRenderer(int row) {
return renderer;
}
@Override
public TableCellEditor getEditor(int row) {
return editor;
}
@Override
public Object getValue(int row, int column) {
if (column == 0) {
switch (row) {
case 0:
return Inter.getLocText("Form-Desin_Width");
}
} else {
switch (row) {
case 0:
return root.toData().getDesignWidth();
}
}
return null;
}
@Override
public boolean setValue(Object value, int row, int column) {
if (column == 1) {
int designerWidth = value == null ? 0 : ((Number) value).intValue();
switch (row) {
case 0:
if(isCompsOutOfDesignerWidth(designerWidth)){
return false;
}
root.toData().setDesignWidth(designerWidth);
return true;
default:
return true;
}
} else {
return false;
}
}
private boolean isCompsOutOfDesignerWidth(int designerWidth){
for(int i=0; i designerWidth){
return true;
}
}
return false;
}
/**
* 改行是否可编辑
* @param row 行号
* @return 第row行可编辑返回true,否则返回false
*/
public boolean isEditable(int row) {
return true;
}
}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java b/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java
new file mode 100644
index 000000000..094fdeb7a
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/parameter/XFormSubmit.java
@@ -0,0 +1 @@
+package com.fr.design.form.parameter;
import com.fr.design.designer.creator.XButton;
import com.fr.design.designer.creator.XCreator;
import com.fr.form.parameter.FormSubmitButton;
import java.awt.*;
/**
* 提交按钮
* @editor zhou
* @since 2012-3-23下午3:36:00
*/
public class XFormSubmit extends XButton {
public XFormSubmit(FormSubmitButton widget, Dimension initSize) {
super(widget, initSize);
}
/**
* 是否有查询按钮
* @param xCreator 控件或容器
* @return 有无查询按钮
*/
public boolean SearchQueryCreators(XCreator xCreator) {
return true;
}
/**
* 该组件是否可以拖入表单主体
* @return 是则返回true
*/
public boolean canEnterIntoAdaptPane(){
return false;
}
@Override
protected String getIconName() {
return "preview_16.png";
}
}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/form/util/XCreatorConstants.java b/designer_form/src/com/fr/design/form/util/XCreatorConstants.java
new file mode 100644
index 000000000..26bf0a049
--- /dev/null
+++ b/designer_form/src/com/fr/design/form/util/XCreatorConstants.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.form.util;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+
+import javax.swing.BorderFactory;
+import javax.swing.border.Border;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class XCreatorConstants {
+
+ private XCreatorConstants() {
+ }
+ public static final String WIDGETNAME = "widgetName";
+ // 描述属性的分类
+ public static final String PROPERTY_CATEGORY = "category";
+ public static final String DEFAULT_GROUP_NAME = "Form-Basic_Properties";
+ public static final Color FORM_BG = new Color(252, 252, 254);
+ // 拖拽标识块的大小
+ public static final int RESIZE_BOX_SIZ = 5;
+ // 拖拽的小方块的内部颜色
+ public static final Color RESIZE_BOX_INNER_COLOR = Color.white;
+ // 拖拽的小方块的边框颜色
+ public static final Color RESIZE_BOX_BORDER_COLOR = new Color(143, 171, 196);
+ // 当前选取的组件的边框线着色
+ public static final Color SELECTION_COLOR = new Color(179, 209, 236);
+ // 设计器区域外边框的颜色和粗细
+ public static final Border AREA_BORDER = BorderFactory.createLineBorder(new Color(224, 224, 255), 0);
+ // 布局拖拽时的颜色
+ public static final Color LAYOUT_HOTSPOT_COLOR = new Color(64, 240, 0);
+ public static final Color LAYOUT_FORBIDDEN_COLOR = new Color(254, 0, 0);
+ //自适应布局拖拽颜色
+ public static final Color FIT_LAYOUT_HOTSPOT_COLOR = new Color(154, 195, 233);
+ // 自适应布局的交叉点渲染颜色
+ public static final Color FIT_LAYOUT_POINT_COLOR = new Color(106, 168, 222);
+ // 格子布局的分割线
+ public static final Color LAYOUT_SEP_COLOR = new Color(210, 210, 210);
+
+ // 伸缩表单操作条的颜色
+ public static final Color OP_COLOR = new Color(157,228,245);
+
+ // 不同粗细的线
+ public static final BasicStroke STROKE = new BasicStroke(2);
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java b/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java
new file mode 100644
index 000000000..229b54943
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/core/FormWidgetOption.java
@@ -0,0 +1 @@
+package com.fr.design.gui.core;
import javax.swing.Icon;
import com.fr.base.BaseUtils;
import com.fr.form.ui.ElementCaseEditor;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WAbsoluteLayout;
import com.fr.form.ui.container.WBorderLayout;
import com.fr.form.ui.container.WCardLayout;
import com.fr.form.ui.container.WFitLayout;
import com.fr.form.ui.container.WHorizontalBoxLayout;
import com.fr.form.ui.container.WParameterLayout;
import com.fr.form.ui.container.WVerticalBoxLayout;
import com.fr.general.Inter;
/**
* Author : Shockway
* Date: 13-6-17
* Time: 上午10:40
*/
public class FormWidgetOption extends WidgetOption {
/**
* 返回名字
* @return 名字
*/
@Override
public String optionName() {
return null;
}
/**
* 返回图标
* @return 图标
*/
@Override
public Icon optionIcon() {
return null;
}
/**
* 组件类
* @return 类
*/
@Override
public Class extends Widget> widgetClass() {
return null;
}
/**
* 返回组件
* @return 控件
*/
@Override
public Widget createWidget() {
return null;
}
/*
* 表单容器
*/
public static WidgetOption[] getFormContainerInstance() {
return new WidgetOption[] { ABSOLUTELAYOUTCONTAINER, BORDERLAYOUTCONTAINER, HORIZONTALBOXLAYOUTCONTAINER, VERTICALBOXLAYOUTCONTAINER,
CARDLAYOUTCONTAINER, FITLAYOUTCONTAINER };
}
/**
* 表单工具栏上的布局
* @return 控件
*/
public static WidgetOption[] getFormLayoutInstance() {
return new WidgetOption[] {CARDLAYOUTCONTAINER};
}
public static final WidgetOption ABSOLUTELAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_AbsoluteLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_absolute.png"),
WAbsoluteLayout.class);
public static final WidgetOption BORDERLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_BorderLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_border.png"),
WBorderLayout.class);
public static final WidgetOption CARDLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_CardLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/card_layout_16.png"),
WCardLayout.class);
public static final WidgetOption HORIZONTALBOXLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_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("FR-Designer_VerticalBoxLayout"), BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"),
WVerticalBoxLayout.class);
public static final WidgetOption FITLAYOUTCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter.getLocText("FR-Designer-Layout_Adaptive_Layout"),
BaseUtils.readIcon("/com/fr/web/images/form/resources/boxlayout_v_16.png"),
WFitLayout.class);
public static final WidgetOption PARAMETERCONTAINER = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Para-Body"), BaseUtils.readIcon("/com/fr/web/images/form/resources/layout_parameter.png"),
WParameterLayout.class);
public static final WidgetOption ELEMENTCASE = WidgetOptionFactory.createByWidgetClass(Inter
.getLocText("FR-Designer_Form-Report"), BaseUtils.readIcon("/com/fr/web/images/form/resources/report_16.png"),
ElementCaseEditor.class);
}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPane.java b/designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPane.java
new file mode 100644
index 000000000..a797f84cd
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPane.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.gui.xpane;
+
+import java.awt.BorderLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import com.fr.base.Utils;
+import com.fr.design.file.HistoryTemplateListPane;
+import com.fr.design.gui.icombobox.UIComboBox;
+import com.fr.design.gui.icontainer.UIScrollPane;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.gui.style.BackgroundNoImagePane;
+import com.fr.design.gui.style.FRFontPane;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.layout.TableLayout;
+import com.fr.design.layout.TableLayoutHelper;
+import com.fr.design.mainframe.JForm;
+import com.fr.design.mainframe.JTemplate;
+import com.fr.design.utils.gui.GUICoreUtils;
+import com.fr.form.ui.LayoutBorderStyle;
+import com.fr.form.ui.WidgetTitle;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.Constants;
+
+/**
+ * CardTagLayoutBorderPane Pane.
+ */
+public class CardTagLayoutBorderPane extends LayoutBorderPane {
+ public CardTagLayoutBorderPane(){
+ initComponents();
+ }
+
+ protected UIScrollPane initRightBottomPane(){
+ this.setFontSizeComboBox(new UIComboBox(FRFontPane.FONT_SIZES));
+ this.setFontNameComboBox(new UIComboBox(Utils.getAvailableFontFamilyNames4Report()));
+ JPanel fontSizeTypePane = new JPanel(new BorderLayout(10,0));
+ fontSizeTypePane.add(this.getFontSizeComboBox(), BorderLayout.CENTER);
+ fontSizeTypePane.add(this.getFontNameComboBox(), BorderLayout.EAST);
+
+ this.setTitleBackgroundPane(new BackgroundNoImagePane());
+
+ double f = TableLayout.FILL;
+ double p = TableLayout.PREFERRED;
+ double[] rowSize = {p,p,p,p,p,p};
+ double[] columnSize = { p, f};
+
+ JPanel rightBottomContentPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Title_Format")), fontSizeTypePane},
+ {new UILabel(""), initFontButtonPane()},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Title_Background")), this.getTitleBackgroundPane()},
+ }, rowSize, columnSize, 10);
+ rightBottomContentPane.setBorder(BorderFactory.createEmptyBorder(15, 12, 10, 12));
+ this.setTitlePane(new UIScrollPane(rightBottomContentPane));
+ this.getTitlePane().setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer-Widget-Style_Title"),null));
+ this.getTitlePane().setVisible(false);
+ return this.getTitlePane();
+ }
+
+ protected void initComponents() {
+
+ this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
+ this.setLayout(FRGUIPaneFactory.createBorderLayout());
+
+ JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ this.add(defaultPane, BorderLayout.CENTER);
+
+ JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ defaultPane.add(centerPane, BorderLayout.CENTER);
+ centerPane.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer-Widget-Style_Preview"), null));
+
+ JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ centerPane.add(borderPane, BorderLayout.CENTER);
+ borderPane.setBorder(BorderFactory.createEmptyBorder(10, 4, 10, 4));
+
+ this.setLayoutBorderPreviewPane(new CardTagLayoutBorderPreviewPane(this.getBorderStyle()));
+
+ borderPane.add(this.getLayoutBorderPreviewPane(), BorderLayout.CENTER);
+
+ JPanel rightPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ defaultPane.add(rightPane, BorderLayout.EAST);
+ rightPane.add(initRightBottomPane(), BorderLayout.CENTER);
+ JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
+ if (!jTemplate.isJWorkBook() && ((JForm)jTemplate).isSelectRootPane()){
+ //界面上表单主体只有背景和透明度可以设置
+ rightPane.add(initBodyRightTopPane(), BorderLayout.NORTH);
+ } else {
+ rightPane.add(initRightTopPane(), BorderLayout.NORTH);
+ }
+ }
+
+
+ public LayoutBorderStyle update() {
+ LayoutBorderStyle style = new LayoutBorderStyle();
+ style.setType(this.getBorderTypeCombo().getSelectedIndex());
+ style.setBorderStyle(this.getBorderStyleCombo().getSelectedIndex());
+ style.setBorder(this.getCurrentLineCombo().getSelectedLineStyle());
+ style.setColor(this.getCurrentLineColorPane().getColor());
+ style.setBackground(this.getBackgroundPane().update());
+ style.setAlpha((float)(this.getNumberDragPane().updateBean()/this.getMaxNumber()));
+
+ WidgetTitle title = style.getTitle() == null ? new WidgetTitle() : style.getTitle();
+ title.setTextObject("title");
+ FRFont frFont = title.getFrFont();
+ frFont = frFont.applySize((Integer)this.getFontSizeComboBox().getSelectedItem());
+ frFont = frFont.applyName(this.getFontNameComboBox().getSelectedItem().toString());
+ frFont = frFont.applyForeground(this.getColorSelectPane().getColor());
+ frFont = updateItalicBold(frFont);
+ int line = this.getUnderline().isSelected() ? this.getUnderlineCombo().getSelectedLineStyle() : Constants.LINE_NONE;
+ frFont = frFont.applyUnderline(line);
+ title.setFrFont(frFont);
+ title.setBackground(this.getTitleBackgroundPane().update());
+ style.setTitle(title);
+ return style;
+ }
+
+
+ protected void populateTitle(){
+ WidgetTitle widgetTitle = this.getBorderStyle() == null ? new WidgetTitle() : this.getBorderStyle().getTitle();
+ widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle;
+ populateFont(widgetTitle);
+ this.getUnderline().addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.getUnderlineCombo().addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+
+ this.getTitleBackgroundPane().populateBean(widgetTitle.getBackground());
+ this.getTitleBackgroundPane().addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ paintPreviewPane();
+ }
+ });
+ paintPreviewPane();
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPreviewPane.java b/designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPreviewPane.java
new file mode 100644
index 000000000..9030ce0aa
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xpane/CardTagLayoutBorderPreviewPane.java
@@ -0,0 +1,14 @@
+package com.fr.design.gui.xpane;
+
+import com.fr.form.ui.LayoutBorderStyle;
+
+/**
+ *
+ * @author focus
+ *
+ */
+public class CardTagLayoutBorderPreviewPane extends LayoutBorderPreviewPane{
+ public CardTagLayoutBorderPreviewPane(LayoutBorderStyle borderStyle) {
+ super(borderStyle,true);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java b/designer_form/src/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java
new file mode 100644
index 000000000..773446f5a
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xpane/FormHyperlinkGroupPane.java
@@ -0,0 +1,30 @@
+package com.fr.design.gui.xpane;
+
+import com.fr.design.gui.controlpane.NameObjectCreator;
+import com.fr.design.gui.controlpane.NameableCreator;
+import com.fr.design.gui.frpane.HyperlinkGroupPane;
+import com.fr.design.form.javascript.FormEmailPane;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.Inter;
+import com.fr.js.EmailJavaScript;
+
+public class FormHyperlinkGroupPane extends HyperlinkGroupPane{
+
+ /**
+ * 生成添加按钮的NameableCreator
+ * 由于表单报表块的单元格超链和单元格条件属性超链中的emailPane都要用表单的emailPane,这里调整下
+ *
+ * @return 返回Nameable按钮数组.
+ */
+ public NameableCreator[] createNameableCreators() {
+ NameableCreator[] creators = super.createNameableCreators();
+ for (int i=0; i namelist = tableDataWrappe.calculateColumnNameList();
+ String[] columnNames = new String[namelist.size()];
+ namelist.toArray(columnNames);
+ valuePane.setEditors(new Editor[]{new OldColumnIndexEditor(columnNames, Inter.getLocText("ColumnName"))}, 1);
+ FormulaEditor formulaEditor = new FormulaEditor(Inter.getLocText("Parameter-Formula"));
+ formulaEditor.setEnabled(true);
+ textPane.setEditors(new Editor[]{new OldColumnIndexEditor(columnNames, Inter.getLocText("ColumnName")), formulaEditor}, 1);
+ } 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
+ this.textPane.populate(tableDataDict.getKeyColumnIndex() + 1);
+ Object value = null;
+ if ((tableDataDict).getFormula() != null) {
+ value = (tableDataDict).getFormula();
+ } else {
+ value = tableDataDict.getValueColumnIndex() + 1;
+ }
+
+ this.valuePane.populate(value);
+ }
+ }
+
+ public TableDataDictionary update() {
+ TableDataDictionary tableDataDict = new TableDataDictionary();
+ Object object = this.valuePane.update();
+ // alex:因为显示到界面上的index是以1为始的,所以要减1
+ // carl:假如这里的序号要变,请考虑6.2的兼容
+ if (object instanceof Integer) {
+ tableDataDict.setValueColumnIndex((Integer) object - 1);
+ } else {
+ tableDataDict.setFormula(((Formula) object));
+ }
+ TableDataWrapper tableDataWrappe = this.treeTableDataComboBox.getSelectedItem();
+ if (tableDataWrappe != null) {
+ tableDataDict.setTableData(new NameTableData(tableDataWrappe.getTableDataName()));
+ tableDataDict.setKeyColumnIndex((Integer) this.textPane.update() - 1);
+ }
+
+ return tableDataDict;
+ }
+
+ @Override
+ protected String title4PopupWindow() {
+ return "Auto Build Tree";
+ }
+
+ @Override
+ public void preview() {
+ TableDataWrapper tableDataWrappe = treeTableDataComboBox.getSelectedItem();
+ if (tableDataWrappe == null) {
+ return;
+ }
+ tableDataWrappe.previewData();
+ }
+
+ @Override
+ 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_form/src/com/fr/design/gui/xpane/LayoutBorderPane.java b/designer_form/src/com/fr/design/gui/xpane/LayoutBorderPane.java
new file mode 100644
index 000000000..d009c3e64
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xpane/LayoutBorderPane.java
@@ -0,0 +1,872 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.gui.xpane;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.GraphHelper;
+import com.fr.base.Utils;
+import com.fr.base.background.GradientBackground;
+import com.fr.design.border.UIRoundedBorder;
+import com.fr.design.constants.LayoutConstants;
+import com.fr.design.constants.UIConstants;
+import com.fr.design.dialog.BasicPane;
+import com.fr.design.file.HistoryTemplateListPane;
+import com.fr.design.formula.TinyFormulaPane;
+import com.fr.design.gui.frpane.UINumberDragPane;
+import com.fr.design.gui.ibutton.*;
+import com.fr.design.gui.icombobox.LineComboBox;
+import com.fr.design.gui.icombobox.UIComboBox;
+import com.fr.design.gui.icontainer.UIScrollPane;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.gui.style.BackgroundNoImagePane;
+import com.fr.design.gui.style.BackgroundSpecialPane;
+import com.fr.design.gui.style.FRFontPane;
+import com.fr.design.layout.FRGUIPaneFactory;
+import com.fr.design.layout.TableLayout;
+import com.fr.design.layout.TableLayoutHelper;
+import com.fr.design.layout.VerticalFlowLayout;
+import com.fr.design.mainframe.JForm;
+import com.fr.design.mainframe.JTemplate;
+import com.fr.design.utils.gui.GUICoreUtils;
+import com.fr.form.ui.LayoutBorderStyle;
+import com.fr.form.ui.WidgetTitle;
+import com.fr.general.Background;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.Constants;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.plaf.basic.BasicToggleButtonUI;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.geom.RoundRectangle2D;
+
+/**
+ * WLayoutBorder Pane.
+ */
+public class LayoutBorderPane extends BasicPane {
+
+ //圆角 7.1.1暂时不做
+ private static final int NO_BORDERS = 0;
+ private static final int RIGHTANGLE_BORDERS = 1;
+ private static final int ROUNDED_BORDERS = 2;
+ private static final int MAX_WIDTH = 220;
+
+ private LayoutBorderStyle borderStyle = new LayoutBorderStyle();
+
+ private LayoutBorderPreviewPane layoutBorderPreviewPane;
+ //边框类型
+ private UIComboBox borderTypeCombo;
+ //渲染风格
+ private UIComboBox borderStyleCombo;
+ //边框粗细
+ private LineComboBox currentLineCombo;
+
+ //边框颜色
+ private UIColorButton currentLineColorPane;
+ //主体背景
+ private BackgroundSpecialPane backgroundPane;
+ //透明度
+ private UINumberDragPane numberDragPane;
+ //标题内容
+ private TinyFormulaPane formulaPane;
+ //标题格式
+ private UIComboBox fontNameComboBox;
+ private UIComboBox fontSizeComboBox;
+ private UIColorButton colorSelectPane;
+ private UIToggleButton bold;
+ private UIToggleButton italic;
+ private UIToggleButton underline;
+ private LineComboBox underlineCombo;
+ //对齐方式
+ private UIButtonGroup hAlignmentPane;
+ //标题背景
+ private BackgroundNoImagePane titleBackgroundPane;
+
+ private UIScrollPane titlePane;
+
+ private int minNumber = 0;
+ private double maxNumber = 100;
+ private int iconWidth = 32;
+
+ public LayoutBorderStyle getBorderStyle() {
+ return borderStyle;
+ }
+
+ public void setBorderStyle(LayoutBorderStyle borderStyle) {
+ this.borderStyle = borderStyle;
+ }
+
+ public LayoutBorderPreviewPane getLayoutBorderPreviewPane() {
+ return layoutBorderPreviewPane;
+ }
+
+ public void setLayoutBorderPreviewPane(
+ LayoutBorderPreviewPane layoutBorderPreviewPane) {
+ this.layoutBorderPreviewPane = layoutBorderPreviewPane;
+ }
+
+ public UIComboBox getBorderTypeCombo() {
+ return borderTypeCombo;
+ }
+
+ public void setBorderTypeCombo(UIComboBox borderTypeCombo) {
+ this.borderTypeCombo = borderTypeCombo;
+ }
+
+ public UIComboBox getBorderStyleCombo() {
+ return borderStyleCombo;
+ }
+
+ public void setBorderStyleCombo(UIComboBox borderStyleCombo) {
+ this.borderStyleCombo = borderStyleCombo;
+ }
+
+ public LineComboBox getCurrentLineCombo() {
+ return currentLineCombo;
+ }
+
+ public void setCurrentLineCombo(LineComboBox currentLineCombo) {
+ this.currentLineCombo = currentLineCombo;
+ }
+
+ public UIColorButton getCurrentLineColorPane() {
+ return currentLineColorPane;
+ }
+
+ public void setCurrentLineColorPane(UIColorButton currentLineColorPane) {
+ this.currentLineColorPane = currentLineColorPane;
+ }
+
+
+ public BackgroundSpecialPane getBackgroundPane() {
+ return backgroundPane;
+ }
+
+ public void setBackgroundPane(BackgroundSpecialPane backgroundPane) {
+ this.backgroundPane = backgroundPane;
+ }
+
+ public UINumberDragPane getNumberDragPane() {
+ return numberDragPane;
+ }
+
+ public void setNumberDragPane(UINumberDragPane numberDragPane) {
+ this.numberDragPane = numberDragPane;
+ }
+
+ public TinyFormulaPane getFormulaPane() {
+ return formulaPane;
+ }
+
+ public void setFormulaPane(TinyFormulaPane formulaPane) {
+ this.formulaPane = formulaPane;
+ }
+
+ public UIComboBox getFontNameComboBox() {
+ return fontNameComboBox;
+ }
+
+ public void setFontNameComboBox(UIComboBox fontNameComboBox) {
+ this.fontNameComboBox = fontNameComboBox;
+ }
+
+ public UIComboBox getFontSizeComboBox() {
+ return fontSizeComboBox;
+ }
+
+ public void setFontSizeComboBox(UIComboBox fontSizeComboBox) {
+ this.fontSizeComboBox = fontSizeComboBox;
+ }
+
+ public UIColorButton getColorSelectPane() {
+ return colorSelectPane;
+ }
+
+ public void setColorSelectPane(UIColorButton colorSelectPane) {
+ this.colorSelectPane = colorSelectPane;
+ }
+
+ public UIToggleButton getBold() {
+ return bold;
+ }
+
+ public void setBold(UIToggleButton bold) {
+ this.bold = bold;
+ }
+
+ public UIToggleButton getItalic() {
+ return italic;
+ }
+
+ public void setItalic(UIToggleButton italic) {
+ this.italic = italic;
+ }
+
+ public UIToggleButton getUnderline() {
+ return underline;
+ }
+
+ public void setUnderline(UIToggleButton underline) {
+ this.underline = underline;
+ }
+
+ public LineComboBox getUnderlineCombo() {
+ return underlineCombo;
+ }
+
+ public void setUnderlineCombo(LineComboBox underlineCombo) {
+ this.underlineCombo = underlineCombo;
+ }
+
+ public UIButtonGroup gethAlignmentPane() {
+ return hAlignmentPane;
+ }
+
+ public void sethAlignmentPane(UIButtonGroup hAlignmentPane) {
+ this.hAlignmentPane = hAlignmentPane;
+ }
+
+ public BackgroundNoImagePane getTitleBackgroundPane() {
+ return titleBackgroundPane;
+ }
+
+ public void setTitleBackgroundPane(BackgroundNoImagePane titleBackgroundPane) {
+ this.titleBackgroundPane = titleBackgroundPane;
+ }
+
+ public UIScrollPane getTitlePane() {
+ return titlePane;
+ }
+
+ public void setTitlePane(UIScrollPane titlePane) {
+ this.titlePane = titlePane;
+ }
+
+ public int getMinNumber() {
+ return minNumber;
+ }
+
+ public void setMinNumber(int minNumber) {
+ this.minNumber = minNumber;
+ }
+
+ public double getMaxNumber() {
+ return maxNumber;
+ }
+
+ public void setMaxNumber(double maxNumber) {
+ this.maxNumber = maxNumber;
+ }
+
+ public int getIconWidth() {
+ return iconWidth;
+ }
+
+ public void setIconWidth(int iconWidth) {
+ this.iconWidth = iconWidth;
+ }
+
+ public final static int[] BORDER_LINE_STYLE_ARRAY = new int[]{
+ Constants.LINE_NONE,
+ Constants.LINE_THIN, //1px
+ Constants.LINE_MEDIUM, //2px
+ Constants.LINE_THICK, //3px
+ };
+
+ public final static String[] BORDER_TYPE = new String[]{Inter.getLocText("FR-Designer-Widget-Style_Standard"), Inter.getLocText("FR-Designer-Widget-Style_Title")};
+ public final static String[] BORDER_STYLE= new String[]{Inter.getLocText("FR-Designer-Widget-Style_Common"), Inter.getLocText("FR-Designer-Widget-Style_Shadow")};
+
+ private final static Dimension BUTTON_SIZE = new Dimension(24, 20);
+
+ public LayoutBorderPane() {
+ this.initComponents();
+ }
+
+ protected void initComponents() {
+ this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
+ this.setLayout(FRGUIPaneFactory.createBorderLayout());
+
+ JPanel defaultPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ this.add(defaultPane, BorderLayout.CENTER);
+
+ JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ defaultPane.add(centerPane, BorderLayout.CENTER);
+ centerPane.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer-Widget-Style_Preview"), null));
+
+ JPanel borderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ centerPane.add(borderPane, BorderLayout.CENTER);
+ borderPane.setBorder(BorderFactory.createEmptyBorder(10, 4, 10, 4));
+
+ layoutBorderPreviewPane = new LayoutBorderPreviewPane(borderStyle);
+
+ borderPane.add(layoutBorderPreviewPane, BorderLayout.CENTER);
+
+ JPanel rightPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ defaultPane.add(rightPane, BorderLayout.EAST);
+ rightPane.add(initRightBottomPane(), BorderLayout.CENTER);
+ JTemplate jTemplate = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
+ if (!jTemplate.isJWorkBook() && ((JForm)jTemplate).isSelectRootPane()){
+ //界面上表单主体只有背景和透明度可以设置
+ rightPane.add(initBodyRightTopPane(), BorderLayout.NORTH);
+ } else {
+ rightPane.add(initRightTopPane(), BorderLayout.NORTH);
+ }
+
+
+ }
+
+ protected UIScrollPane initRightTopPane(){
+ this.borderTypeCombo = new UIComboBox(BORDER_TYPE);
+ this.borderTypeCombo.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ if(borderTypeCombo.getSelectedIndex() == 0){
+ titlePane.setVisible(false);
+ } else {
+ titlePane.setVisible(true);
+ currentLineCombo.setSelectedItem(Constants.LINE_THIN);
+ }
+ }
+ });
+ this.borderStyleCombo = new UIComboBox(BORDER_STYLE);
+ this.currentLineCombo = new LineComboBox(BORDER_LINE_STYLE_ARRAY);
+ this.currentLineColorPane = new UIColorButton(null);
+ currentLineColorPane.setUI(getButtonUI(currentLineColorPane));
+ currentLineColorPane.set4ToolbarButton();
+ currentLineColorPane.setPreferredSize(new Dimension(20,20));
+ JPanel buttonPane = new JPanel(new BorderLayout());
+ buttonPane.add(currentLineColorPane,BorderLayout.WEST);
+ backgroundPane = new BackgroundSpecialPane();
+ JPanel transparencyPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ this.numberDragPane = new UINumberDragPane(0,100);
+ transparencyPane.add(numberDragPane, BorderLayout.CENTER);
+ transparencyPane.add(new UILabel(" %"), BorderLayout.EAST);
+
+ double p = TableLayout.PREFERRED;
+ double[] rowSize = {p,p,p,p,p,p,p};
+ double[] columnSize = { p, MAX_WIDTH};
+ JPanel rightTopContentPane = TableLayoutHelper.createCommonTableLayoutPane(new JComponent[][]{
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Frame_Style")), borderTypeCombo},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Render_Style")), borderStyleCombo},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Border_Line")), currentLineCombo},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Border_Color")), buttonPane},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Body_Background")), backgroundPane},
+ {new UILabel(""),new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Alpha"))},
+ {new UILabel(""),transparencyPane},
+ }, rowSize, columnSize, 10);
+ rightTopContentPane.setBorder(BorderFactory.createEmptyBorder(15, 12, 10, 12));
+ UIScrollPane rightTopPane = new UIScrollPane(rightTopContentPane);
+ rightTopPane.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer-Widget-Style_Frame"),null));
+ rightTopPane.setPreferredSize(rightTopPane.getPreferredSize());
+ return rightTopPane;
+ }
+
+
+
+
+ protected JPanel initBodyRightTopPane(){
+ this.borderTypeCombo = new UIComboBox(BORDER_TYPE);
+ this.borderStyleCombo = new UIComboBox(BORDER_STYLE);
+ this.currentLineCombo = new LineComboBox(BORDER_LINE_STYLE_ARRAY);
+ this.currentLineColorPane = new UIColorButton(null);
+
+ backgroundPane = new BackgroundSpecialPane();
+ JPanel transparencyPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ this.numberDragPane = new UINumberDragPane(0,100);
+ transparencyPane.add(numberDragPane, BorderLayout.CENTER);
+ transparencyPane.add(new UILabel(" %"), BorderLayout.EAST);
+
+ double f = TableLayout.FILL;
+ double p = TableLayout.PREFERRED;
+ double[] rowSize = {p,p,p};
+ double[] columnSize = { p, f};
+ JPanel rightTopContentPane = TableLayoutHelper.createCommonTableLayoutPane(new JComponent[][]{
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Body_Background")), backgroundPane},
+ {new UILabel(""),new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Alpha"))},
+ {new UILabel(""),transparencyPane},
+ }, rowSize, columnSize, 10);
+ rightTopContentPane.setBorder(BorderFactory.createEmptyBorder(15, 12, 10, 6));
+ JPanel bodyRightTopPane =FRGUIPaneFactory.createBorderLayout_S_Pane();
+ bodyRightTopPane.add(rightTopContentPane,BorderLayout.CENTER);
+ bodyRightTopPane.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer-Widget-Style_Frame"),null));
+ return bodyRightTopPane;
+ }
+
+ protected UIScrollPane initRightBottomPane(){
+ formulaPane = new TinyFormulaPane();
+ fontSizeComboBox = new UIComboBox(FRFontPane.FONT_SIZES);
+ fontNameComboBox = new UIComboBox(Utils.getAvailableFontFamilyNames4Report());
+ fontNameComboBox.setPreferredSize(new Dimension(160, 30));
+ JPanel fontSizeTypePane = new JPanel(new BorderLayout(10,0));
+ fontSizeTypePane.add(fontSizeComboBox, BorderLayout.CENTER);
+ fontSizeTypePane.add(fontNameComboBox, BorderLayout.EAST);
+
+ Icon[] hAlignmentIconArray = {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[] hAlignment = new Integer[]{Constants.LEFT, Constants.CENTER, Constants.RIGHT};
+ hAlignmentPane = new UIButtonGroup(hAlignmentIconArray, hAlignment);
+ hAlignmentPane.setAllToolTips(new String[]{Inter.getLocText("FR-Designer-StyleAlignment_Left")
+ , Inter.getLocText("FR-Designer-StyleAlignment_Center"), Inter.getLocText("FR-Designer-StyleAlignment_Right")});
+ JPanel hPaneContainer = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ hPaneContainer.add(hAlignmentPane);
+
+ titleBackgroundPane = new BackgroundNoImagePane();
+
+ double p = TableLayout.PREFERRED;
+ double[] rowSize = {p,p,p,p,p,p};
+ double[] columnSize = { p, MAX_WIDTH};
+
+ JPanel rightBottomContentPane = TableLayoutHelper.createCommonTableLayoutPane( new JComponent[][]{
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Title_Content")), formulaPane},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Title_Format")), fontSizeTypePane},
+ {new UILabel(""), initFontButtonPane()},
+ {new UILabel(Inter.getLocText("FR-Designer_Alignment-Style")), hPaneContainer},
+ {new UILabel(Inter.getLocText("FR-Designer-Widget-Style_Title_Background")), titleBackgroundPane},
+ }, rowSize, columnSize, 10);
+ rightBottomContentPane.setBorder(BorderFactory.createEmptyBorder(15, 12, 10, 12));
+ titlePane =new UIScrollPane(rightBottomContentPane);
+ titlePane.setBorder(GUICoreUtils.createTitledBorder(Inter.getLocText("FR-Designer-Widget-Style_Title"),null));
+ titlePane.setVisible(false);
+ return titlePane;
+ }
+
+
+
+ protected JPanel initFontButtonPane(){
+ colorSelectPane = new UIColorButton();
+ bold = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/bold.png"));
+ italic = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/italic.png"));
+ underline = new UIToggleButton(BaseUtils.readIcon("/com/fr/design/images/m_format/cellstyle/underline.png"));
+ bold.setPreferredSize(BUTTON_SIZE);
+ italic.setPreferredSize(BUTTON_SIZE);
+ underline.setPreferredSize(BUTTON_SIZE);
+ underline.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ underlineCombo.setVisible(underline.isSelected());
+ }
+ });
+ underlineCombo = new LineComboBox(UIConstants.BORDER_LINE_STYLE_ARRAY);
+ Component[] components_font = new Component[]{
+ colorSelectPane, italic, bold, underline
+ };
+ JPanel buttonPane = new JPanel(new BorderLayout());
+ buttonPane.add(GUICoreUtils.createFlowPane(components_font, FlowLayout.LEFT, LayoutConstants.HGAP_SMALL));
+ JPanel combinePane = FRGUIPaneFactory.createBorderLayout_S_Pane();
+ combinePane.add(buttonPane, BorderLayout.WEST);
+ combinePane.add(underlineCombo, BorderLayout.CENTER);
+ initAllNames();
+ setToolTips();
+ return combinePane;
+
+ }
+
+ protected void initAllNames() {
+ fontNameComboBox.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Family"));
+ fontSizeComboBox.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Size"));
+ colorSelectPane.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Foreground"));
+ italic.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Italic"));
+ bold.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Bold"));
+ underline.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Underline"));
+ underlineCombo.setGlobalName(Inter.getLocText("FR-Designer-FRFont_Line_Style"));
+ }
+
+ protected void setToolTips() {
+ colorSelectPane.setToolTipText(Inter.getLocText("FR-Designer-FRFont_Foreground"));
+ italic.setToolTipText(Inter.getLocText("FR-Designer-FRFont_Italic"));
+ bold.setToolTipText(Inter.getLocText("FR-Designer-FRFont_Bold"));
+ underline.setToolTipText(Inter.getLocText("FR-Designer-FRFont_Underline"));
+ }
+
+
+ public LayoutBorderStyle update() {
+ LayoutBorderStyle style = new LayoutBorderStyle();
+ style.setType(borderTypeCombo.getSelectedIndex());
+ style.setBorderStyle(borderStyleCombo.getSelectedIndex());
+ style.setBorder(currentLineCombo.getSelectedLineStyle());
+ style.setColor(currentLineColorPane.getColor());
+ style.setBackground(backgroundPane.update());
+ style.setAlpha((float)(numberDragPane.updateBean()/maxNumber));
+
+ WidgetTitle title = style.getTitle() == null ? new WidgetTitle() : style.getTitle();
+ title.setTextObject(formulaPane.updateBean());
+ FRFont frFont = title.getFrFont();
+ frFont = frFont.applySize((Integer)fontSizeComboBox.getSelectedItem());
+ frFont = frFont.applyName(fontNameComboBox.getSelectedItem().toString());
+ frFont = frFont.applyForeground(colorSelectPane.getColor());
+ frFont = updateItalicBold(frFont);
+ int line = underline.isSelected() ? this.underlineCombo.getSelectedLineStyle() : Constants.LINE_NONE;
+ frFont = frFont.applyUnderline(line);
+ title.setFrFont(frFont);
+ title.setPosition((Integer)hAlignmentPane.getSelectedItem());
+ title.setBackground(titleBackgroundPane.update());
+ style.setTitle(title);
+ return style;
+ }
+
+ protected FRFont updateItalicBold(FRFont frFont) {
+ int italic_bold = frFont.getStyle();
+ boolean isItalic = italic_bold == Font.ITALIC || italic_bold == (Font.BOLD + Font.ITALIC);
+ boolean isBold = italic_bold == Font.BOLD || italic_bold == (Font.BOLD + Font.ITALIC);
+ if (italic.isSelected() && !isItalic) {
+ italic_bold += Font.ITALIC;
+ } else if (!italic.isSelected() && isItalic) {
+ italic_bold -= Font.ITALIC;
+ }
+ frFont = frFont.applyStyle(italic_bold);
+ if (bold.isSelected() && !isBold) {
+ italic_bold += Font.BOLD;
+ } else if (!bold.isSelected() && isBold) {
+ italic_bold -= Font.BOLD;
+ }
+ frFont = frFont.applyStyle(italic_bold);
+ return frFont;
+ }
+
+ public void populate(LayoutBorderStyle style) {
+ if(this.borderStyle == null) {
+ borderStyle = new LayoutBorderStyle();
+ }
+ this.borderStyle.setStyle(style);
+
+ populateBorder();
+
+ populateTitle();
+
+ }
+
+ protected void populateBorder(){
+ this.borderTypeCombo.setSelectedIndex(borderStyle.getType());
+ this.borderTypeCombo.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.borderStyleCombo.setSelectedIndex(borderStyle.getBorderStyle());
+ this.borderStyleCombo.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.currentLineCombo.setSelectedLineStyle(borderStyle.getBorder());
+ this.currentLineCombo.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.currentLineColorPane.setColor(borderStyle.getColor());
+ currentLineColorPane.addColorChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.backgroundPane.populateBean(borderStyle.getBackground());
+ this.backgroundPane.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ paintPreviewPane();
+ }
+ });
+ numberDragPane.populateBean(borderStyle.getAlpha() * maxNumber);
+ }
+
+ protected void populateTitle(){
+ WidgetTitle widgetTitle = borderStyle == null ? new WidgetTitle() : borderStyle.getTitle();
+ widgetTitle = widgetTitle == null ? new WidgetTitle() : widgetTitle;
+
+ populateFourmula(widgetTitle);
+ populateFont(widgetTitle);
+
+ underline.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.underlineCombo.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+
+ hAlignmentPane.setSelectedItem(widgetTitle.getPosition());
+ hAlignmentPane.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ paintPreviewPane();
+ }
+ });
+
+
+
+ titleBackgroundPane.populateBean(widgetTitle.getBackground());
+ this.titleBackgroundPane.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ paintPreviewPane();
+ }
+ });
+ paintPreviewPane();
+ }
+
+ protected void populateFont(WidgetTitle widgetTitle){
+ FRFont frFont = widgetTitle.getFrFont();
+ this.fontSizeComboBox.setSelectedItem(frFont.getSize());
+ this.fontSizeComboBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.fontNameComboBox.setSelectedItem(frFont.getFamily());
+ this.fontNameComboBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.colorSelectPane.setColor(frFont.getForeground());
+ colorSelectPane.addColorChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ paintPreviewPane();
+ }
+ });
+ this.colorSelectPane.repaint();
+ bold.setSelected(frFont.isBold());
+ bold.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ paintPreviewPane();
+ }
+ });
+ italic.setSelected(frFont.isItalic());
+ italic.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ paintPreviewPane();
+ }
+ });
+
+ int line = frFont.getUnderline();
+ if (line == Constants.LINE_NONE) {
+ underline.setSelected(false);
+ underlineCombo.setVisible(false);
+ } else {
+ underline.setSelected(true);
+ underlineCombo.setVisible(true);
+ this.underlineCombo.setSelectedLineStyle(line);
+ }
+ }
+
+ protected void paintPreviewPane(){
+ layoutBorderPreviewPane.repaint(update());
+ }
+
+ protected UIButtonUI getButtonUI(final UIColorButton uiColorButton) {
+ return new UIButtonUI() {
+
+ public void paint(Graphics g, JComponent c) {
+ UIButton b = (UIButton) c;
+ g.setColor(Color.black);
+ GraphHelper.draw(g, new RoundRectangle2D.Double(1, 1, b.getWidth() - 2, b.getHeight() - 2, 0, 0), 1);
+
+ if (b.getModel().isEnabled()) {
+ g.setColor(uiColorButton.getColor());
+ } else {
+ g.setColor(new Color(Utils.filterRGB(uiColorButton.getColor().getRGB(), 50)));
+ }
+ g.fillRect(2, 2, b.getWidth() - 3, b.getHeight() - 3);
+ }
+ };
+ }
+
+
+ private void populateFourmula(WidgetTitle widgetTitle) {
+ this.formulaPane.populateBean(widgetTitle.getTextObject().toString());
+ this.formulaPane.getUITextField().getDocument()
+ .addDocumentListener(new DocumentListener() {
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ paintPreviewPane();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ paintPreviewPane();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ paintPreviewPane();
+ }
+ });
+ }
+
+
+ protected JPanel createVerButtonPane(JToggleButton noBorder, String text) {
+ JPanel verPane = new JPanel();
+ verPane.setLayout(new VerticalFlowLayout(VerticalFlowLayout.CENTER, 2, 2));
+ verPane.add(noBorder);
+ verPane.add(new UILabel(text));
+
+ return verPane;
+ }
+
+ protected class VerButtonPane extends JPanel {
+
+ JToggleButton noBorder;
+ BorderButton normalBorder;
+ BorderButton RoundedBorder;
+ ButtonGroup group;
+
+ private VerButtonPane () {
+ setLayout(new FlowLayout(FlowLayout.CENTER));
+ setBorder(BorderFactory.createEmptyBorder(0, 0, 4, 0));
+ group = new ButtonGroup();
+ noBorder = new BorderButton(NO_BORDERS);
+ normalBorder = new BorderButton(RIGHTANGLE_BORDERS);
+ RoundedBorder = new BorderButton(ROUNDED_BORDERS);
+ group.add(noBorder);
+ group.add(normalBorder);
+ group.add(RoundedBorder);
+
+// add(createVerButtonPane(noBorder, Inter.getLocText("None")));
+// add(createVerButtonPane(normalBorder, Inter.getLocText("Border-Style-Normal")));
+// add(createVerButtonPane(RoundedBorder, Inter.getLocText("Border-Style-Radius")));
+ }
+
+ public void populate(LayoutBorderStyle style) {
+ if(style.getBorder() == Constants.LINE_NONE) {
+ group.setSelected(noBorder.getModel(), true);
+ } else if(style.isCorner()) {
+ group.setSelected(RoundedBorder.getModel(), true);
+ } else {
+ group.setSelected(normalBorder.getModel(), true);
+ }
+ }
+ }
+
+ private class BorderButton extends JToggleButton {
+ private BorderButton(int border) {
+ super();
+ this.setIcon(new BorderButtonIcon(border));
+ addBorderActionListener(border);
+ setPreferredSize(new Dimension(32, 32));
+ this.setBorder(new UIRoundedBorder(new Color(220, 220, 220), 1, 5));
+ this.setRolloverEnabled(true);
+ }
+
+ @Override
+ public Border getBorder() {
+ ButtonModel model = getModel();
+ if (this.isSelected()) {
+ return null;
+ }
+ if (isRolloverEnabled() && model.isRollover()) {
+ return new UIRoundedBorder(new Color(148, 148, 148), 1, 5);
+ }
+ return super.getBorder();
+ }
+
+ @Override
+ public void updateUI() {
+ setUI(new BorderToggleButtonUI());
+ }
+
+ private void addBorderActionListener(final int border) {
+ addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ae) {
+ if (border == 0) {
+ borderStyle.reset();
+ } else {
+ borderStyle.setColor(currentLineColorPane.getColor());
+ borderStyle.setBorder(currentLineCombo.getSelectedLineStyle());
+ borderStyle.setCorner(border != RIGHTANGLE_BORDERS);
+ }
+
+ layoutBorderPreviewPane.repaint();
+ }
+ });
+
+ }
+ }
+
+ private class BorderToggleButtonUI extends BasicToggleButtonUI {
+
+ @Override
+ public void paint(Graphics g, JComponent c) {
+ paintBackground(g, (AbstractButton) c);
+ super.paint(g, c);
+ }
+
+ private void paintBackground(Graphics g, AbstractButton b) {
+ if (b.isContentAreaFilled()) {
+ Dimension size = b.getSize();
+ Background background = new GradientBackground(new Color(247, 247, 247), new Color(228, 228, 228),
+ GradientBackground.TOP2BOTTOM);
+ background.paint(g, new RoundRectangle2D.Double(2, 2, size.width - 4, size.height - 4, 5, 5));
+ }
+ }
+
+ private void paintBorder(Graphics g, Color lineColor, int width, int height) {
+ Graphics2D g2d = (Graphics2D) g;
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2d.setColor(lineColor);
+ g2d.drawRoundRect(0, 0, width - 1, height - 1, 5, 5);
+ g2d.setColor(Color.white);
+ g2d.drawRoundRect(1, 1, width - 3, height - 3, 5, 5);
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
+ }
+
+ @Override
+ protected void paintButtonPressed(Graphics g, AbstractButton b) {
+ Dimension size = b.getSize();
+ paintBorder(g, new Color(78,143,203), size.height, size.width);
+ }
+ }
+
+ // Icon to display in shortcut setting buttons
+ private class BorderButtonIcon implements Icon {
+ private int display;
+
+ private BorderButtonIcon(int display) {
+ this.display = display;
+ }
+
+ public int getIconWidth() {
+ return iconWidth;
+ }
+
+ public int getIconHeight() {
+ return iconWidth;
+ }
+
+ public void paintIcon(Component c, Graphics g, int x, int y) {
+ if (display == LayoutBorderPane.RIGHTANGLE_BORDERS) {
+ g.setColor(Color.black);
+ g.drawRect(3, 3, this.getIconWidth() - 7, this.getIconHeight() - 7);
+ } else if (display == LayoutBorderPane.ROUNDED_BORDERS) {
+ g.setColor(Color.black);
+ g.drawRoundRect(3, 3, this.getIconWidth() - 7, this.getIconHeight() - 7, 6, 6);
+ }
+ }
+ }
+
+ @Override
+ protected String title4PopupWindow() {
+ return Inter.getLocText("FR-Designer-Widget_Style");
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xpane/LayoutBorderPreviewPane.java b/designer_form/src/com/fr/design/gui/xpane/LayoutBorderPreviewPane.java
new file mode 100644
index 000000000..9433cac78
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xpane/LayoutBorderPreviewPane.java
@@ -0,0 +1,178 @@
+package com.fr.design.gui.xpane;
+
+import com.fr.base.FRContext;
+import com.fr.base.GraphHelper;
+import com.fr.base.ScreenResolution;
+import com.fr.base.background.ColorBackground;
+import com.fr.design.designer.creator.cardlayout.XCardSwitchButton;
+import com.fr.design.gui.itextarea.UITextArea;
+import com.fr.form.ui.LayoutBorderStyle;
+import com.fr.form.ui.WidgetTitle;
+import com.fr.general.Background;
+import com.fr.general.FRFont;
+import com.fr.general.Inter;
+import com.fr.stable.Constants;
+
+import javax.swing.*;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Rectangle2D.Double;
+import java.awt.geom.RoundRectangle2D;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: zx
+ * Date: 14-9-18
+ * Time: 下午3:31
+ */
+public class LayoutBorderPreviewPane extends JPanel{
+ private titlePreviewPane jp;
+ private LayoutBorderStyle borderStyle;
+ private int smallGAP = 5;
+ private int GAP = 10;
+ private boolean isTabLayout;
+ private static final String TAB_ZERO = "0";
+ private static final String TAB_ONE = "1";
+
+ /**
+ * 是否为tab布局
+ * @return 是否为tab布局
+ */
+ public boolean isTagLayout() {
+ return isTabLayout;
+ }
+
+ public void setTagLayout(boolean isTagLayout) {
+ this.isTabLayout = isTagLayout;
+ }
+
+ public LayoutBorderPreviewPane(LayoutBorderStyle borderStyle) {
+ this.borderStyle = borderStyle;
+ repaint();
+ jp = new titlePreviewPane();
+ add(jp);
+ }
+
+ public LayoutBorderPreviewPane(LayoutBorderStyle borderStyle,boolean isTabLayout) {
+ this(borderStyle);
+ this.isTabLayout = true;
+ }
+
+ /**
+ * 重新画
+ * @param borderStyle 样式
+ */
+ public void repaint(LayoutBorderStyle borderStyle){
+ this.borderStyle = borderStyle;
+ super.repaint();
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ Background background = borderStyle.getBackground();
+ if (background != null) {
+ Shape shape = new Rectangle2D.Double(smallGAP, smallGAP, this.getWidth() - GAP, this.getHeight() - GAP);
+ background.paint(g, shape);
+ } else {
+ g.setColor(Color.white);
+ g.fillRect(smallGAP, smallGAP, this.getWidth() - GAP, this.getHeight() - GAP);
+ }
+
+ updateBorders(g);
+
+ }
+
+ private void updateBorders(Graphics g) {
+ if(borderStyle != null){
+ int height = borderStyle.getTitle().getFrFont().getSize() + GAP;
+ jp.setPreferredSize(new Dimension(getWidth() - GAP, height));
+ jp.setBounds(smallGAP,smallGAP, getWidth() - GAP, height);
+ borderStyle.paint(g, new Rectangle2D.Double(smallGAP, smallGAP, getWidth() - GAP, getHeight() - GAP));
+ jp.setFontObject(borderStyle.getTitle().getFrFont());
+ jp.setVisible(borderStyle.getType() == LayoutBorderStyle.TITLE);
+
+ }
+ }
+
+ private class titlePreviewPane extends UITextArea {
+ private FRFont frFont = null;
+
+ public titlePreviewPane() {
+ frFont = FRContext.getDefaultValues().getFRFont();
+ }
+
+ public void paintComponent(Graphics g) {
+ Graphics2D g2d = (Graphics2D) g;
+ Dimension d = getSize();
+ g2d.setColor(getBackground());
+ GraphHelper.fillRect(g2d, 0, 0, d.width, d.height);
+ if (frFont == null) {
+ return;
+ }
+ FontMetrics fm = getFontMetrics(frFont);
+ int resolution = ScreenResolution.getScreenResolution();
+ if(this.isEnabled()) {
+ g2d.setColor(frFont.getForeground());
+ } else {
+ g2d.setColor(new Color(237, 237, 237));
+ }
+ g2d.setFont(frFont.applyResolutionNP(resolution));
+ WidgetTitle title = borderStyle.getTitle();
+ String paintText = title.getTextObject().toString();
+ int startX1 = 0;
+ int startY = 0;
+ if(!isTabLayout){
+ startX1 = (d.width - fm.stringWidth(paintText)) / 2;
+ startY = (d.height - fm.getHeight()) / 2 + fm.getAscent();
+ if (title.getPosition() == Constants.LEFT){
+ startX1 = smallGAP;
+ } else if (title.getPosition() == Constants.RIGHT){
+ startX1 = d.width - fm.stringWidth(paintText) - smallGAP - fm.getMaxAdvance();
+ }
+ Background background = title.getBackground();
+ if (background != null) {
+ Shape shape = new Rectangle2D.Double(0, 0, this.getWidth(), this.getHeight());
+ background.paint(g, shape);
+ }
+ GraphHelper.drawString(g2d, paintText, startX1, startY);
+ }else{
+ startX1 = (d.width/2 - fm.stringWidth(paintText)) / 2;
+ startY = (d.height - fm.getHeight()) / 2 + fm.getAscent();
+ drawTabBack(g2d,g,title,fm,startX1,startY);
+ }
+ g.setColor(borderStyle.getColor());
+ int line = GraphHelper.getLineStyleSize(borderStyle.getBorder());
+ Double double1 = new Rectangle2D.Double(0, getHeight()-1, getWidth(), getHeight());
+ double x = double1.getX() + (line == 1 ? 1 : 2) - line - 1;
+ double y = double1.getY() + (line == 1 ? 1 : 2) - line ;
+ RoundRectangle2D.Double double2 = new RoundRectangle2D.Double(x, y, double1.getWidth() + line, double1.getHeight() + line, 0, 0);
+ GraphHelper.draw(g,double2, borderStyle.getBorder());
+ }
+
+ private void drawTabBack(Graphics2D g2d,Graphics g,WidgetTitle title,FontMetrics fm,int startX1,int startY){
+ Dimension d = getSize();
+ String paintText = Inter.getLocText("FR-Designer_Title")+TAB_ZERO;
+
+ Background rightBack = ColorBackground.getInstance(XCardSwitchButton.CHOOSED_GRAL);
+ Shape right = new Rectangle2D.Double(this.getWidth()/2, 0, this.getWidth()/2, this.getHeight());
+ rightBack.paint(g, right);
+ String rightLabel = Inter.getLocText("FR-Designer_Title")+TAB_ONE;
+ GraphHelper.drawString(g2d, rightLabel, (d.width/2 - fm.stringWidth(paintText)) / 2+d.width/2, startY);
+ Background background = title.getBackground();
+ if (background != null) {
+ Shape shape = new Rectangle2D.Double(0, 0, this.getWidth()/2, this.getHeight());
+ background.paint(g, shape);
+ }
+ GraphHelper.drawString(g2d, paintText, startX1, startY);
+ }
+
+ public void setFontObject(FRFont font) {
+ this.frFont = font;
+ this.repaint();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xpane/ToolTipEditor.java b/designer_form/src/com/fr/design/gui/xpane/ToolTipEditor.java
new file mode 100644
index 000000000..8306bb9d6
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xpane/ToolTipEditor.java
@@ -0,0 +1,224 @@
+package com.fr.design.gui.xpane;
+
+import com.fr.base.background.GradientBackground;
+import com.fr.design.ExtraDesignClassManager;
+import com.fr.design.border.UIRoundedBorder;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XEditorHolder;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.gui.core.WidgetOption;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.utils.gui.GUICoreUtils;
+import com.fr.form.ui.DataControl;
+import com.fr.form.ui.EditorHolder;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.WidgetValue;
+import com.fr.general.Background;
+import com.fr.stable.ArrayUtils;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.geom.RoundRectangle2D;
+
+public class ToolTipEditor extends JWindow {
+
+ private static ToolTipEditor editor = new ToolTipEditor();
+
+ public static ToolTipEditor getInstance() {
+ return editor;
+ }
+
+ private XEditorHolder holder;
+ private Border buttonBorder = new UIRoundedBorder(new Color(149, 149, 149), 1, 5);
+ private int Num = 24;
+
+ private ToolTipEditor() {
+ this.initComponents();
+ }
+
+ private void setEditor(XEditorHolder holder) {
+ this.holder = holder;
+ }
+
+ private void transform(Widget createWidget) {
+ XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(holder);
+ EditorHolder widget = (EditorHolder) holder.toData();
+ createWidget.setWidgetName(widget.getWidgetName());
+ createWidget.setEnabled(widget.isEnabled());
+ createWidget.setVisible(widget.isVisible());
+ WidgetValue.convertWidgetValue((DataControl) createWidget, widget.getWidgetValue().getValue());
+ XCreator creator = null;
+ creator = parent.replace(createWidget, holder);
+ Component designer = holder.getDesignerEditor().getEditorTarget().getParent();
+ if (designer instanceof FormDesigner) {
+ ((FormDesigner) designer).getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_EDITED);
+ ((FormDesigner) designer).getSelectionModel().setSelectedCreator(creator);
+ }
+ }
+
+ /**
+ * 显示XEditorHolder可成为类型弹出框
+ * @param holder 控件
+ * @param xAbs 横坐标
+ * @param yAbs 纵坐标
+ */
+ public void showToolTip(XEditorHolder holder, int xAbs, int yAbs) {
+ this.setEditor(holder);
+ if (!this.isVisible()) {
+ this.setVisible(true);
+ if (xAbs + this.getWidth() > Toolkit.getDefaultToolkit().getScreenSize().width) {
+ xAbs -= this.getWidth();
+ }
+ this.setLocation(xAbs, yAbs);
+ }
+ }
+
+ /**
+ * 判断是否隐藏
+ * @return 是返回true
+ */
+ public boolean isEditorVisible() {
+ return this.isVisible();
+ }
+
+ /**
+ * 隐藏弹出框
+ */
+ public void hideToolTip() {
+ this.setVisible(false);
+ }
+
+ /**
+ * 充值大小
+ * @param xEditorHolder 控件
+ * @param bounds 新尺寸
+ * @param oldBounds 旧尺寸
+ */
+ public void resetBounds(XEditorHolder xEditorHolder, Rectangle bounds, Rectangle oldBounds) {
+ if (this.isVisible() && this.holder == xEditorHolder) {
+ if (!GUICoreUtils.isTheSameRect(bounds, oldBounds)) {
+ this.setVisible(false);
+ }
+ }
+ }
+
+ protected void initComponents() {
+ EditorChoosePane pane = new EditorChoosePane();
+ this.getContentPane().add(pane);
+ this.setSize(pane.getPreferredSize());
+ }
+
+ class EditorChoosePane extends JPanel {
+ private Background background;
+
+ public EditorChoosePane() {
+ super();
+ background = new GradientBackground(Color.white, new Color(234, 246, 254), GradientBackground.TOP2BOTTOM);
+ this.setLayout(new EditorLayout());
+ this.initComponents();
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ if (!isOpaque()) {
+ return;
+ }
+ Rectangle r = this.getBounds();
+ background.paint(g, new RoundRectangle2D.Double(r.getX(), r.getY(), r.getWidth(), r.getHeight(), 5, 5));
+ }
+
+ protected void initComponents() {
+ WidgetOption[] options = WidgetOption.getFormWidgetIntance();
+ options = (WidgetOption[]) ArrayUtils.addAll(
+ options, ExtraDesignClassManager.getInstance().getParameterWidgetOptions()
+ );
+ for (WidgetOption o : options) {
+ if (DataControl.class.isAssignableFrom(o.widgetClass())) {
+ this.add(new EditorButton(o));
+ }
+ }
+ this.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2), new UIRoundedBorder(new Color(139, 139, 140), 1, 5)));
+ }
+ }
+
+ class EditorLayout implements LayoutManager {
+ int top = 4, left = 4, right = 4, bottom = 4, hgap = 2, vgap = 4, maxLine = 9;
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+
+ }
+
+ @Override
+ public void layoutContainer(Container target) {
+ synchronized (target.getTreeLock()) {
+ Insets insets = target.getInsets();
+ int nMembers = target.getComponentCount();
+ for (int i = 0; i < nMembers; i++) {
+ Component m = target.getComponent(i);
+ if (m.isVisible()) {
+ Dimension d = m.getPreferredSize();
+ m.setBounds(insets.left + left + i % maxLine * (hgap + d.width), top + insets.top + i / maxLine * (vgap + d.height), d.width, d.height);
+ }
+ }
+ }
+ }
+
+ @Override
+ public Dimension minimumLayoutSize(Container parent) {
+ return new Dimension(0, 0);
+ }
+
+ @Override
+ public Dimension preferredLayoutSize(Container parent) {
+ Insets insets = parent.getInsets();
+ int nmembers = parent.getComponentCount();
+ return new Dimension(maxLine * Num + insets.left + insets.right + right + left, (nmembers + maxLine - 1)
+ / maxLine * Num + insets.top + insets.bottom + top + bottom);
+ }
+
+ @Override
+ public void removeLayoutComponent(Component comp) {
+
+ }
+
+ }
+
+ class EditorButton extends UILabel {
+
+ public EditorButton(final WidgetOption option) {
+ super(option.optionIcon());
+ this.setToolTipText(option.optionName());
+ this.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ ToolTipEditor.this.setVisible(false);
+ ToolTipEditor.this.transform(option.createWidget());
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ EditorButton.this.setBorder(buttonBorder);
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ EditorButton.this.setBorder(null);
+ }
+ });
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(22, 22);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xtable/AbstractPropertyGroupModel.java b/designer_form/src/com/fr/design/gui/xtable/AbstractPropertyGroupModel.java
new file mode 100644
index 000000000..30be1e185
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xtable/AbstractPropertyGroupModel.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.gui.xtable;
+
+import java.beans.PropertyEditor;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.base.FRContext;
+import com.fr.design.beans.GroupModel;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.design.mainframe.widget.renderer.PropertyCellRenderer;
+import com.fr.design.designer.creator.CRPropertyDescriptor;
+import com.fr.design.designer.creator.XCreator;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public abstract class AbstractPropertyGroupModel implements GroupModel, Comparable {
+
+ protected String groupName;
+ protected XCreator creator;
+ protected CRPropertyDescriptor[] properties;
+ protected TableCellRenderer[] renderers;
+ protected PropertyCellEditor[] editors;
+ public static final String RENDERER = "renderer";
+
+ public AbstractPropertyGroupModel(String groupName, XCreator creator, CRPropertyDescriptor[] props) {
+ this.groupName = groupName;
+ this.creator = creator;
+ this.properties = props;
+ this.renderers = new TableCellRenderer[properties.length];
+ this.editors = new PropertyCellEditor[properties.length];
+ }
+
+ @Override
+ public String getGroupName() {
+ return this.groupName;
+ }
+
+ @Override
+ public int getRowCount() {
+ return properties.length;
+ }
+
+ @Override
+ public TableCellRenderer getRenderer(int row) {
+ if (renderers[row] == null) {
+ try {
+ initRenderer(row);
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ }
+ }
+ return renderers[row];
+ }
+
+ @Override
+ public TableCellEditor getEditor(int row) {
+ if (editors[row] == null) {
+ try {
+ initEditor(row);
+ } catch (Exception ex) {
+ FRContext.getLogger().error(ex.getMessage(), ex);
+ }
+ }
+ return editors[row];
+ }
+
+ private void initRenderer(int row) throws Exception {
+ Class rendererCls = (Class) properties[row].getValue(RENDERER);
+ // 先看看有没有设定好的渲染器
+ if (rendererCls != null) {
+ renderers[row] = (TableCellRenderer) rendererCls.newInstance();
+ } else {
+ // 没有设定好的渲染器那么就根据已有的类型查找一个合适的渲染器
+ Class propType = properties[row].getPropertyType();
+ Class extends TableCellRenderer> rendererClass = TableUtils.getTableCellRendererClass(propType);
+ if (rendererClass != null) {
+ renderers[row] = rendererClass.newInstance();
+ } else {
+ // 如果已有的渲染器也不匹配那么就根据编辑器来生成一个渲染器
+ Class> editorClass = properties[row].getPropertyEditorClass();
+ if (editorClass == null) {
+ editorClass = TableUtils.getPropertyEditorClass(propType);
+ }
+ if (editorClass == null) {
+ renderers[row] = new DefaultTableCellRenderer();
+ } else {
+ PropertyEditor editor = ((PropertyCellEditor)getEditor(row)).getCellEditor();
+ renderers[row] = new PropertyCellRenderer(editor);
+ }
+ }
+ }
+ }
+
+ protected abstract void initEditor(final int row) throws Exception;
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xtable/PropertyGroupModel.java b/designer_form/src/com/fr/design/gui/xtable/PropertyGroupModel.java
new file mode 100644
index 000000000..926cbcaa6
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xtable/PropertyGroupModel.java
@@ -0,0 +1,147 @@
+package com.fr.design.gui.xtable;
+
+import com.fr.base.FRContext;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.creator.CRPropertyDescriptor;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.mainframe.FormDesigner;
+import com.fr.design.mainframe.widget.editors.ExtendedPropertyEditor;
+import com.fr.design.mainframe.widget.editors.PropertyCellEditor;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.Inter;
+import com.fr.report.stable.FormConstants;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+public class PropertyGroupModel extends AbstractPropertyGroupModel {
+
+ private FormDesigner designer;
+
+ public PropertyGroupModel(String name, XCreator creator, CRPropertyDescriptor[] propArray,
+ FormDesigner designer) {
+ super(name, creator, propArray);
+ this.designer = designer;
+ }
+
+ @Override
+ public Object getValue(int row, int column) {
+ if (column == 0) {
+ return properties[row].getDisplayName();
+ }
+ try {
+ Method m = properties[row].getReadMethod();
+ return m.invoke(dealCreatorData());
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ @Override
+ public boolean setValue(Object value, int row, int column) {
+ if (column == 0) {
+ return false;
+ }
+
+ try {
+ Method m = properties[row].getWriteMethod();
+ m.invoke(dealCreatorData(), value);
+ //属性名称为控件名时,单独处理下
+ if(ComparatorUtils.equals(FormConstants.NAME, properties[row].getName())){
+ creator.resetCreatorName(value.toString());
+ }
+ properties[row].firePropertyChanged();
+ return true;
+ } catch (Exception e) {
+ FRContext.getLogger().error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 改行是否可编辑
+ * @param row 行
+ * @return 第row行可编辑返回true,否则返回false
+ */
+ @Override
+ public boolean isEditable(int row) {
+ return properties[row].getWriteMethod() != null;
+ }
+
+ /**
+ * 该属性所属的分类,普通属性分为基本属性和其它,事件属性根据事件名称不同进行分类
+ * @return 返回属性名称
+ */
+ @Override
+ public String getGroupName() {
+ return Inter.getLocText(groupName);
+ }
+
+ /**
+ * 比较
+ * @param gm 属性类
+ * @return 返回比较结果
+ */
+ @Override
+ public int compareTo(AbstractPropertyGroupModel gm) {
+ int firstIndex = PROPERTIES.indexOf(groupName);
+ int lastIndex = PROPERTIES.indexOf(gm.getGroupName());
+ if (firstIndex < lastIndex) {
+ return -1;
+ } else if (firstIndex == lastIndex) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ private static ArrayList PROPERTIES = new ArrayList();
+
+ static {
+ PROPERTIES.add("Properties");
+ PROPERTIES.add("Others");
+ }
+
+ /**
+ * 控件属性赋值和取值时,针对scale和title做下处理
+ * @return
+ */
+ private Object dealCreatorData() {
+ return creator.getPropertyDescriptorCreator().toData();
+ }
+
+ @Override
+ protected void initEditor(final int row) throws Exception {
+ ExtendedPropertyEditor editor = (ExtendedPropertyEditor) properties[row].createPropertyEditor(dealCreatorData());
+ if (editor == null) {
+ Class propType = properties[row].getPropertyType();
+ editor = TableUtils.getPropertyEditorClass(propType).newInstance();
+ }
+ if (editor != null) {
+ final ExtendedPropertyEditor extendEditor = editor;
+ editors[row] = new PropertyCellEditor(editor);
+ extendEditor.addPropertyChangeListener(new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if(ComparatorUtils.equals(extendEditor.getValue(),getValue(row,1))) {
+ return;
+ }
+ if (extendEditor.refreshInTime()) {
+ editors[row].stopCellEditing();
+ } else {
+ setValue(extendEditor.getValue(), row, 1);
+ if ("widgetName".equals(properties[row].getName())) {
+ designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_RENAMED);
+ } else {
+ designer.fireTargetModified();
+ }
+ designer.refreshDesignerUI();
+ }
+ }
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/gui/xtable/TableUtils.java b/designer_form/src/com/fr/design/gui/xtable/TableUtils.java
new file mode 100644
index 000000000..413c1d1ee
--- /dev/null
+++ b/designer_form/src/com/fr/design/gui/xtable/TableUtils.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved.
+ */
+package com.fr.design.gui.xtable;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Point;
+import java.util.HashMap;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellRenderer;
+
+import com.fr.base.Formula;
+import com.fr.design.mainframe.widget.editors.BooleanEditor;
+import com.fr.design.mainframe.widget.editors.ColorEditor;
+import com.fr.design.mainframe.widget.editors.DimensionEditor;
+import com.fr.design.mainframe.widget.editors.DoubleEditor;
+import com.fr.design.mainframe.widget.editors.ExtendedPropertyEditor;
+import com.fr.design.mainframe.widget.editors.FloatEditor;
+import com.fr.design.mainframe.widget.editors.FontEditor;
+import com.fr.design.mainframe.widget.editors.FormulaEditor;
+import com.fr.design.mainframe.widget.editors.IntegerPropertyEditor;
+import com.fr.design.mainframe.widget.editors.LongEditor;
+import com.fr.design.mainframe.widget.editors.StringEditor;
+import com.fr.design.mainframe.widget.renderer.ColorCellRenderer;
+import com.fr.design.mainframe.widget.renderer.DimensionCellRenderer;
+import com.fr.design.mainframe.widget.renderer.FontCellRenderer;
+import com.fr.design.mainframe.widget.renderer.PointCellRenderer;
+import com.fr.design.mainframe.widget.renderer.RectangleCellRenderer;
+import com.fr.third.com.lowagie.text.Rectangle;
+
+/**
+ * @author richer
+ * @since 6.5.3
+ */
+public class TableUtils {
+
+ private static HashMap> propertyEditorClasses;
+ private static HashMap> cellRendererClasses;
+
+ static {
+ propertyEditorClasses = new HashMap>();
+ propertyEditorClasses.put(String.class, StringEditor.class);
+ propertyEditorClasses.put(boolean.class, BooleanEditor.class);
+ propertyEditorClasses.put(Color.class, ColorEditor.class);
+ propertyEditorClasses.put(Font.class, FontEditor.class);
+ propertyEditorClasses.put(Dimension.class, DimensionEditor.class);
+ propertyEditorClasses.put(int.class, IntegerPropertyEditor.class);
+ propertyEditorClasses.put(Integer.class, IntegerPropertyEditor.class);
+ propertyEditorClasses.put(long.class, LongEditor.class);
+ propertyEditorClasses.put(Long.class, IntegerPropertyEditor.class);
+ propertyEditorClasses.put(float.class, FloatEditor.class);
+ propertyEditorClasses.put(Float.class, IntegerPropertyEditor.class);
+ propertyEditorClasses.put(double.class, DoubleEditor.class);
+ propertyEditorClasses.put(Double.class, IntegerPropertyEditor.class);
+
+ propertyEditorClasses.put(Formula.class, FormulaEditor.class);
+ // TODO ALEX_SEP
+// propertyEditorClasses.put(DSColumn.class, DSColumnEditor.class);
+
+ cellRendererClasses = new HashMap>();
+ cellRendererClasses.put(Color.class, ColorCellRenderer.class);
+ cellRendererClasses.put(Font.class, FontCellRenderer.class);
+ cellRendererClasses.put(String.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(int.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(Integer.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(long.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(Long.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(float.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(Float.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(double.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(Double.class, DefaultTableCellRenderer.class);
+ cellRendererClasses.put(Point.class, PointCellRenderer.class);
+ cellRendererClasses.put(Dimension.class, DimensionCellRenderer.class);
+ cellRendererClasses.put(Rectangle.class, RectangleCellRenderer.class);
+ }
+
+ public static Class extends ExtendedPropertyEditor> getPropertyEditorClass(Class propType) {
+ return propertyEditorClasses.get(propType);
+ }
+
+ public static Class extends TableCellRenderer> getTableCellRendererClass(Class propType) {
+ return cellRendererClasses.get(propType);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/AutoScrollSource.java b/designer_form/src/com/fr/design/mainframe/AutoScrollSource.java
new file mode 100644
index 000000000..529b3f032
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/AutoScrollSource.java
@@ -0,0 +1,69 @@
+package com.fr.design.mainframe;
+
+import java.awt.Rectangle;
+
+
+public class AutoScrollSource {
+
+ private int x = 0;
+ private int y = 0;
+ private AutoScrollChangeListener l;
+
+ public static int sab(int i, int delay) {
+ if (i > delay) {
+ return i - delay;
+ } else if (i < 0) {
+ return i;
+ } else {
+ return 0;
+ }
+ }
+
+ public static AutoScrollSource creatAutoScrollSource(int x, int y, AutoScrollChangeListener l, FormDesigner designer) {
+ AutoScrollSource as = new AutoScrollSource();
+ as.y = sab(y, designer.getHeight());
+ as.x = sab(x, designer.getWidth());
+ as.l = l;
+ return as;
+ }
+
+ public static AutoScrollSource creatAutoScrollSource(Rectangle rec, int rx, int ry, AutoScrollChangeListener l,
+ FormDesigner designer) {
+ AutoScrollSource as = new AutoScrollSource();
+ if (rec.x + rx < designer.getArea().getHorizontalValue()) {
+ as.x = rec.x + rx - designer.getArea().getHorizontalValue();
+ } else if (rec.x + rx + rec.width > designer.getArea().getHorizontalValue() + designer.getWidth()) {
+ as.x = rec.x + rx + rec.width - designer.getArea().getHorizontalValue() - designer.getWidth();
+ }
+ if (rec.y + ry < designer.getArea().getVerticalValue()) {
+ as.y = rec.y + ry - designer.getArea().getVerticalValue();
+ } else if (rec.y + ry + rec.height > designer.getArea().getVerticalValue() + designer.getHeight()) {
+ as.y = rec.y + ry + rec.height - designer.getArea().getVerticalValue() - designer.getHeight();
+ }
+ as.l = l;
+ return as;
+ }
+
+ private AutoScrollSource() {
+
+ }
+
+ public int getHorizontalExtent() {
+ return x;
+
+ }
+
+ public int getVerticalExtent() {
+ return y;
+ }
+
+ public void propertyChange() {
+ if (l != null) {
+ l.propertyChange(x,y);
+ }
+ }
+
+ public interface AutoScrollChangeListener {
+ void propertyChange(int dx, int dy);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/ComponentTree.java b/designer_form/src/com/fr/design/mainframe/ComponentTree.java
new file mode 100644
index 000000000..fb0586a69
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/ComponentTree.java
@@ -0,0 +1,281 @@
+package com.fr.design.mainframe;
+
+import java.awt.Component;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.DropMode;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import com.fr.design.constants.UIConstants;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.events.DesignerEditListener;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.treeview.ComponentTreeCellRenderer;
+import com.fr.design.designer.treeview.ComponentTreeModel;
+import com.fr.stable.StringUtils;
+
+public class ComponentTree extends JTree {
+
+ private FormDesigner designer;
+ private ComponentTreeModel model;
+
+ public ComponentTree(FormDesigner designer) {
+ this.designer = designer;
+ this.setBackground(UIConstants.NORMAL_BACKGROUND);
+ setRootVisible(true);
+ setCellRenderer(new ComponentTreeCellRenderer());
+ getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+ this.setDragEnabled(false);
+ this.setDropMode(DropMode.ON_OR_INSERT);
+ this.setTransferHandler(new TreeTransferHandler());
+ this.refreshTreeRoot();
+ TreePath[] paths = getSelectedTreePath();
+ addTreeSelectionListener(designer);
+ setSelectionPaths(paths);
+
+ designer.addDesignerEditListener(new TreeDesignerEditAdapter());
+ this.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ popupMenu(e);
+ }
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ popupMenu(e);
+ }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ popupMenu(e);
+ }
+ }
+ });
+ setEditable(true);
+ }
+
+ /**
+ * 构造函数
+ *
+ * @param designer 设计界面组件
+ * @param model 构造JTree的model
+ */
+ public ComponentTree(FormDesigner designer,ComponentTreeModel model) {
+ this(designer);
+ this.setModel(model);
+ }
+
+
+
+
+ /**
+ * 是否可编辑
+ * @param path 树路径
+ * @return 是则返回true
+ */
+ @Override
+ public boolean isPathEditable(TreePath path) {
+ Object object = path.getLastPathComponent();
+ if (object == designer.getRootComponent()) {
+ return false;
+ }
+ return super.isPathEditable(path);
+ }
+
+ /**
+ * 将值转换为文本
+ * @param value 值
+ * @param selected 是否选中
+ * @param expanded 扩展
+ * @param leaf 是否叶子
+ * @param row 行
+ * @param hasFocus 是否焦点
+ *
+ * @return 返回文本
+ */
+ @Override
+ public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+ if (value != null && value instanceof XCreator) {
+ return ((XCreator) value).toData().getWidgetName();
+ } else {
+ return super.convertValueToText(value, selected, expanded, leaf, row, hasFocus);
+ }
+ }
+
+ public void setAndScrollSelectionPath(TreePath treepath) {
+ setSelectionPath(treepath);
+ scrollPathToVisible(treepath);
+ }
+
+ private void popupMenu(MouseEvent e) {
+ TreePath path = this.getSelectionPath();
+ if (path == null) {
+ return;
+ }
+ Component component = (Component) path.getLastPathComponent();
+ if (!(component instanceof XCreator)) {
+ return;
+ }
+ ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, (XCreator) component);
+ JPopupMenu menu = adapter.getContextPopupMenu(e);
+ menu.show(this, e.getX(), e.getY());
+ }
+
+ /**
+ * 刷新
+ */
+ public void refreshUI() {
+ updateUI();
+ }
+
+
+
+
+
+ public TreePath[] getSelectedTreePath() {
+ XCreator[] creators = designer.getSelectionModel().getSelection().getSelectedCreators();
+ TreePath[] paths = new TreePath[creators.length];
+
+ for (int i = 0; i < paths.length; i++) {
+ paths[i] = buildTreePath(creators[i]);
+ }
+ return paths;
+ }
+
+ private class TreeDesignerEditAdapter implements DesignerEditListener {
+
+ @Override
+ public void fireCreatorModified(DesignerEvent evt) {
+ if (evt.getCreatorEventID() == DesignerEvent.CREATOR_SELECTED) {
+ TreePath[] paths = getSelectedTreePath();
+
+ if (paths.length == 1) {
+ setAndScrollSelectionPath(paths[0]);
+ } else {
+ setSelectionPaths(paths);
+ }
+ } else if(evt.getCreatorEventID() == DesignerEvent.CREATOR_PASTED) {
+ ComponentTree.this.refreshUI();
+ TreePath[] paths = getSelectedTreePath();
+
+ if (paths.length == 1) {
+ setAndScrollSelectionPath(paths[0]);
+ } else {
+ setSelectionPaths(paths);
+ }
+ ComponentTree.this.repaint();
+
+ } else {
+ ComponentTree.this.refreshUI();
+ ComponentTree.this.repaint();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o.getClass() == this.getClass();
+ }
+ }
+
+
+ /**
+ *搜索指定名称的路径
+ *
+ * @param text 名称
+ * @return 树路径
+ */
+ public TreePath[] search(String text) {
+ if (StringUtils.isNotEmpty(text)) {
+ text = text.toLowerCase();
+ }
+ ArrayList searchList = new ArrayList();
+ XLayoutContainer root = designer.getRootComponent();
+ searchFormRoot(root, searchList, text);
+ TreePath[] paths = new TreePath[searchList.size()];
+
+ for (int i = 0; i < paths.length; i++) {
+ paths[i] = buildTreePath(searchList.get(i));
+ }
+ if(paths.length > 0) {
+ setAndScrollSelectionPath(paths[0]);
+ } else {
+ setSelectionPath();
+ }
+ return paths;
+ }
+
+
+ private void setSelectionPath(){
+
+ /**
+ * 不让传null参数,所以只有自己定义
+ */
+ super.setSelectionPath(null);
+ clearSelection();
+ }
+
+ private void searchFormRoot(XLayoutContainer container, ArrayList searchList, String text) {
+ if (StringUtils.isEmpty(text)) {
+ return;
+ }
+ for (int i = 0, size = container.getXCreatorCount(); i < size; i++) {
+ XCreator creator = container.getXCreator(i);
+ String xName = creator.toData().getWidgetName();
+ if (xName.toLowerCase().contains(text)) {
+ searchList.add(creator);
+ }
+ if (creator instanceof XLayoutContainer) {
+ searchFormRoot((XLayoutContainer) creator, searchList, text);
+ }
+ }
+ }
+
+ /**
+ * 触发
+ */
+ public void fireTreeChanged() {
+ designer.refreshDesignerUI();
+ }
+
+ /**
+ * 刷新
+ */
+ public void refreshTreeRoot() {
+ model = new ComponentTreeModel(designer, designer.getTopContainer());
+ setModel(model);
+ setDragEnabled(false);
+ setDropMode(DropMode.ON_OR_INSERT);
+ setTransferHandler(new TreeTransferHandler());
+ repaint();
+ }
+
+ private TreePath buildTreePath(Component comp) {
+ ArrayList path = new ArrayList();
+ Component parent = comp;
+
+ while (parent != null) {
+ XCreator creator = (XCreator) parent;
+ path.add(0, parent);
+ if (creator != comp ) {
+ creator.notShowInComponentTree(path);
+ }
+ parent = parent.getParent();
+ }
+ Object[] components = path.toArray();
+ return new TreePath(components);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java b/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java
new file mode 100644
index 000000000..e592a48c9
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/ConnectorHelper.java
@@ -0,0 +1,110 @@
+package com.fr.design.mainframe;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import com.fr.stable.Constants;
+import com.fr.base.GraphHelper;
+import com.fr.design.designer.beans.ConnectorCreator;
+import com.fr.design.designer.creator.XWAbsoluteLayout;
+import com.fr.form.ui.Connector;
+import com.fr.form.ui.container.WAbsoluteLayout.BoundsWidget;
+
+public class ConnectorHelper {
+ //这个类是用来画连接线的,暂时用不到
+
+ public static final int NEAR = 5;
+ private static double ratio = 0.5;
+ private ArrayList drawingPoint;
+ private FormDesigner designer;
+ private boolean drawing;
+
+ public ConnectorHelper(FormDesigner formEditor) {
+ this.designer = formEditor;
+ }
+
+ public void resetConnector(Connector connector) {
+ ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(),connector.getStartPoint(),connector.getEndPoint());
+ connector.addAll(cc.createPointList());
+ }
+
+ public boolean drawLining() {
+ return this.drawing;
+ }
+
+ public void setDrawLine(boolean d) {
+ this.drawing = d;
+ }
+
+ private boolean near(Point p1, Point p2) {
+ return p1.x - p2.x < NEAR && p2.x - p1.x < NEAR && p1.y - p2.y < NEAR && p2.y - p1.y < NEAR;
+ }
+
+ private Point getNearPoint(MouseEvent e, Rectangle r) {
+ Point p1 = new Point((int) (r.x + r.getWidth() * ratio), r.y);
+ Point p2 = new Point((int) (r.x + r.getWidth()), (int) (r.y + r.getHeight() * ratio));
+ Point p3 = new Point((int) (r.x + r.getWidth() * (1 - ratio)), (int) (r.y + r.getHeight()));
+ Point p4 = new Point(r.x, (int) (r.y + r.getHeight() * (1 - ratio)));
+ Point p = new Point(e.getX() + designer.getArea().getHorizontalValue(), e.getY() + designer.getArea().getVerticalValue());
+ if (near(p, p1)) {
+ return p1;
+ } else if (near(p, p2)) {
+ return p2;
+ } else if (near(p, p3)) {
+ return p3;
+ } else if (near(p, p4)) {
+ return p4;
+ }
+ return null;
+ }
+
+ private ArrayList createDefalutNode(Point startPoint, Point endPoint) {
+ long s = System.currentTimeMillis();
+ ConnectorCreator cc = new ConnectorCreator(designer.getTarget().getContainer(), new Point(startPoint), new Point(endPoint));
+ ArrayList p = cc.createPointList();
+ long e = System.currentTimeMillis();
+ System.out.println("useTime:" + (e - s));
+ return p;
+ }
+
+ public void drawAuxiliaryLine(Graphics g) {
+ Point startPoint = designer.getStateModel().getStartPoint();
+ Point endPoint = designer.getStateModel().getEndPoint();
+ drawingPoint = createDefalutNode(startPoint, endPoint);
+ Point[] p = drawingPoint.toArray(new Point[drawingPoint.size()]);
+ g.setColor(Color.green);
+ for (int i = 0; i < p.length - 1; i++) {
+ GraphHelper.drawLine(g, p[i].x - designer.getArea().getHorizontalValue(), p[i].y
+ - designer.getArea().getVerticalValue(), p[i + 1].x - designer.getArea().getHorizontalValue(),
+ p[i + 1].y - designer.getArea().getVerticalValue(), Constants.LINE_HAIR);
+ }
+ }
+
+ public void createDefalutLine() {
+ if (drawingPoint != null
+ && drawingPoint.size() > 1
+ && ConnectorCreator.getMinimumDistance(drawingPoint.get(0), drawingPoint.get(drawingPoint.size() - 1)) > 15) {
+ ((XWAbsoluteLayout) designer.getRootComponent()).addConnector(new Connector().addAll(drawingPoint));
+ }
+ drawingPoint = null;
+ }
+
+ public Point getNearWidgetPoint(MouseEvent e) {
+ BoundsWidget widget;
+ Point p = null;
+ for (int i = 0, size = designer.getTarget().getContainer().getWidgetCount(); i < size; i++) {
+ widget = ((BoundsWidget) designer.getTarget().getContainer().getWidget(i));
+ if (widget.isVisible()) {
+ if ((p = getNearPoint(e, widget.getBounds())) != null) {
+ break;
+ }
+ }
+ }
+ return p;
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/CoverReportPane.java b/designer_form/src/com/fr/design/mainframe/CoverReportPane.java
new file mode 100644
index 000000000..183cf24ee
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/CoverReportPane.java
@@ -0,0 +1,80 @@
+package com.fr.design.mainframe;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.gui.ibutton.UIButton;
+import com.fr.design.icon.IconPathConstants;
+import com.fr.general.Inter;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: zx
+ * Date: 14-7-24
+ * Time: 上午9:09
+ */
+public class CoverReportPane extends JPanel{
+
+ private UIButton editButton;
+
+ private AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 60 / 100.0F);
+
+ public CoverReportPane(){
+ setLayout(coverLayout);
+ setBackground(null);
+ setOpaque(false);
+
+ editButton = new UIButton(Inter.getLocText("Edit"), BaseUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH)){
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(60,24);
+ }
+ };
+ editButton.setBorderPainted(false);
+ editButton.setExtraPainted(false);
+ editButton.setBackground(new Color(176,196,222));
+ add(editButton);
+
+ }
+
+ 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.getParent().getWidth();
+ int height = parent.getParent().getHeight();
+ int preferWidth = editButton.getPreferredSize().width;
+ int preferHeight = editButton.getPreferredSize().height;
+ editButton.setBounds((width - preferWidth)/2, (height - preferHeight)/2, preferWidth, preferHeight);
+ }
+
+ @Override
+ public void addLayoutComponent(String name, Component comp) {
+ }
+ };
+
+ public void paint(Graphics g) {
+ Graphics2D g2d = (Graphics2D) g;
+ Composite oldComposite = g2d.getComposite();
+ g2d.setComposite(composite);
+ g2d.setColor(Color.white);
+ g2d.fillRect(0, 0, getWidth(), getHeight());
+ g2d.setComposite(oldComposite);
+ super.paint(g);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/DesignerTransferHandler.java b/designer_form/src/com/fr/design/mainframe/DesignerTransferHandler.java
new file mode 100644
index 000000000..4ca787199
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/DesignerTransferHandler.java
@@ -0,0 +1,27 @@
+package com.fr.design.mainframe;
+
+import java.awt.datatransfer.Transferable;
+
+import javax.swing.JComponent;
+import javax.swing.TransferHandler;
+
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.models.AddingModel;
+
+public class DesignerTransferHandler extends TransferHandler {
+
+ private FormDesigner designer;
+ private AddingModel addingModel;
+
+ public DesignerTransferHandler(FormDesigner designer, AddingModel addingModel) {
+ super("rootComponent");
+ this.designer = designer;
+ this.addingModel = addingModel;
+ }
+
+ protected void exportDone(JComponent source, Transferable data, int action) {
+ if (!addingModel.isCreatorAdded()) {
+ designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED);
+ }
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java
new file mode 100644
index 000000000..00dd905b1
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/EditingMouseListener.java
@@ -0,0 +1,446 @@
+package com.fr.design.mainframe;
+
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+
+import javax.swing.*;
+import javax.swing.event.MouseInputAdapter;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.ComponentAdapter;
+import com.fr.design.designer.beans.events.DesignerEditor;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.designer.beans.location.Location;
+import com.fr.design.designer.beans.models.SelectionModel;
+import com.fr.design.designer.beans.models.StateModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XEditorHolder;
+import com.fr.design.designer.creator.XElementCase;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWFitLayout;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.ibutton.UIButton;
+import com.fr.design.gui.xpane.ToolTipEditor;
+import com.fr.design.icon.IconPathConstants;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.general.Inter;
+import com.fr.stable.Constants;
+
+/**
+ * 普通模式下的鼠标点击、位置处理器
+ */
+public class EditingMouseListener extends MouseInputAdapter {
+
+ private static final int INDEX = 0;
+ private FormDesigner designer;
+
+ /**
+ * 普通模式下对应的model
+ */
+ private StateModel stateModel;
+
+ /**
+ * 获取表单设计器
+ *
+ * @return 表单设计器
+ */
+ public FormDesigner getDesigner() {
+ return designer;
+ }
+
+ /**
+ * 选择模型,存储当前选择的组件和剪切板
+ */
+ private SelectionModel selectionModel;
+ /**
+ * 获取选择模型
+ *
+ * @return 选择
+ */
+ public SelectionModel getSelectionModel() {
+ return selectionModel;
+ }
+
+ private XCreator last_creator;
+ private MouseEvent lastPressEvent;
+ private DesignerEditor extends JComponent> current_editor;
+ private XCreator current_creator;
+
+ /**
+ * 获取最小移动距离
+ *
+ * @return 最小移动距离
+ */
+ public int getMinMoveSize() {
+ return minMoveSize;
+ }
+
+ private int minDragSize = 5;
+ private int minMoveSize = 8;
+ //报表块的编辑按钮不灵敏,范围扩大一点
+ private static final int GAP = 10;
+
+ private XElementCase xElementCase;
+
+ private JWindow promptWindow = new JWindow();
+
+ public EditingMouseListener(FormDesigner designer) {
+ this.designer = designer;
+ stateModel = designer.getStateModel();
+ selectionModel = designer.getSelectionModel();
+ UIButton promptButton = new UIButton(Inter.getLocText("FR-Designer_Forbid_Drag_into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH));
+ this.promptWindow.add(promptButton);
+ }
+
+ private void promptUser(int x, int y, XLayoutContainer container){
+ if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)){
+ promptWidgetForbidEnter(x ,y , container);
+ } else {
+ cancelPromptWidgetForbidEnter();
+ }
+ }
+
+ private void promptWidgetForbidEnter(int x,int y, XLayoutContainer container){
+ container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM));
+ int screen_X = (int)designer.getArea().getLocationOnScreen().getX();
+ int screen_Y = (int)designer.getArea().getLocationOnScreen().getY();
+ this.promptWindow.setSize(promptWindow.getPreferredSize());
+ this.promptWindow.setPreferredSize(promptWindow.getPreferredSize());
+ promptWindow.setLocation(screen_X + x + GAP, screen_Y + y + GAP);
+ promptWindow.setVisible(true);
+ }
+
+ private void cancelPromptWidgetForbidEnter(){
+ designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN));
+ promptWindow.setVisible(false);
+ }
+
+
+ /**
+ * 按下
+ * @param e 鼠标事件
+ */
+ public void mousePressed(MouseEvent e) {
+ if (!stopEditing()) {
+ return;
+ }
+ if (!designer.isFocusOwner()) {
+ // 获取焦点,以便获取热键
+ designer.requestFocus();
+ }
+ if (e.isPopupTrigger()) {
+ // 为触发上下文菜单预留
+ } else if (e.getButton() == MouseEvent.BUTTON1) {
+
+ Direction dir = selectionModel.getDirectionAt(e);
+ if (!BaseUtils.isAuthorityEditing()) {
+ stateModel.setDirection(dir);
+ }
+
+ if (dir == Location.outer) {
+ if (designer.isDrawLineMode()) {
+ designer.updateDrawLineMode(e);
+ } else {
+ if (selectionModel.hasSelectionComponent()
+ && selectionModel.getSelection().getRelativeBounds().contains(
+ designer.getArea().getHorizontalValue() + e.getX(),
+ designer.getArea().getVerticalValue() + e.getY())) {
+ lastPressEvent = e;
+ last_creator = selectionModel.getSelection().getSelectedCreator();
+ } else {
+ stateModel.startSelecting(e);
+ }
+ }
+ } else {
+ stateModel.startResizing(e);
+ }
+ }
+ }
+
+ /**
+ * 释放
+ * @param e 鼠标事件
+ */
+ public void mouseReleased(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ if (stateModel.isDragging()) {
+ stateModel.draggingCancel();
+ }
+ } else {
+ if (designer.isDrawLineMode()) {
+ if (stateModel.prepareForDrawLining()) {
+ designer.getDrawLineHelper().setDrawLine(false);
+ designer.getDrawLineHelper().createDefalutLine();
+ }
+ } else if (stateModel.isSelecting()) {
+ // 如果当前是区域选择状态,则选择该区域所含的组件
+ designer.selectComponents(e);
+ }
+ if (stateModel.isDragging()) {
+ // 当前鼠标所在的组件
+ XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY());
+ // 拉伸时鼠标拖动过快,导致所在组件获取会为空
+ if (hoveredComponent == null && e.getY() < 0) {
+ // bug63538
+ // 不是拖动过快导致的,而是纵坐标为负值导致的,这时参照横坐标为负值时的做法,取边界位置的组件,为鼠标所在点的组件
+ // 如果直接return,界面上已经进行了拖拽不能恢复
+ hoveredComponent = designer.getComponentAt(0, 0);
+ }
+ // 获取该组件所在的焦点容器
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent);
+
+ if (container != null) {
+ boolean formSubmit2Adapt = !selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane()
+ && container.acceptType(XWFitLayout.class);
+ if ( !formSubmit2Adapt) {
+ // 如果是处于拖拽状态,则释放组件
+ stateModel.releaseDragging(e);
+ } else {
+ selectionModel.deleteSelection();
+ designer.setPainter(null);
+ }
+ cancelPromptWidgetForbidEnter();
+ }
+
+ }
+ }
+ lastPressEvent = null;
+ last_creator = null;
+ }
+
+ /**
+ * 激活上下文菜单,待完善
+ * 6.56暂时不支持右键 bugid 8777
+ */
+ private void trigger_popup(MouseEvent e) {
+
+ XCreator creator = selectionModel.getSelection().getSelectedCreator();
+
+ if (creator == null) {
+ return;
+ }
+
+ JPopupMenu popupMenu = null;
+ ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, creator);
+ popupMenu = adapter.getContextPopupMenu(e);
+
+ if (popupMenu != null) {
+ popupMenu.show(designer, e.getX(), e.getY());
+ }
+ // 通知组件已经被选择了
+ designer.getEditListenerTable().fireCreatorModified(creator, DesignerEvent.CREATOR_SELECTED);
+ }
+
+ /**
+ * 移动
+ * @param e 鼠标事件
+ */
+ public void mouseMoved(MouseEvent e) {
+ XCreator component = designer.getComponentAt(e);
+ if (component instanceof XEditorHolder) {
+ XEditorHolder xcreator = (XEditorHolder) component;
+ Rectangle rect = xcreator.getBounds();
+ int min = rect.x + rect.width / 2 - minMoveSize;
+ int max = rect.x + rect.width / 2 + minMoveSize;
+ if (e.getX() > min && e.getX() < max) {
+ if (designer.getCursor().getType() != Cursor.HAND_CURSOR) {
+ designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ }
+ return;
+ } else {
+ if (designer.getCursor().getType() == Cursor.HAND_CURSOR) {
+ designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
+ }
+ }
+ Direction dir = selectionModel.getDirectionAt(e);
+ if (designer.isDrawLineMode() && stateModel.getDirection() == Location.outer) {
+ designer.updateDrawLineMode(e);
+ }
+ if (!BaseUtils.isAuthorityEditing()) {
+ stateModel.setDirection(dir);
+ }
+ if(xElementCase != null){
+ xElementCase.displayCoverPane(false);
+ }
+ if (component.isReport()) {
+ xElementCase = (XElementCase)component;
+ UIButton button = (UIButton)xElementCase.getCoverPane().getComponent(0);
+ if(designer.getCursor().getType() ==Cursor.HAND_CURSOR) {
+ designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ } // component.getParent() 是报表块所在的XWTitleLayout
+ int minX = button.getX() + component.getX() + component.getParent().getX() - designer.getArea().getHorizontalValue();
+ int minY = button.getY() + component.getY() + component.getParent().getY() + designer.getParaHeight() - designer.getArea().getVerticalValue();
+ if(e.getX() + GAP > minX && e.getX() - GAP < minX + button.getWidth()){
+ if( e.getY() + GAP > minY && e.getY() - GAP < minY + button.getHeight()){
+ designer.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ }
+ }
+ xElementCase.displayCoverPane(true);
+ xElementCase.setDirections(Direction.TOP_BOTTOM_LEFT_RIGHT);
+ designer.repaint();
+ } else {
+ if(xElementCase != null){
+ xElementCase.displayCoverPane(false);
+ designer.repaint();
+ }
+ }
+ }
+
+ /**
+ * 拖拽
+ * @param e 鼠标事件
+ */
+ public void mouseDragged(MouseEvent e) {
+ if (BaseUtils.isAuthorityEditing()) {
+ return;
+ }
+ // 如果当前是左键拖拽状态,拖拽组件
+ if (stateModel.dragable()) {
+ if (SwingUtilities.isRightMouseButton(e)) {
+ return;
+ } else {
+ stateModel.dragging(e);
+ // 获取e所在的焦点组件
+ XCreator hotspot = designer.getComponentAt(e.getX(), e.getY());
+ // 拉伸时鼠标拖动过快,导致所在组件获取会为空
+ if (hotspot == null) {
+ return;
+ }
+ // 获取焦点组件所在的焦点容器
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot);
+ //提示组件是否可以拖入
+ promptUser(e.getX(), e.getY(), container);
+ }
+ } else if (designer.isDrawLineMode()) {
+ if (stateModel.prepareForDrawLining()) {
+ stateModel.drawLine(e);
+ }
+ } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) {
+ // 如果是拖拽选择区域状态,则更新选择区域
+ stateModel.changeSelection(e);
+ } else {
+ if ((lastPressEvent == null) || (last_creator == null)) {
+ return;
+ }
+ if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) {
+ //参数面板和自适应布局不支持拖拽
+ if (last_creator.isSupportDrag()){
+ designer.startDraggingComponent(last_creator, lastPressEvent, e.getX(), e.getY());
+ }
+ e.consume();
+ lastPressEvent = null;
+ }
+ }
+ designer.repaint();
+ }
+
+ /**
+ * 点击
+ * @param e 鼠标事件
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (e.getButton() != MouseEvent.BUTTON1) {
+ return;
+ }
+ XCreator creator = designer.getComponentAt(e);
+ if(creator != null){
+ creator.respondClick(this, e);
+ }
+ creator.doLayout();
+ LayoutUtils.layoutRootContainer(designer.getRootComponent());
+ }
+
+
+
+ /**
+ * 离开
+ * @param e 鼠标事件
+ */
+ public void mouseExited(MouseEvent e) {
+ if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR) {
+ designer.setCursor(Cursor.getDefaultCursor());
+ }
+ if (xElementCase != null){
+ xElementCase.displayCoverPane(false);
+ designer.repaint();
+ }
+ cancelPromptWidgetForbidEnter();
+ }
+
+ /**
+ * 开始编辑
+ * @param creator 容器
+ * @param designerEditor 设计器
+ * @param adapter 适配器
+ */
+ public void startEditing(XCreator creator, DesignerEditor extends JComponent> designerEditor, ComponentAdapter adapter) {
+ if (designerEditor != null) {
+ Rectangle rect = ComponentUtils.getRelativeBounds(creator);
+ current_editor = designerEditor;
+ current_creator = creator;
+ Rectangle bounds = new Rectangle(1, 1, creator.getWidth() - 2, creator.getHeight() - 2);
+ bounds.x += (rect.x - designer.getArea().getHorizontalValue());
+ bounds.y += (rect.y - designer.getArea().getVerticalValue());
+ designerEditor.getEditorTarget().setBounds(bounds);
+ designer.add(designerEditor.getEditorTarget());
+ designer.invalidate();
+ designer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ designerEditor.getEditorTarget().requestFocus();
+ designer.repaint();
+ }
+ }
+
+ /**
+ * 停止编辑
+ * @return 是否编辑成功
+ */
+ public boolean stopEditing() {
+ if (current_editor != null) {
+ designer.remove(current_editor.getEditorTarget());
+ current_editor.fireEditStoped();
+
+ Container container = current_creator.getParent();
+
+ if (container != null) {
+ LayoutUtils.layoutRootContainer(container);
+ }
+ designer.invalidate();
+ designer.repaint();
+ current_creator = null;
+ current_editor = null;
+ return true;
+ }
+ return true;
+ }
+
+ /**
+ * 重置编辑控件大小
+ */
+ public void resetEditorComponentBounds() {
+ if (current_editor == null) {
+ return;
+ }
+
+ if (current_creator.getParent() == null) {
+ stopEditing();
+ return;
+ }
+
+ Rectangle rect = ComponentUtils.getRelativeBounds(current_creator);
+ Rectangle bounds = new Rectangle(1, 1, current_creator.getWidth() - 2, current_creator.getHeight() - 2);
+ bounds.x += (rect.x - designer.getArea().getHorizontalValue());
+ bounds.y += (rect.y - designer.getArea().getVerticalValue());
+ if (current_creator instanceof XEditorHolder) {
+ ToolTipEditor.getInstance().resetBounds((XEditorHolder) current_creator, bounds, current_editor.getEditorTarget().getBounds());
+ }
+ current_editor.getEditorTarget().setBounds(bounds);
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/FormArea.java b/designer_form/src/com/fr/design/mainframe/FormArea.java
new file mode 100644
index 000000000..0f897f82a
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/FormArea.java
@@ -0,0 +1,746 @@
+package com.fr.design.mainframe;
+
+import java.awt.AWTEvent;
+import java.awt.Adjustable;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.MouseEvent;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.border.LineBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWBorderLayout;
+import com.fr.design.designer.creator.XWFitLayout;
+import com.fr.design.file.HistoryTemplateListPane;
+import com.fr.design.gui.frpane.UINumberSlidePane;
+import com.fr.design.gui.ilable.UILabel;
+import com.fr.design.gui.itextfield.UINumberField;
+import com.fr.design.layout.TableLayout;
+import com.fr.design.layout.TableLayoutHelper;
+import com.fr.design.scrollruler.BaseRuler;
+import com.fr.design.scrollruler.HorizontalRuler;
+import com.fr.design.scrollruler.RulerLayout;
+import com.fr.design.scrollruler.ScrollRulerComponent;
+import com.fr.design.scrollruler.VerticalRuler;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.form.ui.container.WBorderLayout;
+import com.fr.general.FRScreen;
+import com.fr.general.Inter;
+
+public class FormArea extends JComponent implements ScrollRulerComponent {
+
+ private static final double SLIDER_FLOAT = 120.0;
+ private static final double SLIDER_MIN = 60.0;
+ public static final double DEFAULT_SLIDER = 100.0;
+ private static final int ROTATIONS = 50;
+ private FormDesigner designer;
+ private int horizontalValue = 0;
+ private int verticalValue = 0;
+ private int verticalMax = 0;
+ private int horicalMax = 0;
+ private FormScrollBar verScrollBar;
+ private FormScrollBar horScrollBar;
+ //显示和设置表单界面大小的控件
+ private UINumberField widthPane;
+ private UINumberField heightPane;
+ private UINumberSlidePane slidePane;
+ private boolean isValid = true;
+ // 初始时滑块值为100,托动后的值设为START_VALUE;
+ private double START_VALUE = DEFAULT_SLIDER;
+ private double screenValue;
+
+ public FormScrollBar getHorScrollBar() {
+ return horScrollBar;
+ }
+
+ public void setHorScrollBar(FormScrollBar horScrollBar) {
+ this.horScrollBar = horScrollBar;
+ }
+
+ public FormArea(FormDesigner designer) {
+ this(designer, true);
+ }
+
+ public FormArea(FormDesigner designer, boolean useScrollBar) {
+ this.designer = designer;
+ this.designer.setParent(this);
+ isValid = useScrollBar;
+ verScrollBar = new FormScrollBar(Adjustable.VERTICAL, this);
+ horScrollBar = new FormScrollBar(Adjustable.HORIZONTAL, this);
+ if (useScrollBar) {
+ this.setLayout(new FormRulerLayout());
+ designer.setBorder(new LineBorder(new Color(198,198,198)));
+ this.add(FormRulerLayout.CENTER, designer);
+ addFormSize();
+ this.add(FormRulerLayout.VERTICAL, verScrollBar);
+ this.add(FormRulerLayout.HIRIZONTAL, horScrollBar);
+ enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
+ } else {
+ // 报表参数界面只要标尺和中心pane
+ this.setLayout(new RulerLayout());
+ this.add(RulerLayout.CENTER, designer);
+ addFormRuler();
+ }
+ this.setFocusTraversalKeysEnabled(false);
+ }
+
+ /**
+ * 增加表单的页面大小控制界面,包括手动修改和滑块拖动
+ */
+ private void addFormSize() {
+ double f = TableLayout.FILL;
+ double p = TableLayout.PREFERRED;
+ double[] rowSize = {f};
+ double[] columnSize = { p, f, p, p, p, p, p, f, p};
+ UILabel tipsPane = new UILabel("form");
+ tipsPane.setPreferredSize(new Dimension(200, 0));
+ widthPane = new UINumberField();
+ widthPane.setPreferredSize(new Dimension(60, 0));
+ heightPane = new UINumberField();
+ heightPane.setPreferredSize(new Dimension(60, 0));
+ slidePane = new UINumberSlidePane(SLIDER_MIN, SLIDER_FLOAT);
+ slidePane.setPreferredSize(new Dimension(200,0));
+ JPanel resizePane =TableLayoutHelper.createCommonTableLayoutPane(new JComponent[][]{
+ {tipsPane, new UILabel(), widthPane, new UILabel(Inter.getLocText("FR-Designer_Indent-Pixel")), new UILabel("x"),
+ heightPane, new UILabel(Inter.getLocText("FR-Designer_Indent-Pixel")), new UILabel(), slidePane}},
+ rowSize, columnSize, 8);
+ this.add(FormRulerLayout.BOTTOM, resizePane);
+ setWidgetsConfig();
+ // 先初始话滑块及对应事件,然后获取分辨率调整容器的显示大小
+ slidePane.setEnabled(false);
+ slidePane.setVisible(false);
+// initTransparent();
+ initCalculateSize();
+ }
+
+ private void setWidgetsConfig() {
+ widthPane.setHorizontalAlignment(widthPane.CENTER);
+ heightPane.setHorizontalAlignment(heightPane.CENTER);
+ widthPane.setMaxDecimalLength(0);
+ heightPane.setMaxDecimalLength(0);
+ //控件初始值就是根节点组件初始的宽和高
+ widthPane.setValue(designer.getRootComponent().getWidth());
+ heightPane.setValue(designer.getRootComponent().getHeight());
+ addWidthPaneListener();
+ addHeightPaneListener();
+ }
+
+ private void initTransparent() {
+ initCalculateSize();
+ slidePane.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ double value = ((UINumberSlidePane) e.getSource()).getValue();
+ reCalculateRoot(value, true);
+ JTemplate form = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate();
+ if(form != null){
+ form.fireTargetModified();
+ }
+ }
+ });
+ }
+
+ /**
+ * 返回当前的屏幕分辨率对应的百分比值
+ * @return 缩放的百分比值
+ */
+ public double getScreenValue() {
+ return screenValue;
+ }
+
+ /**
+ * 设置屏幕分辨率对应的百分比值
+ * @param screenValue 百分比值
+ */
+ public void setScreenValue(double screenValue) {
+ this.screenValue = screenValue;
+ }
+
+ private void initCalculateSize() {
+ Toolkit toolkit = Toolkit.getDefaultToolkit();
+ Dimension scrnsize = toolkit.getScreenSize();
+ this.screenValue = FRScreen.getByDimension(scrnsize).getValue();
+ XLayoutContainer root = FormArea.this.designer.getRootComponent();
+ // 7.1.1不放缩放滑块,但表单大小仍按屏幕分辨率调整
+// slidePane.populateBean(screenValue);
+ if (root.acceptType(XWFitLayout.class)) {
+ XWFitLayout layout = (XWFitLayout) root;
+ if (screenValue != DEFAULT_SLIDER ) {
+ reCalculateRoot(screenValue, true);
+ } else {
+ // 组件间隔啊
+ int val = layout.getAcualInterval();
+ layout.addCompInterval(val);
+ }
+ }
+ LayoutUtils.layoutContainer(root);
+ }
+
+ //设置宽度的控件及响应事件
+ private void addWidthPaneListener() {
+ widthPane.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ int width = (int) ((UINumberField) evt.getSource()).getValue();
+ changeWidthPaneValue(width);
+ }
+ });
+ widthPane.addFocusListener(
+ new FocusAdapter(){
+ public void focusLost(FocusEvent e){
+ // 失去焦点时,可以认为输入结束
+ int width = (int) ((UINumberField) e.getSource()).getValue();
+ changeWidthPaneValue(width);
+ }
+ });
+ }
+
+ private void changeWidthPaneValue(int width) {
+ XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
+ if (width != layout.toData().getContainerWidth()) {
+ reCalculateWidth(width);
+ designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
+ }
+ }
+
+ private void addHeightPaneListener() {
+ heightPane.addActionListener(
+ new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ int height = (int) ((UINumberField) evt.getSource()).getValue();
+ changeHeightPaneValue(height);
+ }
+ });
+ heightPane.addFocusListener(
+ new FocusAdapter(){
+ public void focusLost(FocusEvent e){
+ // 失去焦点时,可以认为输入结束
+ int height = (int) ((UINumberField) e.getSource()).getValue();
+ changeHeightPaneValue(height);
+ }
+ });
+ }
+
+ private void changeHeightPaneValue(int height) {
+ XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
+ if (height != layout.toData().getContainerHeight()) {
+ reCalculateHeight(height);
+ designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_EDITED);
+ }
+ }
+
+ private void reCalculateWidth(int width) {
+ XLayoutContainer root = FormArea.this.designer.getRootComponent();
+ if (root.acceptType(XWFitLayout.class)) {
+ XWFitLayout layout = (XWFitLayout) root;
+ Dimension d = new Dimension(layout.toData().getContainerWidth(), layout.toData().getContainerHeight());
+ Rectangle rec = new Rectangle(d);
+ // 容器大小改变时,设下backupBound为其之前的实际大小,以便调整贴边界的组件
+ layout.setBackupBound(rec);
+ int dW = width-rec.width;
+ if (dW == 0) {
+ return;
+ }
+ double percent = (double) dW/rec.width;
+ if (percent < 0 && !layout.canReduce(percent)) {
+ widthPane.setValue(rec.width);
+ return;
+ }
+ // 布局容器先设大小为实际的高和当前的宽,然后按此调整内部的组件
+ layout.setSize(width, rec.height);
+ layout.adjustCreatorsWidth(percent);
+ if (layout.getNeedAddWidth() > 0) {
+ widthPane.setValue(layout.getWidth());
+ // 调整之后清零调整量,否则再次缩放到最小值会产生干扰
+ layout.setNeedAddWidth(0);
+ }
+ doReCalculateRoot(width, rec.height, layout);
+ }
+ }
+
+ private void reCalculateHeight(int height) {
+ XLayoutContainer root = FormArea.this.designer.getRootComponent();
+ if (root.acceptType(XWFitLayout.class)) {
+ XWFitLayout layout = (XWFitLayout) root;
+ Dimension d = new Dimension(layout.toData().getContainerWidth(), layout.toData().getContainerHeight());
+ Rectangle rec = new Rectangle(d);
+ // 容器大小改变时,设下backupBound为其之前的实际大小
+ layout.setBackupBound(rec);
+ int dH = height - rec.height;
+ if (dH == 0) {
+ return;
+ }
+ double percent = (double) dH/rec.height;
+ if (percent < 0 && !layout.canReduce(percent)) {
+ heightPane.setValue(rec.height);
+ return;
+ }
+ layout.setSize(rec.width, height);
+ layout.adjustCreatorsHeight(percent);
+ if (layout.getNeedAddHeight() > 0) {
+ heightPane.setValue(layout.getHeight());
+ // 调整之后清零调整量,否则再次缩放到最小值会产生干扰
+ layout.setNeedAddHeight(0);
+ }
+ doReCalculateRoot(rec.width, height, layout);
+ }
+ }
+
+ /**
+ * 修改大小后,再根据屏幕分辨率调整下
+ */
+ private void doReCalculateRoot(int width, int height, XWFitLayout layout) {
+// double value = slidePane.updateBean();
+ //重置滑块的值为默认值100
+ START_VALUE = DEFAULT_SLIDER;
+ if (screenValue == DEFAULT_SLIDER) {
+ layout.getParent().setSize(width, height+designer.getParaHeight());
+ FormArea.this.validate();
+ } else {
+ layout.setBackupGap(screenValue/DEFAULT_SLIDER);
+ reCalculateRoot(screenValue, false);
+ }
+ }
+
+ /**
+ * 按照界面大小的百分比值调整root大小
+ * @param needCalculateParaHeight 是否需要调整参数界面高度
+ * @param value
+ */
+ private void reCalculateRoot(double value, boolean needCalculateParaHeight) {
+ if (value == START_VALUE) {
+ return;
+ }
+ double percent = (value - START_VALUE) / START_VALUE;
+ XLayoutContainer root = FormArea.this.designer.getRootComponent();
+ if (root.acceptType(XWFitLayout.class)) {
+ XWFitLayout layout = (XWFitLayout) root;
+ layout.setContainerPercent(value/DEFAULT_SLIDER);
+ traverAndAdjust(layout, percent);
+ layout.adjustCreatorsWhileSlide(percent);
+
+ // 拖动滑块,先将内部组件百分比大小计算,再计算容器大小
+
+ Dimension d = new Dimension(layout.getWidth(), layout.getHeight());
+ // 自适应布局的父层是border
+ if (layout.getParent() != null) {
+ int paraHeight = designer.getParaHeight();
+ if (needCalculateParaHeight && paraHeight > 0) {
+ // 调整参数界面的大小
+ paraHeight += (int) (paraHeight*percent) ;
+ designer.setParaHeight(paraHeight);
+ XWBorderLayout parent = (XWBorderLayout) layout.getParent();
+ parent.toData().setNorthSize(paraHeight);
+ parent.removeAll();
+ parent.add(designer.getParaComponent(),WBorderLayout.NORTH);
+ parent.add(designer.getRootComponent(),WBorderLayout.CENTER);
+ }
+ layout.getParent().setSize(d.width, d.height+paraHeight);
+ // 调整自适应布局大小后,同步调整参数界面和border大小,此时刷新下formArea
+ FormArea.this.validate();
+ }
+ START_VALUE = value;
+ }
+ }
+
+ //循环遍历布局,按百分比调整子组件大小
+ private void traverAndAdjust(XCreator creator,double percent){
+ for(int i=0; i= designer.getRootComponent().getWidth();
+ }
+
+ /**
+ * 设置界面内的组件可见以及水平垂直滚动条的值
+ * (除了根容器,拖入组件进来时如果大小超过当前界面大小,必须设置滚动条值,否则滚动条默认不显示)
+ *
+ * @param creator 控件
+ */
+ public void scrollPathToVisible(XCreator creator) {
+ creator.seleteRelatedComponent(creator);
+
+ if (!ComponentUtils.isComponentVisible(creator) && !designer.isRoot(creator) && (creator.toData()).isVisible()) {
+ designer.makeVisible(creator);
+ }
+
+ if (shouldSetScrollValue(creator)) {
+ return;
+ }
+ //获取在容器的绝对位置
+ Rectangle rec = ComponentUtils.getRelativeBounds(creator);
+ int dWidth = getDesignerWidth();
+ if (rec.width <= dWidth&&rec.x < getHorizontalValue()) {
+ //在边界内部且x位置小于水平滚动条的值
+ horScrollBar.setValue(rec.x);
+ } else if (rec.x+rec.width > dWidth) {
+ //超出边界宽度
+ horScrollBar.setValue(rec.x+rec.width-dWidth);
+ }
+ int dHeight = getDesignerHeight();
+ if (rec.height < dHeight && rec.y < getVerticalValue()) {
+ //在边界内部且y位置小于竖直滚动条的值
+ verScrollBar.setValue(rec.y);
+ } else if (rec.y+rec.height > dHeight) {
+ //超出边界高度
+ verScrollBar.setValue(rec.y+rec.height-dHeight);
+ }
+ }
+
+
+ /**
+ * 容器布局
+ */
+ public void doLayout() {
+ layout();
+ if (isValid) {
+ XLayoutContainer root = designer.getRootComponent();
+ setScrollBarProperties(root.getWidth()-designer.getWidth(), horScrollBar);
+ //计算滚动条值的时候应该算上参数面板的高度
+ setScrollBarProperties(designer.getParaHeight() + root.getHeight()-designer.getHeight(), verScrollBar);
+ }
+ }
+
+ /**
+ * 设置滚动条的属性
+ */
+ private void setScrollBarProperties(int value, FormScrollBar bar) {
+ if (value == 0 && isScrollNotVisible(bar)) {
+ return;
+ }
+ if (value <= 0) {
+ // 界面有滚动条时,手动缩小容器宽度到界面内,重置滚动条值和max
+ setScrollBarMax(0, bar);
+ bar.setMaximum(0);
+ bar.setValue(0);
+ bar.setEnabled(false);
+ } else {
+ //参数面板拖拽过程中value一直为当前value
+ int oldValue = verticalValue;
+ setScrollBarMax(value, bar);
+ bar.setEnabled(true);
+ bar.setMaximum(value);
+ bar.setValue(value);
+ bar.setValue(oldValue);
+ }
+ }
+
+ private boolean isScrollNotVisible(FormScrollBar bar) {
+ if (bar.getOrientation() == Adjustable.VERTICAL ) {
+ return verticalMax == 0;
+ } else {
+ return horicalMax == 0;
+ }
+ }
+
+ private void setScrollBarMax( int max, FormScrollBar bar) {
+ if (bar.getOrientation() == Adjustable.VERTICAL ) {
+ verticalMax = max;
+ } else {
+ horicalMax = max;
+ }
+ }
+
+ /**
+ *返回designer的最小高度
+ *
+ * @return int
+ */
+ public int getMinHeight() {
+ return designer.getDesignerMode().getMinDesignHeight();
+ }
+
+ /**
+ *返回designer的最小宽度
+ *
+ * @return int
+ */
+ public int getMinWidth() {
+ return designer.getDesignerMode().getMinDesignWidth();
+ }
+
+ /**
+ * getRulerLengthUnit
+ *
+ * @return short
+ */
+ public short getRulerLengthUnit() {
+ return -1;
+ }
+
+ /**
+ * 返回水平滚动条的value
+ *
+ * @return int
+ */
+ public int getHorizontalValue() {
+ return horizontalValue;
+ }
+
+ /**
+ * 设置水平滚动条的value
+ *
+ * @param newValue
+ */
+ public void setHorizontalValue(int newValue) {
+ this.horizontalValue = newValue;
+ }
+
+ /**
+ * 返回竖直滚动条的value
+ *
+ * @return
+ */
+ public int getVerticalValue() {
+ return verticalValue;
+ }
+
+ /**
+ * 竖直滚动条赋值
+ *
+ * @param newValue
+ */
+ public void setVerticalValue(int newValue) {
+ this.verticalValue = newValue;
+ }
+
+ /**
+ * 返回当前designer的高度
+ *
+ * @return height
+ */
+ public int getDesignerHeight() {
+ return designer.getHeight();
+ }
+
+ /**
+ * 返回当前designer的宽度
+ *
+ * @return
+ */
+ public int getDesignerWidth() {
+ return designer.getWidth();
+ }
+
+ /**
+ * 返回宽度控件的value
+ *
+ * @return 宽度
+ */
+ public double getWidthPaneValue() {
+ return widthPane.getValue();
+ }
+
+ /**
+ * 设置宽度值
+ * @param value 值
+ */
+ public void setWidthPaneValue(int value) {
+ widthPane.setValue(value);
+ }
+
+ /**
+ * 设置高度值
+ * @param value 值
+ */
+ public void setHeightPaneValue(int value) {
+ heightPane.setValue(value);
+ }
+
+ /**
+ * 返回高度控件的value
+ *
+ * @return 高度
+ */
+ public double getHeightPaneValue() {
+ return heightPane.getValue();
+ }
+
+ /**
+ * 返回界面大小的百分比值
+ *
+ * @return 百分比值
+ */
+ public double getSlideValue() {
+// return slidePane.updateBean();
+ //7.1.1不加缩放滑块
+ return this.screenValue;
+ }
+
+ /**
+ * 返回界面区域大小
+ *
+ * @return Dimension
+ */
+ public Dimension getAreaSize() {
+ return new Dimension(horScrollBar.getMaximum(), verScrollBar.getMaximum());
+ }
+
+ /**
+ * setAreaSize
+ *
+ * @param totalSize
+ * @param horizontalValue
+ * @param verticalValue
+ */
+ public void setAreaSize(Dimension totalSize, int horizontalValue, int verticalValue, double width, double height, double slide) {
+ this.verticalMax = (int) totalSize.getHeight();
+ this.horicalMax = (int) totalSize.getHeight();
+ // 撤销时会refreshRoot,导致layout大小变为默认大小
+ // 按照之前设置的宽高和百分比重置下容器size
+ if (width != widthPane.getValue()) {
+ widthPane.setValue(width);
+ reCalculateWidth((int) width);
+ }
+ if (height != heightPane.getValue()) {
+ heightPane.setValue(height);
+ reCalculateHeight((int) height);
+ }
+ if (designer.getRootComponent().acceptType(XWFitLayout.class) && slide == DEFAULT_SLIDER) {
+ XWFitLayout layout = (XWFitLayout) designer.getRootComponent();
+ // 撤销时先refreshRoot了,此处去掉内边距再增加间隔
+ layout.moveContainerMargin();
+ layout.addCompInterval(layout.getAcualInterval());
+ } else if (designer.getRootComponent().acceptType(XWFitLayout.class)){
+ START_VALUE = DEFAULT_SLIDER;
+ reCalculateRoot(slide, true);
+// slidePane.populateBean(slide);
+ }
+ }
+
+ /**
+ * 计算滚动条的值和max
+ * @param oldmax 之前最大值
+ * @param max 当前最大值
+ * @param newValue 当前value
+ * @param oldValue 之前value
+ * @param visi designer的大小
+ * @param orientation 滚动条方向
+ * @return 计算后的值和max
+ */
+ @Override
+ public Point calculateScroll(int oldmax, int max, int newValue, int oldValue, int visi, int orientation) {
+ int scrollMax = orientation==1 ? verticalMax : horicalMax;
+ //防止滚动条到达低端还可以继续点击移动(滚动条最大范围不变时,newValue要在范围之内)
+ if ( oldmax == scrollMax+visi && newValue>scrollMax ) {
+ return new Point(oldValue, oldmax);
+ }
+ return new Point(newValue, max);
+ }
+
+ private class FormRulerLayout extends RulerLayout{
+ private int DESIGNERWIDTH = 960;
+ private int DESIGNERHEIGHT =540;
+ private int TOPGAP = 8;
+
+ public FormRulerLayout(){
+ super();
+ }
+
+ /**
+ * 表单用的layout,当前不需要标尺
+ */
+ public void layoutContainer(Container target) {
+ synchronized (target.getTreeLock()) {
+ Insets insets = target.getInsets();
+ int top = insets.top;
+ int left = insets.left;
+ int bottom = target.getHeight() - insets.bottom;
+ int right = target.getWidth() - insets.right;
+ Dimension resize = resizePane.getPreferredSize();
+ Dimension hbarPreferredSize = null;
+ Dimension vbarPreferredSize = null;
+
+ resizePane.setBounds(left, bottom - resize.height, right, resize.height);
+ if(horScrollBar != null) {
+ hbarPreferredSize = horScrollBar.getPreferredSize();
+ vbarPreferredSize = verScrollBar.getPreferredSize();
+ horScrollBar.setBounds(left , bottom - hbarPreferredSize.height-resize.height, right - BARSIZE, hbarPreferredSize.height);
+ verScrollBar.setBounds(right - vbarPreferredSize.width, top, vbarPreferredSize.width, bottom - BARSIZE-resize.height);
+ }
+ FormDesigner dg = ((FormDesigner) designer);
+ XLayoutContainer root = dg.getRootComponent();
+ if (root.acceptType(XWFitLayout.class)) {
+ DESIGNERWIDTH = root.getWidth();
+ DESIGNERHEIGHT = dg.hasWAbsoluteLayout() ? root.getHeight()+dg.getParaHeight() : root.getHeight();
+ }
+ Rectangle rec = new Rectangle(left+(right - DESIGNERWIDTH)/2, TOPGAP, right, bottom);
+ //是否为表单
+ if (isValid ){
+ int maxHeight = bottom - hbarPreferredSize.height - resize.height -TOPGAP*2;
+ int maxWidth = right - vbarPreferredSize.width;
+ DESIGNERWIDTH = DESIGNERWIDTH> maxWidth ? maxWidth : DESIGNERWIDTH;
+ DESIGNERHEIGHT = DESIGNERHEIGHT > maxHeight ? maxHeight : DESIGNERHEIGHT;
+ int designerLeft = left+(verScrollBar.getX() - DESIGNERWIDTH)/2;
+ rec = new Rectangle(designerLeft, TOPGAP, DESIGNERWIDTH, DESIGNERHEIGHT);
+ }
+ // designer是整个表单设计界面中的面板部分,目前只放自适应布局和参数界面。
+ designer.setBounds(rec);
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java b/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java
new file mode 100644
index 000000000..a90ba7fb6
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/FormCreatorDropTarget.java
@@ -0,0 +1,239 @@
+package com.fr.design.mainframe;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JWindow;
+
+import com.fr.base.BaseUtils;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.HoverPainter;
+import com.fr.design.designer.beans.Painter;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.models.AddingModel;
+import com.fr.design.designer.creator.XCreator;
+import com.fr.design.designer.creator.XCreatorUtils;
+import com.fr.design.designer.creator.XLayoutContainer;
+import com.fr.design.designer.creator.XWFitLayout;
+import com.fr.design.designer.creator.XWParameterLayout;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.gui.ibutton.UIButton;
+import com.fr.design.icon.IconPathConstants;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.form.ui.Widget;
+import com.fr.general.Inter;
+import com.fr.stable.Constants;
+
+/**
+ * 添加模式下鼠标事件处理器。
+ */
+public class FormCreatorDropTarget extends DropTarget {
+
+ private FormDesigner designer;
+ /**
+ * 当前鼠标的设计组件
+ */
+ private Component current;
+ /**
+ * 当前添加模式对应的model
+ */
+ private AddingModel addingModel;
+ private final static int GAP = 30;
+
+ private JWindow promptWindow = new JWindow();
+ private UIButton promptButton = new UIButton("", BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH));
+
+ public FormCreatorDropTarget(FormDesigner designer) {
+ this.designer = designer;
+ this.addingModel = designer.getAddingModel();
+ this.promptWindow.add(promptButton);
+ }
+
+ private void adding(int x, int y) {
+ // 当前鼠标所在的组件
+ XCreator hoveredComponent = designer.getComponentAt(x, y);
+
+ // 获取该组件所在的焦点容器
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent);
+
+ //cardTagLayout里用到
+ container.stopAddingState(designer);
+
+ boolean success = false;
+
+ if (container != null) {
+ // 如果是容器,则调用其acceptComponent接受组件
+ AddingModel model = designer.getAddingModel();
+
+ boolean chartEnter2Para =!addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class);
+ boolean formSubmit2Adapt = !addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class);
+
+ if (model != null && !chartEnter2Para && !formSubmit2Adapt) {
+ success = model.add2Container(designer, container, x, y);
+ }
+ cancelPromptWidgetForbidEnter();
+ }
+
+ if (success) {
+ // 如果添加成功,则触发相应事件
+ XCreator xCreator = container.acceptType(XWParameterLayout.class) ? designer.getParaComponent() : designer.getRootComponent();
+ designer.getSelectionModel().setSelectedCreators(
+ FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{addingModel.getXCreator().toData()}));
+ designer.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED);
+ } else {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ // 取消提示
+ designer.setPainter(null);
+ // 切换添加状态到普通状态
+ designer.stopAddingState();
+ }
+
+ private void entering(int x, int y) {
+ // 将要添加的组件图标移动到鼠标下的位置
+ addingModel.moveTo(x, y);
+ designer.repaint();
+ }
+
+ private void exiting() {
+ cancelPromptWidgetForbidEnter();
+ // 隐藏组件图标
+ addingModel.reset();
+ designer.setPainter(null);
+ designer.repaint();
+ }
+
+ private void hovering(int x, int y) {
+ // 当前位置移植鼠标e所在的位置
+ addingModel.moveTo(x, y);
+ // 获取e所在的焦点组件
+ XCreator hotspot = designer.getComponentAt(x, y);
+ // 获取焦点组件所在的焦点容器
+ XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot);
+ //提示组件是否可以拖入
+ promptUser(x, y, container);
+ if (container != null) {
+ HoverPainter painter = null;
+
+ if (container != current || designer.getPainter() == null) {
+ // 如果焦点容器不是当前容器
+ if (current != null) {
+ // 取消前一个焦点容器的提示渲染器
+ designer.setPainter(null);
+ }
+
+ painter = AdapterBus.getContainerPainter(designer, container);
+
+ // 为界面设计器设置提示渲染提示器
+ designer.setPainter(painter);
+
+ // 将当前容器更新为新的容器
+ current = container;
+ } else {
+ // 获取当前设计界面的提示渲染器
+ Painter p = designer.getPainter();
+ if (p instanceof HoverPainter) {
+ painter = (HoverPainter) p;
+ }
+ }
+
+ if (painter != null) {
+ // 为提示渲染器设置焦点位置、区域等渲染参数
+ Rectangle rect = ComponentUtils.getRelativeBounds(container);
+ rect.x -= designer.getArea().getHorizontalValue();
+ rect.y -= designer.getArea().getVerticalValue();
+ painter.setRenderingBounds(rect);
+ painter.setHotspot(new Point(x, y));
+ painter.setCreator(addingModel.getXCreator());
+ }
+ } else {
+ // 如果鼠标不在任何组件上,则取消提示器
+ designer.setPainter(null);
+ current = null;
+ }
+ designer.repaint();
+ }
+
+ private void promptUser(int x, int y, XLayoutContainer container){
+ if (!addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class)){
+ promptButton.setText(Inter.getLocText("FR-Designer_Forbid_Drag_into_Para_Pane"));
+ promptWidgetForbidEnter(x ,y ,container);
+ } else if (!addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)){
+ promptButton.setText(Inter.getLocText("FR-Designer_Forbid_Drag_into_Adapt_Pane"));
+ promptWidgetForbidEnter(x ,y , container);
+ } else {
+ cancelPromptWidgetForbidEnter();
+ }
+ }
+
+ private void promptWidgetForbidEnter(int x,int y, XLayoutContainer container){
+ container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM));
+ int screen_X = (int)designer.getArea().getLocationOnScreen().getX();
+ int screen_Y = (int)designer.getArea().getLocationOnScreen().getY();
+ this.promptWindow.setSize(promptWindow.getPreferredSize());
+ this.promptWindow.setPreferredSize(promptWindow.getPreferredSize());
+ promptWindow.setLocation( screen_X + x + GAP ,screen_Y + y + GAP);
+ promptWindow.setVisible(true);
+ }
+
+ private void cancelPromptWidgetForbidEnter(){
+ if (designer.getParaComponent() != null){
+ designer.getParaComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN));
+ }
+ designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN));
+ promptWindow.setVisible(false);
+ }
+
+ /**
+ * 拖拽进入
+ * @param dtde 事件
+ */
+ public void dragEnter(DropTargetDragEvent dtde) {
+ Point loc = dtde.getLocation();
+ this.entering(loc.x, loc.y);
+ }
+
+ /**
+ * 拖拽移动经过
+ * @param dtde 事件
+ */
+ public void dragOver(DropTargetDragEvent dtde) {
+ Point loc = dtde.getLocation();
+ hovering(loc.x, loc.y);
+ }
+
+ /**
+ * 拖拽事件
+ * @param dtde 事件
+ */
+ public void dropActionChanged(DropTargetDragEvent dtde) {
+ }
+
+ /**
+ * 拖拽离开
+ * @param dte 事件
+ */
+ public void dragExit(DropTargetEvent dte) {
+ this.exiting();
+ }
+
+ /**
+ * 拖拽释放
+ * @param dtde 事件
+ */
+ public void drop(DropTargetDropEvent dtde) {
+ Point loc = dtde.getLocation();
+ this.adding(loc.x, loc.y);
+ //针对在表单中拖入一个控件直接ctrl+s无反应
+ designer.requestFocus();
+ }
+}
\ No newline at end of file
diff --git a/designer_form/src/com/fr/design/mainframe/FormDesigner.java b/designer_form/src/com/fr/design/mainframe/FormDesigner.java
new file mode 100644
index 000000000..6312c5248
--- /dev/null
+++ b/designer_form/src/com/fr/design/mainframe/FormDesigner.java
@@ -0,0 +1,1382 @@
+package com.fr.design.mainframe;
+
+import com.fr.base.BaseUtils;
+import com.fr.base.Parameter;
+import com.fr.design.DesignState;
+import com.fr.design.designer.TargetComponent;
+import com.fr.design.designer.beans.AdapterBus;
+import com.fr.design.designer.beans.Painter;
+import com.fr.design.designer.beans.actions.FormDeleteAction;
+import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter;
+import com.fr.design.designer.beans.events.CreatorEventListenerTable;
+import com.fr.design.designer.beans.events.DesignerEditListener;
+import com.fr.design.designer.beans.events.DesignerEvent;
+import com.fr.design.designer.beans.location.Direction;
+import com.fr.design.designer.beans.location.Location;
+import com.fr.design.designer.beans.location.RootResizeDirection;
+import com.fr.design.designer.beans.models.AddingModel;
+import com.fr.design.designer.beans.models.SelectionModel;
+import com.fr.design.designer.beans.models.StateModel;
+import com.fr.design.designer.creator.*;
+import com.fr.design.designer.properties.FormWidgetAuthorityEditPane;
+import com.fr.design.file.HistoryTemplateListPane;
+import com.fr.design.form.util.XCreatorConstants;
+import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus;
+import com.fr.design.menu.MenuDef;
+import com.fr.design.menu.ShortCut;
+import com.fr.design.menu.ToolBarDef;
+import com.fr.design.parameter.ParaDefinitePane;
+import com.fr.design.parameter.ParameterPropertyPane;
+import com.fr.design.roleAuthority.RolesAlreadyEditedPane;
+import com.fr.design.utils.ComponentUtils;
+import com.fr.design.utils.gui.LayoutUtils;
+import com.fr.form.FormElementCaseContainerProvider;
+import com.fr.form.FormElementCaseProvider;
+import com.fr.form.main.Form;
+import com.fr.form.parameter.FormSubmitButton;
+import com.fr.form.ui.EditorHolder;
+import com.fr.form.ui.PaddingMargin;
+import com.fr.form.ui.Widget;
+import com.fr.form.ui.WidgetValue;
+import com.fr.form.ui.container.WBorderLayout;
+import com.fr.form.ui.container.WFitLayout;
+import com.fr.general.ComparatorUtils;
+import com.fr.general.FRLogger;
+import com.fr.general.Inter;
+import com.fr.plugin.ExtraClassManager;
+import com.fr.stable.ArrayUtils;
+import com.fr.stable.bridge.StableFactory;
+import edu.emory.mathcs.backport.java.util.Arrays;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.awt.image.BufferedImage;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 设计界面组件。该组件是界面设计工具的核心,主要负责的是被设计界面的显示,界面设计操作状态的 显示,编辑状态的显示等等。
+ */
+public class FormDesigner extends TargetComponent