Qinghui.Liu
5 years ago
51 changed files with 1552 additions and 578 deletions
@ -0,0 +1,82 @@
|
||||
import org.gradle.plugins.ide.idea.model.IdeaLanguageLevel |
||||
|
||||
plugins { |
||||
id 'java' |
||||
id 'java-library' |
||||
id 'com.fr.common' version '1.0-SNAPSHOT' |
||||
} |
||||
|
||||
// 模块参数 |
||||
ext { |
||||
frVersion = "" |
||||
outputPath = "build" |
||||
ignoreTestFailureSetting = true |
||||
languageLevelSetting = 1.8 |
||||
} |
||||
|
||||
applyGlobalConfigPathIfExist() |
||||
|
||||
if (versions.frVersion) { |
||||
frVersion = versions.frVersion |
||||
} |
||||
def frDevVersion = "DEV" + frVersion |
||||
|
||||
dependencies { |
||||
api project(':designer-base') |
||||
api project(':designer-chart') |
||||
api project(':designer-form') |
||||
api project(':designer-realize') |
||||
} |
||||
|
||||
allprojects { |
||||
apply plugin: 'java' |
||||
apply plugin: 'java-library' |
||||
apply plugin: 'idea' |
||||
|
||||
group 'com.fr.design' |
||||
version frDevVersion |
||||
sourceCompatibility = languageLevelSetting |
||||
targetCompatibility = languageLevelSetting |
||||
|
||||
tasks.withType(JavaCompile) { |
||||
options.encoding = "UTF-8" |
||||
} |
||||
|
||||
repositories { |
||||
mavenLocal() |
||||
} |
||||
|
||||
idea { |
||||
module { |
||||
inheritOutputDirs = false |
||||
outputDir = file(outputPath +"/classes") |
||||
testOutputDir = file(outputPath +"/test-classes") |
||||
languageLevel = new IdeaLanguageLevel(sourceCompatibility) |
||||
targetBytecodeVersion = targetCompatibility |
||||
} |
||||
} |
||||
|
||||
dependencies { |
||||
implementation 'com.fr.third:jxbrowser:7.5' |
||||
implementation 'com.fr.third:jxbrowser-swing:7.5' |
||||
implementation 'com.fr.third:jxbrowser-mac:7.5' |
||||
implementation 'com.fr.third:jxbrowser-win64:7.5' |
||||
implementation 'com.fr.third.server:servlet-api:3.0' |
||||
implementation 'org.swingexplorer:swexpl:2.0.1' |
||||
implementation 'org.swingexplorer:swag:1.0' |
||||
implementation 'net.java.dev.jna:jna:5.4.0' |
||||
implementation 'org.apache.tomcat:tomcat-catalina:8.5.32' |
||||
implementation 'io.socket:socket.io-client:0.7.0' |
||||
implementation 'com.fr.third:fine-third:' + frVersion |
||||
implementation 'com.fr.core:fine-core:' + frDevVersion |
||||
implementation 'com.fr.activator:fine-activator:' + frVersion |
||||
implementation 'com.fr.datasource:fine-datasource:' + frVersion |
||||
implementation 'com.fr.decision:fine-decision:' + frVersion |
||||
implementation 'com.fr.schedule:fine-schedule:' + frVersion |
||||
implementation 'com.fr.report:fine-report-engine:' + frDevVersion |
||||
testImplementation 'org.easymock:easymock:3.5.1' |
||||
testImplementation 'org.powermock:powermock-module-junit4:1.7.1' |
||||
testImplementation 'org.powermock:powermock-api-easymock:1.7.1' |
||||
testImplementation 'junit:junit:4.12' |
||||
} |
||||
} |
@ -1,234 +0,0 @@
|
||||
package com.fr.design.extra; |
||||
|
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.general.IOUtils; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import javafx.application.Platform; |
||||
import javafx.beans.property.BooleanProperty; |
||||
import javafx.beans.property.SimpleBooleanProperty; |
||||
import javafx.beans.value.ChangeListener; |
||||
import javafx.beans.value.ObservableValue; |
||||
import javafx.concurrent.Worker; |
||||
import javafx.embed.swing.JFXPanel; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.event.EventHandler; |
||||
import javafx.scene.Group; |
||||
import javafx.scene.Node; |
||||
import javafx.scene.Scene; |
||||
import javafx.scene.control.ButtonBuilder; |
||||
import javafx.scene.control.LabelBuilder; |
||||
import javafx.scene.input.MouseEvent; |
||||
import javafx.scene.layout.BorderPane; |
||||
import javafx.scene.layout.HBox; |
||||
import javafx.scene.layout.HBoxBuilder; |
||||
import javafx.scene.paint.Color; |
||||
import javafx.scene.web.WebEngine; |
||||
import javafx.scene.web.WebEvent; |
||||
import javafx.scene.web.WebView; |
||||
import javafx.stage.Modality; |
||||
import javafx.stage.Screen; |
||||
import javafx.stage.Stage; |
||||
import javafx.stage.StageStyle; |
||||
import javafx.stage.WindowEvent; |
||||
import javafx.util.Callback; |
||||
import netscape.javascript.JSObject; |
||||
|
||||
import javax.swing.JOptionPane; |
||||
import javax.swing.SwingUtilities; |
||||
import java.awt.Toolkit; |
||||
|
||||
/** |
||||
* Created by zhaohehe on 16/7/28. |
||||
*/ |
||||
public class QQLoginWebPane extends JFXPanel { |
||||
|
||||
private WebEngine webEngine; |
||||
private String url; |
||||
|
||||
private static JSObject window; |
||||
|
||||
private static int DEFAULT_PRIMARYSTAGE_WIDTH = 100; |
||||
private static int DEFAULT_PRIMARYSTAGE_HEIGHT = 100; |
||||
|
||||
private static int DEFAULT_CONFIRM_WIDTH = 450; |
||||
private static int DEFAULT_CONFIRM_HEIGHT = 160; |
||||
private static int DEFAULT_OFFEST = 20; |
||||
|
||||
class Delta { |
||||
double x, y; |
||||
} |
||||
|
||||
public QQLoginWebPane(final String installHome) { |
||||
Platform.setImplicitExit(false); |
||||
Platform.runLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
BorderPane root = new BorderPane(); |
||||
Scene scene = new Scene(root); |
||||
QQLoginWebPane.this.setScene(scene); |
||||
final WebView webView = new WebView(); |
||||
webEngine = webView.getEngine(); |
||||
url = "file:///" + installHome + "/scripts/qqLogin.html"; |
||||
webEngine.load(url); |
||||
|
||||
final Stage primaryStage = new Stage(); |
||||
|
||||
HBox layout = new HBox(); |
||||
try { |
||||
primaryStage.initStyle(StageStyle.TRANSPARENT); |
||||
primaryStage.setScene(new Scene(layout)); |
||||
webView.getScene().getStylesheets().add(IOUtils.getResource("modal-dialog.css", getClass()).toExternalForm()); |
||||
primaryStage.initStyle(StageStyle.UTILITY); |
||||
primaryStage.setScene(new Scene(new Group(), DEFAULT_PRIMARYSTAGE_WIDTH, DEFAULT_PRIMARYSTAGE_HEIGHT)); |
||||
primaryStage.setX(0); |
||||
primaryStage.setY(Screen.getPrimary().getBounds().getHeight() + DEFAULT_PRIMARYSTAGE_HEIGHT); |
||||
primaryStage.show(); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().info(e.getMessage()); |
||||
} |
||||
webEngine.setConfirmHandler(new Callback<String, Boolean>() { |
||||
@Override |
||||
public Boolean call(String msg) { |
||||
Boolean confirmed = confirm(primaryStage, msg, webView); |
||||
return confirmed; |
||||
} |
||||
}); |
||||
configWebEngine(); |
||||
webView.setContextMenuEnabled(false);//屏蔽右键
|
||||
root.setCenter(webView); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void configWebEngine() { |
||||
|
||||
webEngine.locationProperty().addListener(new ChangeListener<String>() { |
||||
@Override |
||||
public void changed(ObservableValue<? extends String> observable, final String oldValue, String newValue) { |
||||
disableLink(webEngine); |
||||
// webView好像默认以手机版显示网页,浏览器里过滤掉这个跳转
|
||||
if (ComparatorUtils.equals(newValue, url) || ComparatorUtils.equals(newValue, CloudCenter.getInstance().acquireUrlByKind("bbs.mobile"))) { |
||||
return; |
||||
} |
||||
LoginWebBridge.getHelper().openUrlAtLocalWebBrowser(webEngine, newValue); |
||||
} |
||||
}); |
||||
|
||||
webEngine.setOnAlert(new EventHandler<WebEvent<String>>() { |
||||
@Override |
||||
public void handle(WebEvent<String> event) { |
||||
showAlert(event.getData()); |
||||
} |
||||
}); |
||||
|
||||
webEngine.getLoadWorker().stateProperty().addListener( |
||||
new ChangeListener<Worker.State>() { |
||||
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) { |
||||
if (newState == Worker.State.SUCCEEDED) { |
||||
window = (JSObject) webEngine.executeScript("window"); |
||||
window.setMember("QQLoginHelper", LoginWebBridge.getHelper()); |
||||
} |
||||
} |
||||
} |
||||
); |
||||
} |
||||
|
||||
private void showAlert(final String message) { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
FineJOptionPane.showMessageDialog(QQLoginWebPane.this, message); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void disableLink(final WebEngine eng) { |
||||
try { |
||||
// webView端不跳转 虽然webView可以指定本地浏览器打开某个链接,但是当本地浏览器跳转到指定链接的同时,webView也做了跳转,
|
||||
// 为了避免出现在一个600*400的资讯框里加载整个网页的情况,webView不跳转到新网页
|
||||
Platform.runLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
eng.executeScript("location.reload()"); |
||||
LoginWebBridge.getHelper().closeQQWindow(); |
||||
} |
||||
}); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
private Boolean confirm(final Stage parent, String msg, final WebView webView) { |
||||
final BooleanProperty confirmationResult = new SimpleBooleanProperty(); |
||||
// initialize the confirmation dialog
|
||||
final Stage dialog = new Stage(StageStyle.UTILITY); |
||||
dialog.setX(Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - DEFAULT_CONFIRM_WIDTH / 2.0D + DEFAULT_OFFEST); |
||||
dialog.setY(Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 + DEFAULT_OFFEST); |
||||
dialog.setHeight(DEFAULT_CONFIRM_HEIGHT); |
||||
dialog.setWidth(DEFAULT_CONFIRM_WIDTH); |
||||
dialog.setIconified(false); |
||||
dialog.initOwner(parent); |
||||
dialog.initModality(Modality.WINDOW_MODAL); |
||||
dialog.setScene( |
||||
new Scene( |
||||
HBoxBuilder.create().styleClass("modal-dialog").children( |
||||
LabelBuilder.create().text(msg).build(), |
||||
ButtonBuilder.create().text(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_BBSLogin_Switch_Account")).defaultButton(true).onAction(new EventHandler<ActionEvent>() { |
||||
@Override |
||||
public void handle(ActionEvent actionEvent) { |
||||
// take action and close the dialog.
|
||||
confirmationResult.set(true); |
||||
webView.getEngine().reload(); |
||||
dialog.close(); |
||||
} |
||||
}).build(), |
||||
ButtonBuilder.create().text(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Engine_Cancel")).cancelButton(true).onAction(new EventHandler<ActionEvent>() { |
||||
@Override |
||||
public void handle(ActionEvent actionEvent) { |
||||
// abort action and close the dialog.
|
||||
confirmationResult.set(false); |
||||
dialog.close(); |
||||
} |
||||
}).build() |
||||
).build() |
||||
, Color.TRANSPARENT |
||||
) |
||||
); |
||||
configDrag(dialog); |
||||
// style and show the dialog.
|
||||
dialog.getScene().getStylesheets().add(IOUtils.getResource("modal-dialog.css", getClass()).toExternalForm()); |
||||
dialog.setOnCloseRequest(new EventHandler<WindowEvent>() { |
||||
@Override |
||||
public void handle(WindowEvent event) { |
||||
event.consume(); |
||||
dialog.close(); |
||||
} |
||||
}); |
||||
dialog.showAndWait(); |
||||
return confirmationResult.get(); |
||||
} |
||||
|
||||
private void configDrag(final Stage dialog) { |
||||
// allow the dialog to be dragged around.
|
||||
final Node root = dialog.getScene().getRoot(); |
||||
final Delta dragDelta = new Delta(); |
||||
|
||||
root.setOnMousePressed(new EventHandler<MouseEvent>() { |
||||
@Override |
||||
public void handle(MouseEvent mouseEvent) { |
||||
// record a delta distance for the drag and drop operation.
|
||||
dragDelta.x = dialog.getX() - mouseEvent.getScreenX(); |
||||
dragDelta.y = dialog.getY() - mouseEvent.getScreenY(); |
||||
} |
||||
}); |
||||
root.setOnMouseDragged(new EventHandler<MouseEvent>() { |
||||
@Override |
||||
public void handle(MouseEvent mouseEvent) { |
||||
dialog.setX(mouseEvent.getScreenX() + dragDelta.x); |
||||
dialog.setY(mouseEvent.getScreenY() + dragDelta.y); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,200 @@
|
||||
package com.fr.design.utils; |
||||
|
||||
import sun.awt.SunToolkit; |
||||
|
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* 适配jdk10之后被移除的 com.sun.awt.AWTUtilities |
||||
* 参照 https://github.com/frohoff/jdk8u-dev-jdk/blob/master/src/share/classes/com/sun/awt/AWTUtilities.java中实现
|
||||
* |
||||
* @author hades |
||||
* @version 10.0 |
||||
* Created by hades on 2020/5/29 |
||||
*/ |
||||
public class AWTUtilities { |
||||
|
||||
/** |
||||
* @param window the window to set the shape to |
||||
* @param shape the shape to set to the window |
||||
* |
||||
*/ |
||||
public static void setWindowShape(Window window, Shape shape) { |
||||
if (window == null) { |
||||
throw new NullPointerException("The window argument should not be null."); |
||||
} |
||||
window.setShape(shape); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* |
||||
* @param window the window to set the shape to |
||||
* @param opaque whether the window must be opaque (true), |
||||
* or translucent (false) |
||||
* |
||||
*/ |
||||
public static void setWindowOpaque(Window window, boolean opaque) { |
||||
if (window == null) { |
||||
throw new NullPointerException("The window argument should not be null."); |
||||
} |
||||
if (!opaque && !isTranslucencySupported(Translucency.PERPIXEL_TRANSLUCENT)) { |
||||
throw new UnsupportedOperationException("The PERPIXEL_TRANSLUCENT translucency kind is not supported"); |
||||
} |
||||
Color color = window.getBackground(); |
||||
if (color == null) { |
||||
color = new Color(0, 0, 0, 0); |
||||
} |
||||
window.setBackground(new Color(color.getRed(), color.getGreen(), color.getBlue(), opaque ? 255 : 0)); |
||||
} |
||||
|
||||
|
||||
public static enum Translucency { |
||||
/** |
||||
* Represents support in the underlying system for windows each pixel |
||||
* of which is guaranteed to be either completely opaque, with |
||||
* an alpha value of 1.0, or completely transparent, with an alpha |
||||
* value of 0.0. |
||||
*/ |
||||
PERPIXEL_TRANSPARENT, |
||||
|
||||
/** |
||||
* Represents support in the underlying system for windows all of |
||||
* the pixels of which have the same alpha value between or including |
||||
* 0.0 and 1.0. |
||||
*/ |
||||
TRANSLUCENT, |
||||
|
||||
/** |
||||
* Represents support in the underlying system for windows that |
||||
* contain or might contain pixels with arbitrary alpha values |
||||
* between and including 0.0 and 1.0. |
||||
*/ |
||||
PERPIXEL_TRANSLUCENT; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns whether the given level of translucency is supported by |
||||
* the underlying system. |
||||
* |
||||
* Note that this method may sometimes return the value |
||||
* indicating that the particular level is supported, but |
||||
* the native windowing system may still not support the |
||||
* given level of translucency (due to the bugs in |
||||
* the windowing system). |
||||
* |
||||
* @param translucencyKind a kind of translucency support |
||||
* (either PERPIXEL_TRANSPARENT, |
||||
* TRANSLUCENT, or PERPIXEL_TRANSLUCENT) |
||||
* @return whether the given translucency kind is supported |
||||
*/ |
||||
private static boolean isTranslucencySupported(Translucency translucencyKind) { |
||||
switch (translucencyKind) { |
||||
case PERPIXEL_TRANSPARENT: |
||||
return isWindowShapingSupported(); |
||||
case TRANSLUCENT: |
||||
return isWindowOpacitySupported(); |
||||
case PERPIXEL_TRANSLUCENT: |
||||
return isWindowTranslucencySupported(); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the windowing system supports changing the opacity |
||||
* value of top-level windows. |
||||
* Note that this method may sometimes return true, but the native |
||||
* windowing system may still not support the concept of |
||||
* translucency (due to the bugs in the windowing system). |
||||
*/ |
||||
private static boolean isWindowOpacitySupported() { |
||||
Toolkit curToolkit = Toolkit.getDefaultToolkit(); |
||||
if (!(curToolkit instanceof SunToolkit)) { |
||||
return false; |
||||
} |
||||
return ((SunToolkit)curToolkit).isWindowOpacitySupported(); |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the windowing system supports changing the shape |
||||
* of top-level windows. |
||||
* Note that this method may sometimes return true, but the native |
||||
* windowing system may still not support the concept of |
||||
* shaping (due to the bugs in the windowing system). |
||||
*/ |
||||
private static boolean isWindowShapingSupported() { |
||||
Toolkit curToolkit = Toolkit.getDefaultToolkit(); |
||||
if (!(curToolkit instanceof SunToolkit)) { |
||||
return false; |
||||
} |
||||
return ((SunToolkit)curToolkit).isWindowShapingSupported(); |
||||
} |
||||
|
||||
private static boolean isWindowTranslucencySupported() { |
||||
/* |
||||
* Per-pixel alpha is supported if all the conditions are TRUE: |
||||
* 1. The toolkit is a sort of SunToolkit |
||||
* 2. The toolkit supports translucency in general |
||||
* (isWindowTranslucencySupported()) |
||||
* 3. There's at least one translucency-capable |
||||
* GraphicsConfiguration |
||||
*/ |
||||
|
||||
Toolkit curToolkit = Toolkit.getDefaultToolkit(); |
||||
if (!(curToolkit instanceof SunToolkit)) { |
||||
return false; |
||||
} |
||||
|
||||
if (!((SunToolkit)curToolkit).isWindowTranslucencySupported()) { |
||||
return false; |
||||
} |
||||
|
||||
GraphicsEnvironment env = |
||||
GraphicsEnvironment.getLocalGraphicsEnvironment(); |
||||
|
||||
// If the default GC supports translucency return true.
|
||||
// It is important to optimize the verification this way,
|
||||
// see CR 6661196 for more details.
|
||||
if (isTranslucencyCapable(env.getDefaultScreenDevice() |
||||
.getDefaultConfiguration())) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
// ... otherwise iterate through all the GCs.
|
||||
GraphicsDevice[] devices = env.getScreenDevices(); |
||||
|
||||
for (int i = 0; i < devices.length; i++) { |
||||
GraphicsConfiguration[] configs = devices[i].getConfigurations(); |
||||
for (int j = 0; j < configs.length; j++) { |
||||
if (isTranslucencyCapable(configs[j])) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
private static boolean isTranslucencyCapable(GraphicsConfiguration gc) { |
||||
if (gc == null) { |
||||
throw new NullPointerException("The gc argument should not be null"); |
||||
} |
||||
/* |
||||
return gc.isTranslucencyCapable(); |
||||
*/ |
||||
Toolkit curToolkit = Toolkit.getDefaultToolkit(); |
||||
if (!(curToolkit instanceof SunToolkit)) { |
||||
return false; |
||||
} |
||||
return ((SunToolkit)curToolkit).isTranslucencyCapable(gc); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,41 @@
|
||||
package com.fr.design.gui.icombocheckbox; |
||||
|
||||
import junit.framework.TestCase; |
||||
import org.junit.Assert; |
||||
import org.junit.Test; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.TreeMap; |
||||
|
||||
/** |
||||
* @author hades |
||||
* @version 10.0 |
||||
* Created by hades on 2020/4/3 |
||||
*/ |
||||
public class UICheckListPopupTest extends TestCase { |
||||
|
||||
@Test |
||||
public void testGetSelectedValues() { |
||||
Object[] values = new Object[]{"a", "b", "c"}; |
||||
Map<Object, Boolean> map = new TreeMap<>(); |
||||
map.put("a", true); |
||||
map.put("b", false); |
||||
map.put("c", true); |
||||
List<Object> list = new ArrayList<>(); |
||||
for (Map.Entry<Object, Boolean> entry : map.entrySet()) { |
||||
if (entry.getValue()) { |
||||
list.add(entry.getKey()); |
||||
} |
||||
} |
||||
Object[] selectValues = list.toArray(); |
||||
UICheckListPopup uiCheckListPopup1 = new UICheckListPopup(values); |
||||
uiCheckListPopup1.setSelectedValue(map); |
||||
Assert.assertArrayEquals(selectValues, uiCheckListPopup1.getSelectedValues()); |
||||
UICheckListPopup uiCheckListPopup2 = new UICheckListPopup(values, false); |
||||
uiCheckListPopup2.setSelectedValue(map); |
||||
Assert.assertArrayEquals(selectValues, uiCheckListPopup2.getSelectedValues()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@
|
||||
dependencies { |
||||
compile project(':designer-base') |
||||
} |
@ -0,0 +1,3 @@
|
||||
dependencies { |
||||
compile project(':designer-base') |
||||
} |
@ -0,0 +1,55 @@
|
||||
package com.fr.design.designer.beans.models; |
||||
|
||||
import com.fr.design.designer.creator.XCreator; |
||||
import com.fr.design.designer.creator.XWParameterLayout; |
||||
import com.fr.form.main.Form; |
||||
import com.fr.form.ui.Widget; |
||||
import com.fr.stable.StringUtils; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* created by Harrison on 2020/06/05 |
||||
**/ |
||||
abstract class ModelUtil { |
||||
|
||||
public static void renameWidgetName(Form form, XCreator xCreator) { |
||||
|
||||
Set<String> duplicated = new HashSet<>(); |
||||
recursiveRenameWidgetName(form, xCreator, duplicated); |
||||
} |
||||
|
||||
private static void recursiveRenameWidgetName(Form form, XCreator xCreator, Set<String> duplicated) { |
||||
|
||||
Set<XCreator> nameRelatedCreators = new HashSet<>(); |
||||
//直接遍历出来目标值,然后按需处理
|
||||
xCreator.traversalNameRelatedXCreators(nameRelatedCreators); |
||||
for (XCreator target : nameRelatedCreators) { |
||||
String uniqueName = uniqueName(form, target, duplicated); |
||||
target.resetCreatorName(uniqueName); |
||||
} |
||||
} |
||||
|
||||
private static String uniqueName(Form form, XCreator xCreator, Set<String> duplicated) { |
||||
|
||||
if (xCreator.acceptType(XWParameterLayout.class)) { |
||||
return xCreator.createDefaultName(); |
||||
} |
||||
Widget widget = xCreator.toData(); |
||||
String widgetName = widget.getWidgetName(); |
||||
if (StringUtils.isEmpty(widgetName)) { |
||||
widgetName = xCreator.createDefaultName(); |
||||
} |
||||
String raw = widgetName; |
||||
int i = 0; |
||||
while (form.isNameExist(widgetName) || duplicated.contains(widgetName)) { |
||||
widgetName = raw + i; |
||||
i++; |
||||
} |
||||
//将名字加入重复集合中
|
||||
duplicated.add(widgetName); |
||||
return widgetName; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,206 @@
|
||||
package com.fr.design.designer.beans.models; |
||||
|
||||
import com.fr.base.chart.BaseChartCollection; |
||||
import com.fr.config.dao.DaoContext; |
||||
import com.fr.config.dao.impl.LocalClassHelperDao; |
||||
import com.fr.config.dao.impl.LocalEntityDao; |
||||
import com.fr.config.dao.impl.LocalXmlEntityDao; |
||||
import com.fr.design.designer.creator.CRPropertyDescriptor; |
||||
import com.fr.design.designer.creator.XChartEditor; |
||||
import com.fr.design.designer.creator.XCreator; |
||||
import com.fr.design.designer.creator.XLayoutContainer; |
||||
import com.fr.design.designer.creator.XWTitleLayout; |
||||
import com.fr.design.designer.creator.cardlayout.XWCardLayout; |
||||
import com.fr.design.gui.chart.MiddleChartComponent; |
||||
import com.fr.design.mainframe.FormDesigner; |
||||
import com.fr.design.module.DesignModuleFactory; |
||||
import com.fr.form.main.Form; |
||||
import com.fr.form.ui.ChartEditor; |
||||
import com.fr.form.ui.Widget; |
||||
import com.fr.form.ui.container.WAbsoluteLayout; |
||||
import com.fr.form.ui.container.WCardLayout; |
||||
import com.fr.form.ui.container.WTitleLayout; |
||||
import com.fr.stable.core.PropertyChangeListener; |
||||
import org.easymock.EasyMock; |
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.powermock.api.easymock.PowerMock; |
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore; |
||||
import org.powermock.core.classloader.annotations.PrepareForTest; |
||||
import org.powermock.modules.junit4.PowerMockRunner; |
||||
|
||||
import javax.swing.JComponent; |
||||
import java.awt.Dimension; |
||||
import java.awt.Rectangle; |
||||
import java.beans.IntrospectionException; |
||||
|
||||
@PrepareForTest({DesignModuleFactory.class}) |
||||
@PowerMockIgnore({"com.sun.*", "javax.*", "com.fr.jvm.assist.*"}) |
||||
@RunWith(PowerMockRunner.class) |
||||
public class AddingModelTest { |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
DaoContext.setXmlEntityDao(new LocalXmlEntityDao()); |
||||
DaoContext.setClassHelperDao(new LocalClassHelperDao()); |
||||
DaoContext.setEntityDao(new LocalEntityDao()); |
||||
} |
||||
|
||||
@After |
||||
public void tearDown() { |
||||
DaoContext.setXmlEntityDao(null); |
||||
DaoContext.setClassHelperDao(null); |
||||
DaoContext.setEntityDao(null); |
||||
} |
||||
|
||||
@Test |
||||
public void testInstantiateCreator() throws Exception { |
||||
|
||||
Dimension dimension = new Dimension(20, 20); |
||||
|
||||
ChartEditor chartEditor1 = new ChartEditor(); |
||||
XCreator xCreator1 = new DemoCreator(chartEditor1, dimension, "test"); |
||||
|
||||
ChartEditor chartEditor2 = new ChartEditor(); |
||||
chartEditor2.setWidgetName("test02"); |
||||
XCreator xCreator2 = new DemoCreator(chartEditor2, dimension, "test02"); |
||||
xCreator1.add(xCreator2); |
||||
|
||||
ChartEditor chartEditor3 = new ChartEditor(); |
||||
chartEditor3.setWidgetName("test03"); |
||||
WAbsoluteLayout.BoundsWidget boundsWidget = new WAbsoluteLayout.BoundsWidget(chartEditor3, new Rectangle(dimension)); |
||||
WTitleLayout wTitleLayout03 = new WTitleLayout(); |
||||
wTitleLayout03.addWidget(boundsWidget); |
||||
//需要和内部的 widget 一样
|
||||
wTitleLayout03.setWidgetName("test03"); |
||||
XWTitleLayout xCreator3 = new XWTitleLayout(wTitleLayout03, dimension); |
||||
xCreator1.add(xCreator3); |
||||
|
||||
AddingModel addingModel = new AddingModel(xCreator1, 20, 20); |
||||
|
||||
Form form = EasyMock.mock(Form.class); |
||||
EasyMock.expect(form.isNameExist("test")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist("test03")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); |
||||
EasyMock.replay(form); |
||||
|
||||
FormDesigner mock = EasyMock.mock(FormDesigner.class); |
||||
EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); |
||||
EasyMock.replay(mock); |
||||
|
||||
addingModel.instantiateCreator(mock); |
||||
//没有默认参数, 但已经存在 test
|
||||
Assert.assertEquals("test0", xCreator1.toData().getWidgetName()); |
||||
//直接返回
|
||||
Assert.assertEquals("test02", xCreator2.toData().getWidgetName()); |
||||
//已经存在,后接0
|
||||
Assert.assertEquals("test030", xCreator3.toData().getWidgetName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testInstantiateCreator_cardLayout() throws Exception { |
||||
|
||||
Form form = EasyMock.mock(Form.class); |
||||
EasyMock.expect(form.isNameExist("cardlayout")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist("cardlayout0")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); |
||||
EasyMock.replay(form); |
||||
|
||||
FormDesigner mock = EasyMock.mock(FormDesigner.class); |
||||
EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); |
||||
EasyMock.replay(mock); |
||||
|
||||
WCardLayout wCardLayout = new WCardLayout(20, 20); |
||||
XWCardLayout xwCardLayout = new XWCardLayout(wCardLayout, new Dimension(40, 40)); |
||||
AddingModel addingModel = new AddingModel(mock, xwCardLayout); |
||||
Assert.assertEquals("cardlayout1", xwCardLayout.toData().getWidgetName()); |
||||
|
||||
//依赖于 cardlayout 创建 container
|
||||
XLayoutContainer parentLayOut = xwCardLayout.initCreatorWrapper(80); |
||||
AddingModel parentModel = new AddingModel(mock, parentLayOut); |
||||
Assert.assertEquals("tablayout1", parentLayOut.toData().getWidgetName()); |
||||
Assert.assertEquals("tabpane1", ((XCreator) (parentLayOut.getComponent(0))).getXCreator().toData().getWidgetName()); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testInstantiateCreator_containsNotXCreator() throws Exception { |
||||
|
||||
Form form = EasyMock.mock(Form.class); |
||||
EasyMock.expect(form.isNameExist("cardlayout")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist("cardlayout0")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); |
||||
EasyMock.replay(form); |
||||
|
||||
FormDesigner mock = EasyMock.mock(FormDesigner.class); |
||||
EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); |
||||
EasyMock.replay(mock); |
||||
|
||||
PowerMock.mockStaticPartial(DesignModuleFactory.class, "getChartComponent"); |
||||
EasyMock.expect(DesignModuleFactory.getChartComponent(EasyMock.anyObject(BaseChartCollection.class))).andReturn(new MiddleChartComponent() { |
||||
@Override |
||||
public void populate(BaseChartCollection cc) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public BaseChartCollection update() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void reset() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void addStopEditingListener(PropertyChangeListener list) { |
||||
|
||||
} |
||||
}).anyTimes(); |
||||
PowerMock.replayAll(); |
||||
|
||||
Dimension dimension = new Dimension(20, 20); |
||||
|
||||
ChartEditor chartEditor1 = new ChartEditor(); |
||||
XCreator xCreator1 = new XChartEditor(chartEditor1, dimension); |
||||
|
||||
|
||||
AddingModel chartModel = new AddingModel(mock, xCreator1); |
||||
Assert.assertEquals("chart", xCreator1.toData().getWidgetName()); |
||||
} |
||||
|
||||
private static class DemoCreator extends XCreator { |
||||
|
||||
private String widgetName; |
||||
|
||||
public DemoCreator(Widget ob, Dimension initSize, String widgetName) { |
||||
super(ob, initSize); |
||||
this.widgetName = widgetName; |
||||
} |
||||
|
||||
@Override |
||||
public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { |
||||
return new CRPropertyDescriptor[0]; |
||||
} |
||||
|
||||
@Override |
||||
protected JComponent initEditor() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void initXCreatorProperties() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public String createDefaultName() { |
||||
return this.widgetName; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,4 @@
|
||||
dependencies { |
||||
compile project(':designer-form') |
||||
compile project(':designer-chart') |
||||
} |
@ -0,0 +1,29 @@
|
||||
def getRootGradle() { |
||||
def currentGradle = gradle |
||||
while (currentGradle.parent) { |
||||
currentGradle = currentGradle.parent |
||||
} |
||||
return currentGradle |
||||
} |
||||
|
||||
def findHookIncludedBuild() { |
||||
def rootGradle = getRootGradle() |
||||
def hookProject = rootGradle.getIncludedBuilds() |
||||
.find({ build -> build.name == 'hook' }) |
||||
return hookProject |
||||
} |
||||
|
||||
def findGlobalConfig() { |
||||
def hookProject = findHookIncludedBuild() |
||||
if (hookProject) { |
||||
def path = hookProject.projectDir.parent + '/globalConfig.gradle' |
||||
if (file(path).exists()) { |
||||
return path |
||||
} |
||||
} |
||||
} |
||||
|
||||
def globalConfigPath = findGlobalConfig() |
||||
if (globalConfigPath) { |
||||
apply from: globalConfigPath |
||||
} |
Binary file not shown.
@ -0,0 +1,6 @@
|
||||
#Wed Apr 22 15:17:12 CST 2020 |
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-all.zip |
||||
distributionBase=GRADLE_USER_HOME |
||||
distributionPath=wrapper/dists |
||||
zipStorePath=wrapper/dists |
||||
zipStoreBase=GRADLE_USER_HOME |
@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh |
||||
|
||||
############################################################################## |
||||
## |
||||
## Gradle start up script for UN*X |
||||
## |
||||
############################################################################## |
||||
|
||||
# Attempt to set APP_HOME |
||||
# Resolve links: $0 may be a link |
||||
PRG="$0" |
||||
# Need this for relative symlinks. |
||||
while [ -h "$PRG" ] ; do |
||||
ls=`ls -ld "$PRG"` |
||||
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||
if expr "$link" : '/.*' > /dev/null; then |
||||
PRG="$link" |
||||
else |
||||
PRG=`dirname "$PRG"`"/$link" |
||||
fi |
||||
done |
||||
SAVED="`pwd`" |
||||
cd "`dirname \"$PRG\"`/" >/dev/null |
||||
APP_HOME="`pwd -P`" |
||||
cd "$SAVED" >/dev/null |
||||
|
||||
APP_NAME="Gradle" |
||||
APP_BASE_NAME=`basename "$0"` |
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
DEFAULT_JVM_OPTS='"-Xmx64m"' |
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value. |
||||
MAX_FD="maximum" |
||||
|
||||
warn () { |
||||
echo "$*" |
||||
} |
||||
|
||||
die () { |
||||
echo |
||||
echo "$*" |
||||
echo |
||||
exit 1 |
||||
} |
||||
|
||||
# OS specific support (must be 'true' or 'false'). |
||||
cygwin=false |
||||
msys=false |
||||
darwin=false |
||||
nonstop=false |
||||
case "`uname`" in |
||||
CYGWIN* ) |
||||
cygwin=true |
||||
;; |
||||
Darwin* ) |
||||
darwin=true |
||||
;; |
||||
MINGW* ) |
||||
msys=true |
||||
;; |
||||
NONSTOP* ) |
||||
nonstop=true |
||||
;; |
||||
esac |
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
||||
|
||||
# Determine the Java command to use to start the JVM. |
||||
if [ -n "$JAVA_HOME" ] ; then |
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||
# IBM's JDK on AIX uses strange locations for the executables |
||||
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||
else |
||||
JAVACMD="$JAVA_HOME/bin/java" |
||||
fi |
||||
if [ ! -x "$JAVACMD" ] ; then |
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the |
||||
location of your Java installation." |
||||
fi |
||||
else |
||||
JAVACMD="java" |
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the |
||||
location of your Java installation." |
||||
fi |
||||
|
||||
# Increase the maximum file descriptors if we can. |
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then |
||||
MAX_FD_LIMIT=`ulimit -H -n` |
||||
if [ $? -eq 0 ] ; then |
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
||||
MAX_FD="$MAX_FD_LIMIT" |
||||
fi |
||||
ulimit -n $MAX_FD |
||||
if [ $? -ne 0 ] ; then |
||||
warn "Could not set maximum file descriptor limit: $MAX_FD" |
||||
fi |
||||
else |
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
||||
fi |
||||
fi |
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock |
||||
if $darwin; then |
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
||||
fi |
||||
|
||||
# For Cygwin, switch paths to Windows format before running java |
||||
if $cygwin ; then |
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
||||
JAVACMD=`cygpath --unix "$JAVACMD"` |
||||
|
||||
# We build the pattern for arguments to be converted via cygpath |
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
||||
SEP="" |
||||
for dir in $ROOTDIRSRAW ; do |
||||
ROOTDIRS="$ROOTDIRS$SEP$dir" |
||||
SEP="|" |
||||
done |
||||
OURCYGPATTERN="(^($ROOTDIRS))" |
||||
# Add a user-defined pattern to the cygpath arguments |
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
||||
fi |
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh |
||||
i=0 |
||||
for arg in "$@" ; do |
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
||||
else |
||||
eval `echo args$i`="\"$arg\"" |
||||
fi |
||||
i=$((i+1)) |
||||
done |
||||
case $i in |
||||
(0) set -- ;; |
||||
(1) set -- "$args0" ;; |
||||
(2) set -- "$args0" "$args1" ;; |
||||
(3) set -- "$args0" "$args1" "$args2" ;; |
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
||||
esac |
||||
fi |
||||
|
||||
# Escape application args |
||||
save () { |
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done |
||||
echo " " |
||||
} |
||||
APP_ARGS=$(save "$@") |
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules |
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" |
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong |
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then |
||||
cd "$(dirname "$0")" |
||||
fi |
||||
|
||||
exec "$JAVACMD" "$@" |
@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off |
||||
@rem ########################################################################## |
||||
@rem |
||||
@rem Gradle startup script for Windows |
||||
@rem |
||||
@rem ########################################################################## |
||||
|
||||
@rem Set local scope for the variables with windows NT shell |
||||
if "%OS%"=="Windows_NT" setlocal |
||||
|
||||
set DIRNAME=%~dp0 |
||||
if "%DIRNAME%" == "" set DIRNAME=. |
||||
set APP_BASE_NAME=%~n0 |
||||
set APP_HOME=%DIRNAME% |
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
set DEFAULT_JVM_OPTS="-Xmx64m" |
||||
|
||||
@rem Find java.exe |
||||
if defined JAVA_HOME goto findJavaFromJavaHome |
||||
|
||||
set JAVA_EXE=java.exe |
||||
%JAVA_EXE% -version >NUL 2>&1 |
||||
if "%ERRORLEVEL%" == "0" goto init |
||||
|
||||
echo. |
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
echo. |
||||
echo Please set the JAVA_HOME variable in your environment to match the |
||||
echo location of your Java installation. |
||||
|
||||
goto fail |
||||
|
||||
:findJavaFromJavaHome |
||||
set JAVA_HOME=%JAVA_HOME:"=% |
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
||||
|
||||
if exist "%JAVA_EXE%" goto init |
||||
|
||||
echo. |
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
||||
echo. |
||||
echo Please set the JAVA_HOME variable in your environment to match the |
||||
echo location of your Java installation. |
||||
|
||||
goto fail |
||||
|
||||
:init |
||||
@rem Get command-line arguments, handling Windows variants |
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args |
||||
|
||||
:win9xME_args |
||||
@rem Slurp the command line arguments. |
||||
set CMD_LINE_ARGS= |
||||
set _SKIP=2 |
||||
|
||||
:win9xME_args_slurp |
||||
if "x%~1" == "x" goto execute |
||||
|
||||
set CMD_LINE_ARGS=%* |
||||
|
||||
:execute |
||||
@rem Setup the command line |
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
||||
|
||||
@rem Execute Gradle |
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% |
||||
|
||||
:end |
||||
@rem End local scope for the variables with windows NT shell |
||||
if "%ERRORLEVEL%"=="0" goto mainEnd |
||||
|
||||
:fail |
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
||||
rem the _cmd.exe /c_ return code! |
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |
||||
exit /b 1 |
||||
|
||||
:mainEnd |
||||
if "%OS%"=="Windows_NT" endlocal |
||||
|
||||
:omega |
Loading…
Reference in new issue