1 /*******************************************************************************
2 * Copyright (c) 2011 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Polytechnique Montréal - Initial API and implementation
11 * Bernd Hufmann - Productification, enhancements and fixes
13 *******************************************************************************/
14 package org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.dialogs
;
18 import org
.eclipse
.core
.resources
.IProject
;
19 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
20 import org
.eclipse
.core
.runtime
.CoreException
;
21 import org
.eclipse
.linuxtools
.lttng
.LTTngProjectNature
;
22 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.TargetResource
;
23 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.TraceResource
;
24 import org
.eclipse
.linuxtools
.lttng
.tracecontrol
.model
.config
.TraceConfig
;
25 import org
.eclipse
.linuxtools
.lttng
.ui
.LTTngUiPlugin
;
26 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.Messages
;
27 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.TraceControlConstants
;
28 import org
.eclipse
.linuxtools
.lttng
.ui
.tracecontrol
.subsystems
.TraceSubSystem
;
29 import org
.eclipse
.rse
.services
.clientserver
.messages
.SystemMessageException
;
30 import org
.eclipse
.rse
.ui
.SystemBasePlugin
;
31 import org
.eclipse
.swt
.SWT
;
32 import org
.eclipse
.swt
.events
.SelectionEvent
;
33 import org
.eclipse
.swt
.events
.SelectionListener
;
34 import org
.eclipse
.swt
.layout
.GridData
;
35 import org
.eclipse
.swt
.layout
.GridLayout
;
36 import org
.eclipse
.swt
.widgets
.Button
;
37 import org
.eclipse
.swt
.widgets
.Combo
;
38 import org
.eclipse
.swt
.widgets
.Composite
;
39 import org
.eclipse
.swt
.widgets
.Dialog
;
40 import org
.eclipse
.swt
.widgets
.DirectoryDialog
;
41 import org
.eclipse
.swt
.widgets
.Display
;
42 import org
.eclipse
.swt
.widgets
.Event
;
43 import org
.eclipse
.swt
.widgets
.Group
;
44 import org
.eclipse
.swt
.widgets
.Label
;
45 import org
.eclipse
.swt
.widgets
.Listener
;
46 import org
.eclipse
.swt
.widgets
.Shell
;
47 import org
.eclipse
.swt
.widgets
.Text
;
50 * <b><u>NewTraceDialog</u></b>
52 * Dialog box to create a new trace.
55 public class NewTraceDialog
extends Dialog
{
57 // ------------------------------------------------------------------------
59 // ------------------------------------------------------------------------
61 private String fTraceName
;
62 private String fTraceTransport
;
63 private String fTracePath
;
65 private int fNumChannel
;
66 private Boolean fIsAppend
;
67 private Boolean fIsLocal
;
68 private Text fNameText
;
69 private Text fTransportText
;
70 private Text fPathText
;
71 private Text fNumLttdThreadsText
;
72 private Button fFinishButton
;
73 private Button fHostButton
;
74 private Button fTargetButton
;
75 private Button fIsAppendButton
;
76 private Button fFlightRecorderButton
;
77 private Button fNormalButton
;
78 private Boolean fFinishButtonClicked
;
79 private Display fDisplay
;
80 private String fTraceNameError
;
81 private String fTracePathError
;
82 private Label fErrorLabel
;
83 private Button fBrowseButton
;
85 private TraceSubSystem fSubSystem
;
86 private TargetResource fTargetResource
;
88 private IProject fProject
;
89 private static IProject defaultProject
;
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
98 * @param parent The parent shell
99 * @param subSystem The trace SubSystem
100 * @param targetResource The parent target resource
102 public NewTraceDialog(Shell parent
, TraceSubSystem subSystem
, TargetResource targetResource
) {
104 fSubSystem
= subSystem
;
105 fTargetResource
= targetResource
;
108 // ------------------------------------------------------------------------
110 // ------------------------------------------------------------------------
113 * Makes the dialog visible and returns the trace configuration of the new trace.
115 * @return trace configuration
117 public TraceConfig
open() {
118 Shell parent
= getParent();
119 final Shell shell
= new Shell(parent
, SWT
.TITLE
| SWT
.BORDER
| SWT
.APPLICATION_MODAL
);
120 shell
.setText(Messages
.NewTraceDialog_Title
);
122 shell
.setLayout(new GridLayout());
123 shell
.setImage(LTTngUiPlugin
.getDefault().getImage(LTTngUiPlugin
.ICON_ID_NEW_TRACE
));
125 GridData griddata
= new GridData();
126 fFinishButtonClicked
= Boolean
.valueOf(false);
127 fTraceNameError
= ""; //$NON-NLS-1$
128 fTracePathError
= ""; //$NON-NLS-1$
130 griddata
= new GridData();
131 Composite composite1
= new Composite(shell
, SWT
.NONE
);
132 GridLayout compositeLayout1
= new GridLayout(2, false);
133 composite1
.setSize(520, 300);
134 composite1
.setLayout(compositeLayout1
);
135 griddata
.horizontalSpan
= 3;
136 griddata
.widthHint
= 520;
137 griddata
.minimumWidth
= 520;
138 composite1
.setLayoutData(griddata
);
140 Label nameLabel
= new Label(composite1
, SWT
.NULL
);
141 nameLabel
.setText(Messages
.NewTraceDialog_TraceName
+ ":"); //$NON-NLS-1$
142 griddata
= new GridData();
143 griddata
.verticalIndent
= 20;
144 nameLabel
.setLayoutData(griddata
);
146 fNameText
= new Text(composite1
, SWT
.SINGLE
| SWT
.BORDER
);
147 if (fTargetResource
.isUst()) {
148 fNameText
.setText(TraceControlConstants
.Lttng_Ust_TraceName
);
149 fNameText
.setEnabled(false);
152 griddata
= new GridData();
153 griddata
.horizontalAlignment
= SWT
.FILL
;
154 griddata
.grabExcessHorizontalSpace
= true;
155 griddata
.verticalIndent
= 20;
156 fNameText
.setLayoutData(griddata
);
157 fNameText
.setSize(500, 50);
159 Label transportLabel
= new Label(composite1
, SWT
.NULL
);
160 transportLabel
.setText(Messages
.ConfigureTraceDialog_Trace_Transport
+ ":"); //$NON-NLS-1$
161 griddata
= new GridData();
162 transportLabel
.setLayoutData(griddata
);
164 fTransportText
= new Text(composite1
, SWT
.SINGLE
| SWT
.BORDER
);
165 griddata
= new GridData();
166 griddata
.horizontalAlignment
= SWT
.FILL
;
167 griddata
.grabExcessHorizontalSpace
= true;
168 fTransportText
.setLayoutData(griddata
);
169 fTransportText
.setSize(500, 50);
170 fTransportText
.setText(TraceControlConstants
.Lttng_Trace_Transport_Relay
);
171 fTransportText
.setEnabled(false); // relay is the only allowed value
173 griddata
= new GridData();
174 Group composite21
= new Group(composite1
, SWT
.SHADOW_OUT
);
175 composite21
.setSize(300, 300);
176 composite21
.setText(Messages
.ConfigureTraceDialog_Trace_Location
);
177 griddata
.horizontalAlignment
= SWT
.FILL
;
178 griddata
.horizontalSpan
= 2;
179 griddata
.verticalIndent
= 10;
180 griddata
.widthHint
= 300;
181 griddata
.minimumWidth
= 300;
182 composite21
.setLayoutData(griddata
);
183 GridLayout compositeLayout21
= new GridLayout(4, false);
184 composite21
.setLayout(compositeLayout21
);
185 fTargetButton
= new Button(composite21
, SWT
.RADIO
);
186 fTargetButton
.setText(Messages
.ConfigureTraceDialog_Target
);
187 fTargetButton
.setSelection(true);
188 fHostButton
= new Button(composite21
, SWT
.RADIO
);
189 fHostButton
.setText(Messages
.ConfigureTraceDialog_Host
);
190 griddata
= new GridData();
191 griddata
.horizontalSpan
= 3;
192 fHostButton
.setLayoutData(griddata
);
194 fHostButton
.addListener(SWT
.Selection
, new Listener() {
196 public void handleEvent(Event e
) {
197 if (fHostButton
.getSelection()) {
199 fBrowseButton
.setEnabled(true);
202 fBrowseButton
.setEnabled(false);
204 validatePathName(fPathText
.getText());
209 Label pathLabel
= new Label(composite21
, SWT
.NULL
);
210 pathLabel
.setText(Messages
.ConfigureTraceDialog_Trace_Path
);
211 griddata
= new GridData();
212 griddata
.verticalIndent
= 10;
213 pathLabel
.setLayoutData(griddata
);
215 fPathText
= new Text(composite21
, SWT
.SINGLE
| SWT
.BORDER
);
216 griddata
= new GridData();
217 griddata
.horizontalAlignment
= SWT
.FILL
;
218 griddata
.grabExcessHorizontalSpace
= true;
219 griddata
.verticalIndent
= 10;
220 fPathText
.setLayoutData(griddata
);
221 fPathText
.setData(""); //$NON-NLS-1$
223 fBrowseButton
= new Button(composite21
, SWT
.PUSH
);
224 fBrowseButton
.setText(Messages
.ConfigureTraceDialog_Browse
+ "..."); //$NON-NLS-1$
225 griddata
= new GridData();
226 griddata
.grabExcessHorizontalSpace
= false;
227 griddata
.widthHint
= 100;
228 griddata
.verticalIndent
= 10;
229 fBrowseButton
.setLayoutData(griddata
);
230 fBrowseButton
.setEnabled(false);
231 fBrowseButton
.addListener(SWT
.Selection
, new Listener() {
233 public void handleEvent(Event event
) {
234 DirectoryDialog dialog
= new DirectoryDialog(shell
);
235 String newPath
= dialog
.open();
236 if (newPath
!= null) {
237 fPathText
.setText(newPath
);
242 fNameText
.addListener(SWT
.Modify
, new Listener() {
244 public void handleEvent(Event event
) {
245 validateTraceName(fNameText
.getText());
250 fTransportText
.addListener(SWT
.Modify
, new Listener() {
252 public void handleEvent(Event event
) {
257 fPathText
.addListener(SWT
.Modify
, new Listener() {
259 public void handleEvent(Event event
) {
260 if (!fPathText
.isEnabled()) {
263 validatePathName(fPathText
.getText());
268 Composite projectComposite
= new Composite(composite1
, SWT
.NONE
);
269 projectComposite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false, 2, 1));
270 GridLayout gl
= new GridLayout(2, false);
272 gl
.marginHeight
= 10;
273 projectComposite
.setLayout(gl
);
275 Label projectLabel
= new Label(projectComposite
, SWT
.NONE
);
276 projectLabel
.setText(Messages
.NewTraceDialog_Tracing_Project
+ ":"); //$NON-NLS-1$);
278 final Combo projectCombo
= new Combo(projectComposite
, SWT
.READ_ONLY
);
279 projectCombo
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
280 for (IProject project
: ResourcesPlugin
.getWorkspace().getRoot().getProjects()) {
282 if (project
.isOpen() && project
.hasNature(LTTngProjectNature
.ID
)) {
283 projectCombo
.add(project
.getName());
284 projectCombo
.setData(project
.getName(), project
);
285 if (fProject
== null || project
.equals(defaultProject
)) {
286 projectCombo
.select(projectCombo
.getItemCount() - 1);
290 } catch (CoreException e
) {
291 SystemBasePlugin
.logError("NewTraceDialog", e
); //$NON-NLS-1$
294 projectCombo
.addSelectionListener(new SelectionListener() {
296 public void widgetSelected(SelectionEvent e
) {
297 fProject
= (IProject
) projectCombo
.getData(projectCombo
.getText());
300 public void widgetDefaultSelected(SelectionEvent e
) {
303 griddata
= new GridData();
304 Composite composite2
= new Composite(composite1
, SWT
.NONE
);
305 GridLayout compositeLayout2
= new GridLayout(2, false);
306 compositeLayout2
.marginWidth
= 0;
307 composite2
.setLayout(compositeLayout2
);
308 griddata
.horizontalSpan
= 2;
309 composite2
.setLayoutData(griddata
);
311 Label numLttdThreadsLabel
= new Label(composite2
, SWT
.NULL
);
312 numLttdThreadsLabel
.setText(Messages
.ConfigureTraceDialog_Num_Lttd_Threads
+ ":"); //$NON-NLS-1$);
314 fNumLttdThreadsText
= new Text(composite2
, SWT
.SINGLE
| SWT
.BORDER
);
315 griddata
= new GridData();
316 griddata
.horizontalAlignment
= SWT
.BEGINNING
;
317 griddata
.widthHint
= 50;
318 griddata
.minimumWidth
= 50;
319 fNumLttdThreadsText
.setLayoutData(griddata
);
320 if (fTargetResource
.isUst()) {
321 fNumLttdThreadsText
.setText("1"); //$NON-NLS-1$
322 fNumLttdThreadsText
.setEnabled(false);
324 fNumLttdThreadsText
.setText("2"); //$NON-NLS-1$
327 fNumLttdThreadsText
.addListener(SWT
.Verify
, new Listener() {
329 public void handleEvent(Event e
) {
330 String string
= e
.text
;
331 char[] chars
= new char[string
.length()];
332 string
.getChars(0, chars
.length
, chars
, 0);
333 for (int i
= 0; i
< chars
.length
; i
++) {
334 if (!('0' <= chars
[i
] && chars
[i
] <= '9')) {
342 fNumLttdThreadsText
.addListener(SWT
.Modify
, new Listener() {
344 public void handleEvent(Event event
) {
349 fIsAppendButton
= new Button(composite1
, SWT
.CHECK
);
350 fIsAppendButton
.setText(Messages
.ConfigureTraceDialog_Append
);
351 griddata
= new GridData();
352 griddata
.horizontalAlignment
= SWT
.BEGINNING
;
353 griddata
.horizontalSpan
= 2;
354 griddata
.verticalIndent
= 10;
355 fIsAppendButton
.setLayoutData(griddata
);
356 fIsAppend
= Boolean
.valueOf(false);
357 fIsAppendButton
.addListener(SWT
.Selection
, new Listener() {
359 public void handleEvent(Event e
) {
360 if (fIsAppendButton
.getSelection()) {
368 if (fTargetResource
.isUst()) {
369 fIsAppendButton
.setEnabled(false);
372 griddata
= new GridData();
373 Group composite22
= new Group(composite1
, SWT
.SHADOW_OUT
);
374 composite22
.setText(Messages
.ConfigureTraceDialog_Trace_Mode
);
375 griddata
.horizontalSpan
= 2;
376 griddata
.verticalIndent
= 10;
377 composite22
.setLayoutData(griddata
);
378 GridLayout compositeLayout22
= new GridLayout(2, false);
379 composite22
.setLayout(compositeLayout22
);
380 fNormalButton
= new Button(composite22
, SWT
.RADIO
);
381 fNormalButton
.setText(Messages
.ConfigureTraceDialog_Mode_Normal
);
382 fFlightRecorderButton
= new Button(composite22
, SWT
.RADIO
);
383 fFlightRecorderButton
.setText(Messages
.ConfigureTraceDialog_Mode_Flight_Recorder
);
384 fMode
= TraceConfig
.NORMAL_MODE
;
385 fNormalButton
.setSelection(true);
386 fNormalButton
.addListener(SWT
.Selection
, new Listener() {
388 public void handleEvent(Event e
) {
389 if (fNormalButton
.getSelection()) {
390 fMode
= TraceConfig
.NORMAL_MODE
;
394 fFlightRecorderButton
.addListener(SWT
.Selection
, new Listener() {
396 public void handleEvent(Event e
) {
397 if (fFlightRecorderButton
.getSelection()) {
398 fMode
= TraceConfig
.FLIGHT_RECORDER_MODE
;
402 if (fTargetResource
.isUst()) {
403 fFlightRecorderButton
.setEnabled(false);
404 fNormalButton
.setEnabled(false);
407 fErrorLabel
= new Label(shell
, SWT
.NULL
);
408 fDisplay
= parent
.getDisplay();
409 fErrorLabel
.setForeground(fDisplay
.getSystemColor(SWT
.COLOR_RED
));
410 griddata
= new GridData();
411 griddata
.widthHint
= 400;
412 griddata
.minimumWidth
= 400;
413 fErrorLabel
.setLayoutData(griddata
);
415 Label shadow_sep_h
= new Label(shell
, SWT
.SEPARATOR
| SWT
.SHADOW_OUT
| SWT
.HORIZONTAL
);
416 griddata
= new GridData();
417 griddata
.horizontalAlignment
= SWT
.FILL
;
418 griddata
.grabExcessHorizontalSpace
= true;
419 griddata
.verticalIndent
= 20;
420 shadow_sep_h
.setLayoutData(griddata
);
422 Composite buttonComposite
= new Composite(shell
, SWT
.NONE
);
423 buttonComposite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
424 buttonComposite
.setLayout(new GridLayout(2, false));
426 Button cancelButton
= new Button(buttonComposite
, SWT
.PUSH
);
427 cancelButton
.setText(Messages
.ConfigureTraceDialog_Cancel
);
428 cancelButton
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.CENTER
, true, false));
430 fFinishButton
= new Button(buttonComposite
, SWT
.PUSH
);
431 fFinishButton
.setText(Messages
.ConfigureTraceDialog_Finish
);
432 fFinishButton
.setLayoutData(new GridData(SWT
.CENTER
, SWT
.CENTER
, false, false));
433 fFinishButton
.addListener(SWT
.Selection
, new Listener() {
435 public void handleEvent(Event event
) {
436 fFinishButtonClicked
= true;
442 cancelButton
.addListener(SWT
.Selection
, new Listener() {
444 public void handleEvent(Event event
) {
446 fTraceTransport
= null;
452 shell
.addListener(SWT
.Traverse
, new Listener() {
454 public void handleEvent(Event event
) {
455 if (event
.detail
== SWT
.TRAVERSE_ESCAPE
) {
463 Display display
= parent
.getDisplay();
464 while (!shell
.isDisposed()) {
465 if (!display
.readAndDispatch()) {
469 if ((fTraceName
== null) || (fTraceTransport
== null) || (fTracePath
== null) || (!fFinishButtonClicked
)) {
472 TraceConfig result
= new TraceConfig();
473 result
.setTraceName(fTraceName
);
474 result
.setTraceTransport(fTraceTransport
);
475 result
.setTracePath(fTracePath
);
476 result
.setNetworkTrace(fIsLocal
);
477 result
.setIsAppend(fIsAppend
);
478 result
.setMode(fMode
);
479 result
.setNumChannel(fNumChannel
);
480 result
.setProject(fProject
);
481 defaultProject
= fProject
;
486 * Validates the trace name which has to be unique.
488 private boolean validateTraceName(String name
) {
489 if (name
.length() > 0) {
490 TraceResource
[] traces
= new TraceResource
[0];
492 traces
= fSubSystem
.getAllTraces();
493 } catch (SystemMessageException e
) {
494 SystemBasePlugin
.logError("NewTraceDialog ", e
); //$NON-NLS-1$
496 for (int i
= 0; i
< traces
.length
; i
++) {
497 if (traces
[i
].getName().compareTo(name
) == 0) {
498 fTraceNameError
= Messages
.NewTraceDialog_Error_Already_Exists
;
499 fErrorLabel
.setText(fTraceNameError
);
503 final char[] chars
= name
.toCharArray();
504 for (int x
= 0; x
< chars
.length
; x
++) {
505 final char c
= chars
[x
];
506 if ((x
== 0) && !(((c
>= 'a') && (c
<= 'z')) || ((c
>= 'A') && (c
<= 'Z')))) {
507 fTraceNameError
= Messages
.NewTraceDialog_Error_Invalid_First_Char
;
508 fErrorLabel
.setText(fTraceNameError
);
511 if (!((c
>= 'a') && (c
<= 'z')) && !((c
>= 'A') && (c
<= 'Z')) && !((c
>= '0') && (c
<= '9'))) {
512 fTraceNameError
= Messages
.NewTraceDialog_Error_Invalid_Name
;
513 fErrorLabel
.setText(fTraceNameError
);
519 if (fTracePathError
.length() > 0) {
520 fErrorLabel
.setText(fTracePathError
);
522 fErrorLabel
.setText(""); //$NON-NLS-1$
524 fTraceNameError
= ""; //$NON-NLS-1$
529 * Validates the trace path.
531 private boolean validatePathName(String path
) {
532 if (path
.length() > 0) {
533 final char c0
= path
.charAt(0);
535 fTracePathError
= Messages
.ConfigureTraceDialog_Error_Invalid_Path
;
536 fErrorLabel
.setText(fTracePathError
);
539 String
[] folders
= path
.split("/"); //$NON-NLS-1$
540 for (int i
= 0; i
< folders
.length
; i
++) {
541 final char[] chars
= folders
[i
].toCharArray();
542 for (int x
= 0; x
< chars
.length
; x
++) {
543 final char c
= chars
[x
];
544 if ((c
>= 'a') && (c
<= 'z')) {
545 continue; // lowercase
547 if ((c
>= 'A') && (c
<= 'Z')) {
548 continue; // uppercase
550 if ((c
>= '0') && (c
<= '9')) {
553 fTracePathError
= Messages
.ConfigureTraceDialog_Error_Invalid_Folder
;
554 fErrorLabel
.setText(fTracePathError
);
558 if (path
.length() > 1) {
559 for (int i
= 0; i
< path
.length() - 1; i
++) {
560 if ((path
.charAt(i
) == '/') && (path
.charAt(i
+ 1) == '/')) {
561 fTracePathError
= Messages
.ConfigureTraceDialog_Error_Multiple_Seps
;
562 fErrorLabel
.setText(fTracePathError
);
569 File file
= new File(path
);
571 fTracePathError
= Messages
.ConfigureTraceDialog_Error_File_Exists
;
572 fErrorLabel
.setText(fTracePathError
);
575 if (path
.length() > 1 && !file
.getParentFile().canWrite()) {
576 fTracePathError
= Messages
.ConfigureTraceDialog_Error_Can_Not_Write
;
577 fErrorLabel
.setText(fTracePathError
);
582 if (fTraceNameError
.length() > 0) {
583 fErrorLabel
.setText(fTraceNameError
);
585 fErrorLabel
.setText(""); //$NON-NLS-1$
587 fTracePathError
= ""; //$NON-NLS-1$
592 * It validates all input values.
594 private void validate() {
595 if ((fTracePathError
.length() > 0) || (fTraceNameError
.length() > 0)) {
596 fFinishButton
.setEnabled(false);
599 if ((fNameText
.getText() == null) || (fNameText
.getText().length() == 0)) {
600 fErrorLabel
.setText(Messages
.NewTraceDialog_Error_No_Name
);
601 fFinishButton
.setEnabled(false);
604 if ((fTransportText
.getText() == null) || (fTransportText
.getText().length() == 0)) {
605 fFinishButton
.setEnabled(false);
608 if (fPathText
.getText().length() == 0) {
609 fErrorLabel
.setText(Messages
.NewTraceDialog_Error_No_Path
);
610 fFinishButton
.setEnabled(false);
613 if (fProject
== null) {
614 fErrorLabel
.setText(Messages
.NewTraceDialog_Error_No_Project
);
615 fFinishButton
.setEnabled(false);
618 if ((fNumLttdThreadsText
.getText().length() == 0) || (fNumLttdThreadsText
.getText().length() == 0)) {
619 fErrorLabel
.setText(Messages
.NewTraceDialog_Error_No_NumLttdThreads
);
620 fFinishButton
.setEnabled(false);
623 fErrorLabel
.setText(""); //$NON-NLS-1$
624 fTraceName
= fNameText
.getText();
625 fTraceTransport
= fTransportText
.getText();
626 fTracePath
= fPathText
.getText();
627 fNumChannel
= Integer
.parseInt(fNumLttdThreadsText
.getText());
628 fFinishButton
.setEnabled(true);