• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package ohos.devtools.views.layout.chartview.cpu;
17 
18 import com.intellij.openapi.util.IconLoader;
19 import com.intellij.ui.JBColor;
20 import com.intellij.ui.components.JBLabel;
21 import com.intellij.ui.components.JBPanel;
22 import com.intellij.ui.components.JBTabbedPane;
23 import com.intellij.ui.components.JBTextField;
24 import net.miginfocom.swing.MigLayout;
25 import ohos.devtools.datasources.utils.device.entity.DeviceIPPortInfo;
26 import ohos.devtools.datasources.utils.device.entity.DeviceType;
27 import ohos.devtools.datasources.utils.monitorconfig.entity.AppTraceConfig;
28 import ohos.devtools.datasources.utils.monitorconfig.entity.ConfigInfo;
29 import ohos.devtools.datasources.utils.monitorconfig.entity.PerfConfig;
30 import ohos.devtools.views.common.ColorConstants;
31 import ohos.devtools.views.common.LayoutConstants;
32 import ohos.devtools.views.common.customcomp.CustomComboBox;
33 import ohos.devtools.views.common.customcomp.CustomJBComboBoxUI;
34 import ohos.devtools.views.layout.chartview.utils.DigitCheckDocument;
35 import ohos.devtools.views.layout.chartview.utils.MultiComboBox;
36 import ohos.devtools.views.layout.dialog.CustomDialog;
37 import org.apache.commons.lang.StringUtils;
38 import org.apache.logging.log4j.LogManager;
39 import org.apache.logging.log4j.Logger;
40 
41 import javax.swing.BorderFactory;
42 import javax.swing.Icon;
43 import javax.swing.JButton;
44 import javax.swing.JSlider;
45 import javax.swing.JToggleButton;
46 import javax.swing.SwingWorker;
47 import javax.swing.event.DocumentEvent;
48 import javax.swing.event.DocumentListener;
49 import javax.swing.text.BadLocationException;
50 import java.awt.Dimension;
51 import java.awt.Font;
52 import java.awt.event.MouseAdapter;
53 import java.awt.event.MouseEvent;
54 import java.awt.event.WindowAdapter;
55 import java.awt.event.WindowEvent;
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.List;
59 import java.util.Locale;
60 
61 /**
62  * CpuConfigDialog
63  *
64  * @since 2021/11/15 10:20
65  */
66 public class CpuConfigDialog<T extends JBPanel<T>> {
67     private static final Logger LOGGER = LogManager.getLogger(CpuConfigDialog.class);
68 
69     /**
70      * config Panel min width
71      */
72     private static final int CONFIG_PANEL_MIN_WIDTH = 440;
73 
74     /**
75      * config Panel min height
76      */
77     private static final int CONFIG_PANEL_MIN_HEIGHT = 780;
78 
79     /**
80      * config button width
81      */
82     private static final int CONFIG_BUTTON_WIDTH = 80;
83 
84     /**
85      * config button height
86      */
87     private static final int CONFIG_BUTTON_HEIGHT = 30;
88 
89     /**
90      * mMapPages Max value
91      */
92     private static final int M_MAP_PAGES_MAX_VALUE = 10;
93 
94     /**
95      * mMapPages Min value
96      */
97     private static final int M_MAP_PAGES_MIN_VALUE = 1;
98 
99     /**
100      * CPU percent max
101      */
102     private static final int CPU_PERCENT_MAX = 100;
103 
104     /**
105      * view Border distance
106      */
107     private static final int VIEW_BORDER_DISTANCE = 8;
108 
109     /**
110      * detailed bounds size
111      */
112     private static final int BOUNDS_SIZE = 20;
113 
114     /**
115      * detailed border size
116      */
117     private static final int BORDER_SIZE = 2;
118 
119     /**
120      * normal on
121      */
122     private final Icon NORMAL_ON = IconLoader.getIcon("/images/normal_on.png", CpuConfigDialog.class);
123 
124     /**
125      * normal off
126      */
127     private final Icon NORMAL_OFF = IconLoader.getIcon("/images/normal_off.png", CpuConfigDialog.class);
128 
129     /**
130      * label Font
131      */
132     private final Font titleFont = new Font("PingFangSC-Regular;", Font.PLAIN, 14);
133 
134     /**
135      * area Font
136      */
137     private final Font messageFont = new Font("PingFangSC-Regular", Font.PLAIN, 12);
138 
139     /**
140      * label font
141      */
142     private final Font font = new Font(Font.DIALOG, Font.PLAIN, LayoutConstants.FONT_SIZE);
143 
144     /**
145      * Cancel button
146      */
147     private final JButton buttonCancel = new JButton("Cancel");
148 
149     /**
150      * Save button
151      */
152     private final JButton buttonSave = new JButton("Save");
153 
154     /**
155      * Save button
156      */
157     private final JButton restoreConfig = new JButton("Restore Config");
158 
159     /**
160      * deviceIPPortInfo
161      */
162     private DeviceIPPortInfo deviceIPPortInfo;
163 
164     /**
165      * perf Config Panel
166      */
167     private JBPanel<T> perfConfigPanel;
168 
169     /**
170      * appTrace Config Panel
171      */
172     private JBPanel<T> appTraceConfigPanel;
173 
174     /**
175      * tabbedPane
176      */
177     private JBTabbedPane tabbedPane;
178 
179     /**
180      * cpu List
181      */
182     private final List<String> cpuList = new ArrayList<>();
183 
184     /**
185      * perf Config
186      */
187     private PerfConfig<String> perfConfig;
188 
189     /**
190      * AppTrace Config
191      */
192     private AppTraceConfig appTraceConfig;
193 
194     /**
195      * perfConfig
196      */
197     private PerfConfig<String> restorePerfConfig;
198 
199     /**
200      * cpu Num
201      */
202     private int cpuNumber = 1;
203 
204     /**
205      * isLeakOhos
206      */
207     private boolean isLeakOhos;
208 
209     /**
210      * eventList
211      */
212     private List<String> eventList = new ArrayList<>();
213 
214     /**
215      * cpu Multi List
216      */
217     private List<String> cpuMultiList = new ArrayList<>();
218 
219     /**
220      * event Multi List
221      */
222     private List<String> eventMultiList = new ArrayList<>();
223 
224     /**
225      * configInfo
226      */
227     private ConfigInfo configInfo;
228 
229     /**
230      * configPanel
231      */
232     private JBPanel<T> configPanel;
233 
234     /**
235      * customDialog
236      */
237     private CustomDialog customDialog;
238 
239     /**
240      * configButton
241      */
242     private JBLabel configButton;
243 
244     /**
245      * multiCpuComboBox
246      */
247     private MultiComboBox<String> multiCpuComboBox;
248 
249     /**
250      * multiEventComboBox
251      */
252     private MultiComboBox<String> multiEventComboBox;
253 
254     /**
255      * CpuConfigDialog
256      *
257      * @param configButton configButton
258      * @param deviceIPPortInfo deviceIPPortInfo
259      */
CpuConfigDialog(JBLabel configButton, DeviceIPPortInfo deviceIPPortInfo)260     public CpuConfigDialog(JBLabel configButton, DeviceIPPortInfo deviceIPPortInfo) {
261         this.configButton = configButton;
262         this.deviceIPPortInfo = deviceIPPortInfo;
263         configButton.setName("open");
264         configInfo = ConfigInfo.getInstance();
265         initConfigPanel();
266     }
267 
initConfigPanel()268     private void initConfigPanel() {
269         new SwingWorker<>() {
270             @Override
271             protected Object doInBackground() {
272                 initDefaultData(deviceIPPortInfo);
273                 return new Object();
274             }
275 
276             @Override
277             protected void done() {
278                 // JBTabbedPane
279                 tabbedPane = new JBTabbedPane();
280                 // init ConfigTab
281                 perfConfigPanel = new JBPanel<>(new MigLayout("insets 0", "[grow]", "[grow]"));
282                 appTraceConfigPanel = new JBPanel<>(new MigLayout("insets 0", "[grow]", "[grow]"));
283                 addTabPanel(perfConfigPanel, " PerfConfig");
284                 addPerfConfigTab();
285                 addTabPanel(appTraceConfigPanel, " APPTraceConfig");
286                 addAppTraceConfigTab();
287                 configPanel = new JBPanel<>(new MigLayout("insets 0 10 5 0", "[grow]", "[90%!,fill][10%!,fill]"));
288                 configPanel.add(tabbedPane, "span, growx, growy");
289                 configPanel.setMinimumSize(new Dimension(CONFIG_PANEL_MIN_WIDTH, CONFIG_PANEL_MIN_HEIGHT));
290                 initConfigStyle(configPanel);
291                 customDialog = new CustomDialog("Config", configPanel);
292                 addConfigListener();
293                 customDialog.setResizable(false);
294                 customDialog.show();
295             }
296         }.execute();
297     }
298 
addTabPanel(JBPanel<T> configPanel, String name)299     private void addTabPanel(JBPanel<T> configPanel, String name) {
300         configPanel.setOpaque(true);
301         configPanel.setBorder(BorderFactory.createLineBorder(JBColor.green));
302         // Config Tab
303         configPanel.setBorder(BorderFactory.createEmptyBorder(VIEW_BORDER_DISTANCE, 0, VIEW_BORDER_DISTANCE, 0));
304         // Custom Config Tab
305         tabbedPane.addTab("", configPanel);
306         // PerfConfig Tab
307         JBLabel configLabel = new JBLabel(name);
308         configLabel.setBorder(BorderFactory.createEmptyBorder(BORDER_SIZE, BOUNDS_SIZE, BORDER_SIZE, 0));
309         configLabel.setOpaque(false);
310         configLabel.setPreferredSize(new Dimension(LayoutConstants.JPA_LABEL_WIDTH, LayoutConstants.DEVICES_HEIGHT));
311         configLabel.setFont(font);
312         configLabel
313             .setBounds(LayoutConstants.RECORD_BORDER_SPACE, BORDER_SIZE, LayoutConstants.RECORD_TABBED_BOUNDS_WIDTH,
314                 BOUNDS_SIZE);
315         tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(configPanel), configLabel);
316     }
317 
318     /**
319      * init Default Data
320      *
321      * @param deviceIPPortInfo deviceIPPortInfo
322      */
initDefaultData(DeviceIPPortInfo deviceIPPortInfo)323     private void initDefaultData(DeviceIPPortInfo deviceIPPortInfo) {
324         isLeakOhos = deviceIPPortInfo.getDeviceType() == DeviceType.LEAN_HOS_DEVICE;
325         String deviceID = deviceIPPortInfo.getDeviceID();
326         perfConfig = configInfo.getPerfConfig(isLeakOhos);
327         appTraceConfig = configInfo.getAppTraceConfig();
328         // set default cpu Number
329         eventList = perfConfig.getSoftHardWareEvents(isLeakOhos, deviceID);
330         cpuNumber = perfConfig.getCpuCount(isLeakOhos, deviceID);
331         restorePerfConfig = perfConfig;
332     }
333 
334     /**
335      * init Config panel Style
336      *
337      * @param configPanel configPanel
338      */
initConfigStyle(JBPanel<T> configPanel)339     private void initConfigStyle(JBPanel<T> configPanel) {
340         buttonCancel.setFont(titleFont);
341         buttonSave.setFont(titleFont);
342         restoreConfig.setFont(titleFont);
343         buttonCancel.setPreferredSize(new Dimension(CONFIG_BUTTON_WIDTH, CONFIG_BUTTON_HEIGHT));
344         buttonSave.setPreferredSize(new Dimension(CONFIG_BUTTON_WIDTH, CONFIG_BUTTON_HEIGHT));
345         restoreConfig.setPreferredSize(new Dimension(CONFIG_BUTTON_WIDTH, CONFIG_BUTTON_HEIGHT));
346         JBPanel<T> buttonPanel = new JBPanel<>(new MigLayout("insets 0", "[]210[][]"));
347         buttonPanel.add(restoreConfig);
348         buttonPanel.add(buttonCancel);
349         buttonPanel.add(buttonSave);
350         configPanel.add(buttonPanel);
351     }
352 
353     /**
354      * add Config Panel Listener
355      */
addConfigListener()356     private void addConfigListener() {
357         buttonSave.addMouseListener(new MouseAdapter() {
358             @Override
359             public void mouseClicked(MouseEvent mouseEvent) {
360                 eventMultiList = getInputContent(multiEventComboBox.getTextField().getText());
361                 perfConfig.setEventList(eventMultiList);
362                 cpuMultiList = getInputContent(multiCpuComboBox.getTextField().getText());
363                 perfConfig.setCpuList(cpuMultiList);
364                 configInfo.setPerfConfig(perfConfig);
365                 configInfo.setAppTraceConfig(appTraceConfig);
366                 configButton.setName("close");
367                 customDialog.close(1);
368             }
369         });
370         buttonCancel.addMouseListener(new MouseAdapter() {
371             @Override
372             public void mouseClicked(MouseEvent event) {
373                 super.mouseClicked(event);
374                 perfConfig = restorePerfConfig;
375                 configButton.setName("close");
376                 customDialog.close(1);
377             }
378         });
379         restoreConfig.addMouseListener(new MouseAdapter() {
380             @Override
381             public void mouseClicked(MouseEvent event) {
382                 super.mouseClicked(event);
383                 configInfo.restorePerfDefault(isLeakOhos);
384                 perfConfigPanel.removeAll();
385                 appTraceConfigPanel.removeAll();
386                 initDefaultData(deviceIPPortInfo);
387                 appTraceConfig.setMemoryBufferSize(10);
388                 addPerfConfigTab();
389                 addAppTraceConfigTab();
390                 perfConfigPanel.repaint();
391                 perfConfigPanel.validate();
392             }
393         });
394 
395         customDialog.getWindow().addWindowListener(new WindowAdapter() {
396             @Override
397             public void windowClosed(WindowEvent event) {
398                 super.windowClosed(event);
399                 configButton.setName("close");
400             }
401         });
402     }
403 
addAppTraceConfigTab()404     private void addAppTraceConfigTab() {
405         JBPanel<T> appTracePanel =
406             new JBPanel<>(new MigLayout("insets 0", "[80%!,fill]10[10%!,fill]", "10[5%!,fill][5%!,fill][80%!,fill]"));
407         // title label
408         JBLabel titleLabel = new JBLabel("In-memory buffer size");
409         titleLabel.setOpaque(true);
410         titleLabel.setFont(titleFont);
411         appTracePanel.add(titleLabel, "span,wrap");
412         // mMapPages Slider
413         JSlider unitSlider = new JSlider(0, 110);
414         // buffer size
415         int bufferSize = appTraceConfig.getMemoryBufferSize();
416         unitSlider.setValue(bufferSize);
417         unitSlider.setMajorTickSpacing(10);
418         unitSlider.setMinorTickSpacing(1);
419         // ValuePanel
420         JBLabel valuePanel = new JBLabel("" + bufferSize + " MB", JBLabel.CENTER);
421         valuePanel.setFont(titleFont);
422         valuePanel.setVerticalTextPosition(JBLabel.CENTER);
423         valuePanel.setHorizontalTextPosition(JBLabel.CENTER);
424         valuePanel.setBackground(JBColor.background().brighter());
425         valuePanel.setOpaque(true);
426         appTracePanel.add(unitSlider, "growx,growy");
427         appTracePanel.add(valuePanel, "growx,growy,wrap");
428         appTracePanel.add(new JBLabel(), "span,growx,growy");
429         unitSlider.addChangeListener(event -> {
430             valuePanel.setText("" + unitSlider.getValue() + " MB");
431             appTraceConfig.setMemoryBufferSize(unitSlider.getValue());
432         });
433         appTraceConfigPanel.add(appTracePanel, "span,growx,growy");
434     }
435 
436     /**
437      * add Perf Config Tab
438      */
addPerfConfigTab()439     private void addPerfConfigTab() {
440         addParameterComponent("CPU", "Record assign cpu num such as 0,1,2", ComponentType.MULTI_DROP_DOWN_BOX);
441         addParameterComponent("Event List", "Event type Default is cpu cycles", ComponentType.MULTI_DROP_DOWN_BOX);
442         addParameterComponent("CPU Percent", "Set the max percent of cpu time used for recording",
443             ComponentType.SLIDER_BAR);
444         addParameterComponent("Frequency", "Set event sampling frequency", ComponentType.INPUT_BOX);
445         addParameterComponent("Period", "Set event sampling period for trace point events", ComponentType.INPUT_BOX);
446         addParameterComponent("Is Off CPU", "Trace when threads are scheduled off cpu", ComponentType.TOGGLE_BUTTON);
447         addParameterComponent("No Inherit", "Don't trace child processes", ComponentType.TOGGLE_BUTTON);
448         addParameterComponent("Call Stack", "Setup and enable call stack recording", ComponentType.DROP_DOWN_BOX);
449         addParameterComponent("Branch", "Taken branch stack sampling", ComponentType.DROP_DOWN_BOX);
450         addParameterComponent("Mmap Pages", "Used to receiving record data from kernel", ComponentType.SLIDER_BAR);
451         addParameterComponent("Clock Type",
452             "Set the clock id to use for the various time fields in the perf_event_type records",
453             ComponentType.DROP_DOWN_BOX);
454     }
455 
456     /**
457      * addParameterComponent
458      *
459      * @param name name
460      * @param Message Message
461      * @param componentType componentType
462      */
addParameterComponent(String name, String Message, ComponentType componentType)463     private void addParameterComponent(String name, String Message, ComponentType componentType) {
464         // title label
465         JBLabel titleLabel = new JBLabel(name);
466         titleLabel.setOpaque(true);
467         titleLabel.setFont(titleFont);
468         // message Label
469         JBLabel messageLabel = new JBLabel(Message);
470         messageLabel.setFont(messageFont);
471         messageLabel.setForeground(JBColor.foreground().darker());
472         messageLabel.setOpaque(false);
473         switch (componentType) {
474             case INPUT_BOX:
475                 perfConfigPanel.add(titleLabel, "split 2");
476                 perfConfigPanel.add(messageLabel, "span,flowx,wrap");
477                 buildInputBox(name);
478                 break;
479             case SLIDER_BAR:
480                 perfConfigPanel.add(titleLabel, "split 2");
481                 perfConfigPanel.add(messageLabel, "span,flowx,wrap");
482                 buildSliderBar(name);
483                 break;
484             case DROP_DOWN_BOX:
485                 perfConfigPanel.add(titleLabel, "split 2");
486                 perfConfigPanel.add(messageLabel, "span, flowx, wrap");
487                 buildDropDownBox(name);
488                 break;
489             case TOGGLE_BUTTON:
490                 perfConfigPanel.add(titleLabel, "split 2");
491                 perfConfigPanel.add(messageLabel, "flowx");
492                 buildToggleButton(name);
493                 break;
494             case MULTI_DROP_DOWN_BOX:
495                 perfConfigPanel.add(titleLabel, "split 2");
496                 perfConfigPanel.add(messageLabel, "span, flowx, wrap");
497                 buildMultiComboBox(name);
498                 break;
499             default:
500                 break;
501         }
502     }
503 
504     /**
505      * build Multi DropDown Box
506      *
507      * @param name name
508      */
buildMultiComboBox(String name)509     private void buildMultiComboBox(String name) {
510         if (name.equals("CPU")) {
511             ArrayList<String> cpuArray = new ArrayList<>();
512             cpuArray.add("Select All");
513             for (int index = 0; index < cpuNumber; index++) {
514                 cpuArray.add(index + "");
515             }
516             multiCpuComboBox = new MultiComboBox<>(cpuArray);
517             multiCpuComboBox.setSelectValues(perfConfig.getCpuList());
518             multiCpuComboBox.setName(name);
519             multiCpuComboBox.setFont(titleFont);
520             perfConfigPanel.add(multiCpuComboBox, "growx,growy,span,wrap");
521         }
522         if (name.equals("Event List")) {
523             ArrayList<String> eventArray = new ArrayList<>();
524             eventArray.add("Select All");
525             eventArray.addAll(this.eventList);
526             multiEventComboBox = new MultiComboBox<>(eventArray);
527             multiEventComboBox.setSelectValues(perfConfig.getEventList());
528             multiEventComboBox.setName(name);
529             multiEventComboBox.setFont(titleFont);
530             perfConfigPanel.add(multiEventComboBox, "growx,growy,span,wrap");
531         }
532     }
533 
getInputContent(String content)534     private List<String> getInputContent(String content) {
535         String contentText = content.replace("[", "").replace("]", "")
536             .replace(" ", "").strip();
537         if (StringUtils.isBlank(content)) {
538             return new ArrayList<>();
539         }
540         return Arrays.asList(contentText.split(","));
541     }
542 
543     /**
544      * build DropDown Box
545      *
546      * @param name name
547      */
buildDropDownBox(String name)548     private void buildDropDownBox(String name) {
549         List<String> dropList = new ArrayList<>();
550         boolean isAddAll = false;
551         int selectIndex = 0;
552         switch (name) {
553             case "Call Stack": {
554                 for (Enum anEnum : PerfConfig.CallStack.values()) {
555                     dropList.add(anEnum.name().toLowerCase(Locale.ENGLISH));
556                 }
557                 selectIndex = perfConfig.getCallStack();
558                 break;
559             }
560             case "Branch": {
561                 for (Enum anEnum : PerfConfig.Branch.values()) {
562                     dropList.add(anEnum.name().toLowerCase(Locale.ENGLISH));
563                 }
564                 selectIndex = perfConfig.getBranch();
565                 break;
566             }
567             case "Clock Type": {
568                 dropList = new ArrayList<>();
569                 for (Enum anEnum : PerfConfig.Clock.values()) {
570                     dropList.add(anEnum.name().toLowerCase(Locale.ENGLISH));
571                 }
572                 selectIndex = perfConfig.getClockId();
573                 break;
574             }
575             default: {
576                 break;
577             }
578         }
579         // recordFeatures add Arrange by
580         CustomComboBox<String> arrangeBox = new CustomComboBox<>();
581         arrangeBox.setFont(titleFont);
582         arrangeBox.setUI(new CustomJBComboBoxUI());
583         arrangeBox.setBorder(BorderFactory.createLineBorder(ColorConstants.NATIVE_RECORD_BORDER, 1));
584         if (isAddAll) {
585             arrangeBox.addItem("All");
586             cpuList.add(String.valueOf(cpuList.size()));
587         }
588         for (String itemName : dropList) {
589             arrangeBox.addItem(itemName);
590         }
591         arrangeBox.setSelectedIndex(selectIndex);
592         perfConfigPanel.add(arrangeBox, "growx,growy,span,wrap");
593         addArrangeBoxListener(name, arrangeBox);
594     }
595 
596     /**
597      * build SliderBar
598      *
599      * @param name name
600      */
buildSliderBar(String name)601     private void buildSliderBar(String name) {
602         JSlider unitSlider;
603         JBLabel valuePanel;
604         if (name.contains("CPU")) {
605             int cpuPercent = perfConfig.getCpuPercent();
606             // cpuPercent Slider
607             unitSlider = new JSlider(0, CPU_PERCENT_MAX);
608             unitSlider.setValue(cpuPercent);
609             unitSlider.setMajorTickSpacing(1);
610             // ValuePanel
611             valuePanel = new JBLabel("" + cpuPercent + " %", JBLabel.CENTER);
612         } else {
613             int mMapPages = perfConfig.getMmapPages();
614             // mMapPages Slider
615             unitSlider = new JSlider(M_MAP_PAGES_MIN_VALUE, M_MAP_PAGES_MAX_VALUE);
616             unitSlider.setValue(logTwo(mMapPages));
617             unitSlider.setMajorTickSpacing(12);
618             unitSlider.setMinorTickSpacing(2);
619             // ValuePanel
620             valuePanel = new JBLabel("" + mMapPages + " MB", JBLabel.CENTER);
621         }
622         valuePanel.setFont(titleFont);
623         valuePanel.setVerticalTextPosition(JBLabel.CENTER);
624         valuePanel.setHorizontalTextPosition(JBLabel.CENTER);
625         valuePanel.setOpaque(true);
626         perfConfigPanel.add(unitSlider, "growx,growy");
627         perfConfigPanel.add(valuePanel, "growx,growy,wrap");
628         valuePanel.setBackground(JBColor.background().brighter());
629         addUnitSliderListener(unitSlider, valuePanel);
630         valuePanel.setFont(titleFont);
631         valuePanel.setVerticalTextPosition(JBLabel.CENTER);
632         valuePanel.setHorizontalTextPosition(JBLabel.CENTER);
633     }
634 
635     /**
636      * build InputBox
637      *
638      * @param name name
639      */
buildInputBox(String name)640     private void buildInputBox(String name) {
641         JBTextField textField = new JBTextField();
642         if (name.contains("Frequency")) {
643             textField.setName("Frequency");
644             textField.setText(String.valueOf(perfConfig.getFrequency()));
645         } else {
646             textField.setName("Period");
647             textField.setText(String.valueOf(perfConfig.getPeriod()));
648         }
649         textField.addMouseListener(new MouseAdapter() {
650             @Override
651             public void mouseExited(MouseEvent event) {
652                 super.mouseExited(event);
653                 if (textField.getName().contains("Frequency")) {
654                     if (!textField.getText().equals("")) {
655                         perfConfig.setFrequency(Integer.parseInt(textField.getText()));
656                     }
657                 }
658                 if (textField.getName().contains("Period")) {
659                     if (!textField.getText().equals("")) {
660                         perfConfig.setPeriod(Integer.parseInt(textField.getText()));
661                     }
662                 }
663             }
664         });
665         textField.getDocument().addDocumentListener(new DocumentListener() {
666             @Override
667             public void insertUpdate(DocumentEvent event) {
668                 updateTextConfig(name, textField, event);
669             }
670 
671             @Override
672             public void removeUpdate(DocumentEvent event) {
673                 removeTextConfig(name, textField, event);
674             }
675 
676             @Override
677             public void changedUpdate(DocumentEvent event) {
678                 updateTextConfig(name, textField, event);
679             }
680         });
681         perfConfigPanel.add(textField, "span,growx,growy,wrap");
682     }
683 
updateTextConfig(String name, JBTextField textField, DocumentEvent event)684     private void updateTextConfig(String name, JBTextField textField, DocumentEvent event) {
685         textField.setDocument(new DigitCheckDocument(5));
686         int inputNumber = 0;
687         try {
688             String text = event.getDocument()
689                 .getText(event.getDocument().getStartPosition().getOffset(), event.getDocument().getLength());
690             inputNumber = Integer.parseInt(text);
691         } catch (BadLocationException | NumberFormatException exception) {
692             textField.setToolTipText("The input type is wrong, please select a number as input!");
693         }
694         if (name.contains("Frequency")) {
695             perfConfig.setFrequency(inputNumber);
696         } else {
697             perfConfig.setPeriod(inputNumber);
698         }
699     }
700 
removeTextConfig(String name, JBTextField textField, DocumentEvent event)701     private void removeTextConfig(String name, JBTextField textField, DocumentEvent event) {
702         try {
703             String text = event.getDocument()
704                 .getText(event.getDocument().getStartPosition().getOffset(), event.getDocument().getLength());
705             if (text == null) {
706                 if (name.contains("Frequency")) {
707                     perfConfig.setFrequency(0);
708                 } else {
709                     perfConfig.setPeriod(0);
710                 }
711             }
712         } catch (BadLocationException exception) {
713             textField.setToolTipText("The input type is wrong, please select a number as input!");
714         }
715     }
716 
717     /**
718      * build ToggleButton
719      *
720      * @param name name
721      */
buildToggleButton(String name)722     private void buildToggleButton(String name) {
723         // JBRadioButton
724         JToggleButton toggleButton = name.contains("Is Off CPU") ? new JToggleButton("", perfConfig.isOffCpu())
725             : new JToggleButton("", perfConfig.isInherit());
726         toggleButton.setOpaque(true);
727         toggleButton.setBorderPainted(false);
728         toggleButton.setSelectedIcon(NORMAL_ON);
729         toggleButton.setIcon(NORMAL_OFF);
730 
731         toggleButton.addMouseListener(new MouseAdapter() {
732             @Override
733             public void mouseReleased(MouseEvent event) {
734                 super.mouseReleased(event);
735                 if (name.contains("Is Off CPU")) {
736                     perfConfig.setOffCpu(toggleButton.isSelected());
737                 }
738                 if (name.contains("No Inherit")) {
739                     perfConfig.setInherit(toggleButton.isSelected());
740                 }
741             }
742         });
743         perfConfigPanel.add(toggleButton, "wrap");
744     }
745 
addArrangeBoxListener(String name, CustomComboBox<String> arrangeBox)746     private void addArrangeBoxListener(String name, CustomComboBox<String> arrangeBox) {
747         arrangeBox.addActionListener(event -> {
748             int selectedIndex = arrangeBox.getSelectedIndex();
749             if (name.contains("Call Stack")) {
750                 perfConfig.setCallStack(selectedIndex);
751             }
752             if (name.contains("Branch")) {
753                 perfConfig.setBranch(selectedIndex);
754             }
755             if (name.contains("Clock Type")) {
756                 perfConfig.setClockId(selectedIndex);
757             }
758         });
759     }
760 
addUnitSliderListener(JSlider unitSlider, JBLabel valuePanel)761     private void addUnitSliderListener(JSlider unitSlider, JBLabel valuePanel) {
762         unitSlider.addChangeListener(event -> {
763             if (unitSlider.getMajorTickSpacing() == 1) {
764                 valuePanel.setText("" + unitSlider.getValue() + " %");
765                 perfConfig.setCpuPercent(unitSlider.getValue());
766             } else {
767                 double mMapValue = Math.pow(2, unitSlider.getValue());
768                 valuePanel.setText("" + (int) mMapValue + " MB");
769                 perfConfig.setMmapPages((int) mMapValue);
770             }
771         });
772     }
773 
774     /**
775      * getPerfConfig
776      *
777      * @return PerfConfig <String>
778      */
getPerfConfig()779     public PerfConfig<String> getPerfConfig() {
780         return perfConfig;
781     }
782 
783     /**
784      * setPerfConfig
785      *
786      * @param perfConfig perfConfig
787      */
setPerfConfig(PerfConfig<String> perfConfig)788     public void setPerfConfig(PerfConfig<String> perfConfig) {
789         this.perfConfig = perfConfig;
790     }
791 
792     /**
793      * ComponentType enum
794      */
795     private enum ComponentType {
796         DROP_DOWN_BOX, SLIDER_BAR, INPUT_BOX, TOGGLE_BUTTON, MULTI_DROP_DOWN_BOX
797     }
798 
logTwo(int value)799     private int logTwo(int value) {
800         if (value == 1) {
801             return 0;
802         } else {
803             return 1 + logTwo(value >> 1);
804         }
805     }
806 }
807