diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java index a5f4a72ac..58cd014e0 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesktopCardPane.java @@ -35,6 +35,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener } DesignerFrameFileDealerPane.getInstance().setCurrentEditingTemplate(jt); if (component != null) { + component.onLostFocus(); remove(component); } add(component = jt, BorderLayout.CENTER); @@ -42,6 +43,7 @@ public class DesktopCardPane extends BasicPane implements TargetModifiedListener repaint(); revalidate(); component.requestGridFocus(); + component.onGetFocus(); } protected JTemplate getSelectedJTemplate() { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index 9708dcb65..9b6a76172 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -36,6 +36,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.template.info.TemplateInfoCollector; import com.fr.design.mainframe.template.info.TemplateProcessInfo; +import com.fr.design.mainframe.template.info.TimeConsumeTimer; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.mainframe.toolbar.VcsScene; import com.fr.design.menu.MenuDef; @@ -78,7 +79,6 @@ import java.util.regex.Pattern; public abstract class JTemplate> extends TargetComponent implements ToolBarMenuDockPlus, DesignerProxy { // TODO ALEX_SEP editingFILE这个属性一定要吗?如果非要不可,有没有可能保证不为null private static final int PREFIX_NUM = 3000; - private static final int ONE_THOUSAND = 1000; private FILE editingFILE = null; // alex:初始状态为saved,这样不管是新建模板,还是打开模板,如果未做任何操作直接关闭,不提示保存 private boolean saved = true; @@ -92,7 +92,7 @@ public abstract class JTemplate> private static short currentIndex = 0;// 此变量用于多次新建模板时,让名字不重复 private DesignModelAdapter designModel; private PreviewProvider previewType; - private long openTime = 0L; // 打开模板的时间点(包括新建模板) + private TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); public int resolution = ScreenResolution.getScreenResolution(); public JTemplate() { @@ -100,7 +100,6 @@ public abstract class JTemplate> public JTemplate(T t, String defaultFileName) { this(t, new MemFILE(newTemplateNameByIndex(defaultFileName)), true); - openTime = System.currentTimeMillis(); } public JTemplate(T t, FILE file) { @@ -123,10 +122,24 @@ public abstract class JTemplate> this.add(createCenterPane(), BorderLayout.CENTER); this.undoState = createUndoState(); designModel = createDesignModel(); - // 如果不是新建模板,并且在收集列表中 - if (!isNewFile && TemplateInfoCollector.getInstance().contains(t.getTemplateID())) { - openTime = System.currentTimeMillis(); + + consumeTimer.setEnabled(shouldInitForCollectInfo(isNewFile)); + } + + void onGetFocus() { + consumeTimer.start(); + } + + void onLostFocus() { + consumeTimer.stop(); + } + + private boolean shouldInitForCollectInfo(boolean isNewFile) { + if (isNewFile) { + return true; } + // 不是新建模板,但是已经在收集列表中 + return TemplateInfoCollector.getInstance().contains(template.getTemplateID()); } // 刷新右侧属性面板 @@ -139,9 +152,8 @@ public abstract class JTemplate> // 为收集模版信息作准备 private void initForCollect() { generateTemplateId(); - if (openTime == 0) { - openTime = System.currentTimeMillis(); - } + consumeTimer.setEnabled(true); + consumeTimer.start(); } private void collectInfo() { // 执行收集操作 @@ -149,16 +161,15 @@ public abstract class JTemplate> } private void collectInfo(String originID) { // 执行收集操作 - if (openTime == 0) { // 旧模板,不收集数据 + if (!consumeTimer.isEnabled()) { return; } - long saveTime = System.currentTimeMillis(); // 保存模板的时间点 try { - long timeConsume = ((saveTime - openTime) / ONE_THOUSAND); // 制作模板耗时(单位:s) - TemplateInfoCollector.getInstance().collectInfo(template.getTemplateID(), originID, getProcessInfo(), (int)timeConsume); + int timeConsume = consumeTimer.popTime(); + TemplateInfoCollector.getInstance().collectInfo(template.getTemplateID(), originID, getProcessInfo(), timeConsume); } catch (Throwable th) { // 不管收集过程中出现任何异常,都不应该影响模版保存 } - openTime = saveTime; // 更新 openTime,准备下一次计算 + consumeTimer.start(); // 准备下一次计算 } public abstract TemplateProcessInfo getProcessInfo(); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java new file mode 100644 index 000000000..ace07be0d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/template/info/TimeConsumeTimer.java @@ -0,0 +1,72 @@ +package com.fr.design.mainframe.template.info; + +/** + * Created by plough on 2019/4/19. + */ +public class TimeConsumeTimer { + private static final int ONE_THOUSAND = 1000; + private enum State { + RUNNING, STOPPED + } + private int timeConsume; // 单位 s + private long startMS; // 单位 ms + private long stopMS; + private State state; + private boolean enabled; + + public TimeConsumeTimer() { + reset(); + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void start() { + if (!isEnabled() || isRunning()) { + return; + } + startMS = System.currentTimeMillis(); + state = State.RUNNING; + } + + public void stop() { + if (!isEnabled() || !isRunning()) { + return; + } + stopMS = System.currentTimeMillis(); + + timeConsume += ((stopMS - startMS) / ONE_THOUSAND); + startMS = 0; + stopMS = 0; + state = State.STOPPED; + + + System.out.println("timeConsume now: " + timeConsume); + } + + public int popTime() { + if (!isEnabled()) { + return 0; + } + stop(); + int result = timeConsume; + reset(); + return result; + } + + private boolean isRunning() { + return state == State.RUNNING; + } + + private void reset() { + timeConsume = 0; + startMS = 0; + stopMS = 0; + state = State.STOPPED; + } +} diff --git a/designer-base/src/test/java/com/fr/design/mainframe/template/info/TimeConsumeTimerTest.java b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TimeConsumeTimerTest.java new file mode 100644 index 000000000..5dcf60e7f --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/mainframe/template/info/TimeConsumeTimerTest.java @@ -0,0 +1,62 @@ +package com.fr.design.mainframe.template.info; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Created by plough on 2019/4/19. + */ +public class TimeConsumeTimerTest { + + @Test + public void testNotEnabled() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.start(); + Thread.sleep(1100); + consumeTimer.stop(); + assertEquals(0, consumeTimer.popTime()); + } + + @Test + public void testEnabled() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.setEnabled(true); + consumeTimer.start(); + Thread.sleep(1100); + consumeTimer.stop(); + assertEquals(1, consumeTimer.popTime()); + assertEquals(0, consumeTimer.popTime()); + } + + @Test + public void testMultiTimes() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.setEnabled(true); + + consumeTimer.start(); + Thread.sleep(1010); + consumeTimer.stop(); + + Thread.sleep(2000); + + consumeTimer.start(); + Thread.sleep(1010); + assertEquals(2, consumeTimer.popTime()); + } + + @Test + public void testStartMultiTime() throws InterruptedException { + TimeConsumeTimer consumeTimer = new TimeConsumeTimer(); + consumeTimer.setEnabled(true); + + consumeTimer.start(); + Thread.sleep(1010); + consumeTimer.start(); + Thread.sleep(1010); + consumeTimer.start(); + Thread.sleep(1010); + + assertEquals(3, consumeTimer.popTime()); + } +}