diff --git a/php.dbgp/nbproject/project.xml b/php.dbgp/nbproject/project.xml --- a/php.dbgp/nbproject/project.xml +++ b/php.dbgp/nbproject/project.xml @@ -133,6 +133,15 @@ + org.netbeans.modules.editor.mimelookup + + + + 1 + 1.41 + + + org.netbeans.modules.lexer diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BreakpointsReader.java @@ -47,11 +47,8 @@ import java.net.URL; import org.netbeans.api.debugger.Properties; import org.netbeans.modules.php.dbgp.breakpoints.FunctionBreakpoint.Type; -import org.openide.cookies.LineCookie; import org.openide.filesystems.FileObject; import org.openide.filesystems.URLMapper; -import org.openide.loaders.DataObject; -import org.openide.loaders.DataObjectNotFoundException; import org.openide.text.Line; /** @@ -59,8 +56,7 @@ * @author ads */ public class BreakpointsReader implements Properties.Reader { - private static final String LINE_NUMBER = "lineNumber"; // NOI18N - private static final String URL = "url"; // NOI18N + private static final String ENABED = "enabled"; // NOI18N private static final String FUNC_NAME = "functionName"; // NOI18N private static final String TYPE = "type"; // NOI18N @@ -77,7 +73,7 @@ @Override public Object read(String typeID, Properties properties) { if (typeID.equals(LineBreakpoint.class.getName())) { - Line line = getLine(properties.getString(URL, null), properties.getInt(LINE_NUMBER, 1)); + Line line = getLine(properties.getString(LineBreakpoint.PROP_URL, null), properties.getInt(LineBreakpoint.PROP_LINE_NUMBER, 1)); if (line == null) { return null; } @@ -86,6 +82,7 @@ breakpoint.disable(); } breakpoint.setGroupName(properties.getString(GROUP_NAME, "")); + breakpoint.setCondition(properties.getString(LineBreakpoint.PROP_CONDITION, null)); return breakpoint; } else if (typeID.equals(FunctionBreakpoint.class.getName())) { String func = properties.getString(FUNC_NAME, null); @@ -109,10 +106,11 @@ if (object instanceof LineBreakpoint) { LineBreakpoint breakpoint = (LineBreakpoint) object; FileObject fileObject = breakpoint.getLine().getLookup().lookup(FileObject.class); - properties.setString(URL, fileObject.toURL().toString()); - properties.setInt(LINE_NUMBER, breakpoint.getLine().getLineNumber()); + properties.setString(LineBreakpoint.PROP_URL, fileObject.toURL().toString()); + properties.setInt(LineBreakpoint.PROP_LINE_NUMBER, breakpoint.getLine().getLineNumber()); properties.setBoolean(ENABED, breakpoint.isEnabled()); properties.setString(GROUP_NAME, breakpoint.getGroupName()); + properties.setString(LineBreakpoint.PROP_CONDITION, breakpoint.getCondition()); } else if (object instanceof FunctionBreakpoint) { FunctionBreakpoint breakpoint = (FunctionBreakpoint) object; String func = breakpoint.getFunction(); @@ -128,28 +126,7 @@ if (file == null) { return null; } - DataObject dataObject; - try { - dataObject = DataObject.find(file); - } catch (DataObjectNotFoundException ex) { - return null; - } - if (dataObject == null) { - return null; - } - LineCookie lineCookie = dataObject.getLookup().lookup(LineCookie.class); - if (lineCookie == null) { - return null; - } - Line.Set ls = lineCookie.getLineSet(); - if (ls == null) { - return null; - } - try { - return ls.getCurrent(lineNumber); - } catch (IndexOutOfBoundsException e) { - return null; - } + return Utils.getLine(file, lineNumber); } private FileObject getFileObject(String url) { diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BrkptsViewActionProvider.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BrkptsViewActionProvider.java --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BrkptsViewActionProvider.java +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/BrkptsViewActionProvider.java @@ -43,13 +43,25 @@ */ package org.netbeans.modules.php.dbgp.breakpoints; +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.Action; - +import org.netbeans.modules.php.dbgp.ui.DbgpLineBreakpointCustomizer; +import org.netbeans.modules.php.dbgp.ui.DbgpLineBreakpointCustomizerPanel; +import org.netbeans.spi.debugger.ui.Controller; import org.netbeans.spi.viewmodel.Models; import org.netbeans.spi.viewmodel.NodeActionsProvider; import org.netbeans.spi.viewmodel.NodeActionsProviderFilter; import org.netbeans.spi.viewmodel.UnknownTypeException; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.NotificationLineSupport; +import org.openide.NotifyDescriptor; import org.openide.text.Line; +import org.openide.util.HelpCtx; import org.openide.util.NbBundle; /** @@ -63,10 +75,12 @@ public Action[] getActions(NodeActionsProvider original, Object node) throws UnknownTypeException { Action[] actions = original.getActions(node); if (node instanceof LineBreakpoint) { - Action[] newActions = new Action[actions.length + 2]; + Action[] newActions = new Action[actions.length + 4]; newActions[0] = GO_TO_SOURCE_ACTION; newActions[1] = null; System.arraycopy(actions, 0, newActions, 2, actions.length); + newActions[newActions.length - 2] = null; + newActions[newActions.length - 1] = CUSTOMIZE_ACTION; actions = newActions; } return actions; @@ -87,6 +101,64 @@ line.show(Line.ShowOpenType.REUSE, Line.ShowVisibilityType.FOCUS); } } + + @NbBundle.Messages("CTL_Breakpoint_Customizer_Title=Breakpoint Properties") + private static void customize(LineBreakpoint lb) { + DbgpLineBreakpointCustomizerPanel panel = DbgpLineBreakpointCustomizer.getCustomizerComponent(lb); + HelpCtx helpCtx = HelpCtx.findHelp(panel); + if (helpCtx == null) { + helpCtx = new HelpCtx("debug.add.breakpoint"); // NOI18N + } + + Controller controller = panel.getController(); + if (controller == null) { + return; + } + + final Controller[] cPtr = new Controller[]{controller}; + final DialogDescriptor[] descriptorPtr = new DialogDescriptor[1]; + final Dialog[] dialogPtr = new Dialog[1]; + final PropertyChangeListener propertyChangeListener = (PropertyChangeEvent e) -> { + if (e.getPropertyName().equals(NotifyDescriptor.PROP_ERROR_NOTIFICATION)) { + Object v = e.getNewValue(); + String message = (v == null) ? null : v.toString(); + descriptorPtr[0].getNotificationLineSupport().setErrorMessage(message); + } else if (e.getPropertyName().equals(Controller.PROP_VALID)) { + descriptorPtr[0].setValid(controller.isValid()); + } + }; + controller.addPropertyChangeListener(propertyChangeListener); + ActionListener buttonsActionListener = (ActionEvent e) -> { + if (descriptorPtr[0].getValue() == DialogDescriptor.OK_OPTION) { + boolean ok = cPtr[0].ok(); + if (ok) { + dialogPtr[0].setVisible(false); + cPtr[0].removePropertyChangeListener(propertyChangeListener); + } + } else { + dialogPtr[0].setVisible(false); + cPtr[0].removePropertyChangeListener(propertyChangeListener); + } + }; + DialogDescriptor descriptor = new DialogDescriptor( + panel, + Bundle.CTL_Breakpoint_Customizer_Title(), + true, + DialogDescriptor.OK_CANCEL_OPTION, + DialogDescriptor.OK_OPTION, + DialogDescriptor.DEFAULT_ALIGN, + helpCtx, + buttonsActionListener + ); + descriptor.setClosingOptions(new Object[]{}); + descriptor.createNotificationLineSupport(); + Dialog d = DialogDisplayer.getDefault().createDialog(descriptor); + d.pack(); + descriptorPtr[0] = descriptor; + dialogPtr[0] = d; + d.setVisible(true); + } + private static final Action GO_TO_SOURCE_ACTION = Models.createAction( NbBundle.getMessage(BrkptsViewActionProvider.class, GO_TO_SOURCE_LABEL), new GoToSourcePerformer(), @@ -106,4 +178,24 @@ } + @NbBundle.Messages("CTL_Breakpoint_Customize_Label=Properties") + private static final Action CUSTOMIZE_ACTION = Models.createAction( + Bundle.CTL_Breakpoint_Customize_Label(), + new CustomizePerformer(), + Models.MULTISELECTION_TYPE_EXACTLY_ONE + ); + + private static class CustomizePerformer implements Models.ActionPerformer { + + @Override + public boolean isEnabled(Object node) { + return true; + } + + @Override + public void perform(Object[] nodes) { + customize((LineBreakpoint) nodes[0]); + } + } + } diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/DbgpLineBreakpointType.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/DbgpLineBreakpointType.java new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/DbgpLineBreakpointType.java @@ -0,0 +1,115 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + */ +package org.netbeans.modules.php.dbgp.breakpoints; + +import javax.swing.JComponent; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import org.netbeans.api.editor.EditorRegistry; +import org.netbeans.api.editor.document.LineDocumentUtils; +import org.netbeans.editor.BaseDocument; +import org.netbeans.modules.editor.NbEditorUtilities; +import org.netbeans.modules.php.api.util.FileUtils; +import org.netbeans.modules.php.dbgp.ui.DbgpLineBreakpointCustomizerPanel; +import org.netbeans.spi.debugger.ui.BreakpointType; +import org.netbeans.spi.debugger.ui.Controller; +import org.openide.filesystems.FileObject; +import org.openide.text.Line; +import org.openide.util.NbBundle; + +@NbBundle.Messages({ + "DbgpLineBreakpointType.CategoryDisplayName=PHP", + "DbgpLineBreakpointType.TypeDisplayName=Line" +}) +@BreakpointType.Registration(displayName = "#DbgpLineBreakpointType.TypeDisplayName") +public class DbgpLineBreakpointType extends BreakpointType { + + private Controller controller; + + @Override + public String getCategoryDisplayName() { + return Bundle.DbgpLineBreakpointType_CategoryDisplayName(); + } + + @Override + public String getTypeDisplayName() { + return Bundle.DbgpLineBreakpointType_TypeDisplayName(); + } + + @Override + public JComponent getCustomizer() { + JTextComponent lastFocusedComponent = EditorRegistry.lastFocusedComponent(); + Line line; + if (lastFocusedComponent != null) { + FileObject fileObject = NbEditorUtilities.getFileObject(lastFocusedComponent.getDocument()); + int caretPosition = lastFocusedComponent.getCaretPosition(); + try { + int lineNumber = LineDocumentUtils.getLineIndex((BaseDocument) lastFocusedComponent.getDocument(), caretPosition); + line = Utils.getLine(fileObject, lineNumber); + } catch (BadLocationException ex) { + line = null; + } + } else { + line = null; + } + DbgpLineBreakpointCustomizerPanel customizer = new DbgpLineBreakpointCustomizerPanel(line); + controller = customizer.getController(); + return customizer; + } + + @Override + public Controller getController() { + return controller; + } + + @Override + public boolean isDefault() { + JTextComponent lastFocusedComponent = EditorRegistry.lastFocusedComponent(); + if (lastFocusedComponent == null) { + return false; + } + FileObject fileObject = NbEditorUtilities.getFileObject(lastFocusedComponent.getDocument()); + if (fileObject == null) { + return false; + } + return FileUtils.isPhpFile(fileObject); + } + +} diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpoint.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpoint.java --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpoint.java +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpoint.java @@ -61,6 +61,7 @@ import org.netbeans.editor.BaseDocument; import org.netbeans.editor.Utilities; import org.netbeans.modules.csl.api.OffsetRange; +import org.netbeans.modules.csl.spi.support.CancelSupport; import org.netbeans.modules.parsing.api.ParserManager; import org.netbeans.modules.parsing.api.ResultIterator; import org.netbeans.modules.parsing.api.Source; @@ -79,6 +80,7 @@ import org.openide.filesystems.FileChangeListener; import org.openide.filesystems.FileEvent; import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileRenameEvent; import org.openide.loaders.DataObject; import org.openide.text.DataEditorSupport; import org.openide.text.Line; @@ -87,17 +89,26 @@ import org.openide.util.WeakListeners; /** + * If this class name is changed, {@link LineBreakpointBeanInfo} class name must + * be changed. * * @author ads */ public class LineBreakpoint extends AbstractBreakpoint { + private static final Logger LOGGER = Logger.getLogger(LineBreakpoint.class.getName()); private static final RequestProcessor RP = new RequestProcessor(LineBreakpoint.class); + public static final String PROP_URL = "url"; // NOI18N + public static final String PROP_LINE_NUMBER = "lineNumber"; // NOI18N + public static final String PROP_CONDITION = "condition"; // NOI18N + private final Line myLine; private final FileRemoveListener myListener; private FileChangeListener myWeakListener; private final String myFileUrl; private final Future isValidFuture; + // @GuardedBy("this") + private String condition; public LineBreakpoint(Line line) { myLine = line; @@ -188,6 +199,24 @@ return myFileUrl; } + public synchronized final String getCondition() { + return condition; + } + + public synchronized final void setCondition(String condition) { + String oldCondition = this.condition; + if ((condition != null && condition.equals(oldCondition)) + || (condition == null && oldCondition == null)) { + return; + } + this.condition = condition; + firePropertyChange(PROP_CONDITION, oldCondition, condition); + } + + public synchronized final boolean isConditional() { + return condition != null && !condition.isEmpty(); + } + @Override public int isTemp() { return 0; @@ -215,6 +244,11 @@ return new PhpGroupProperties(); } + void fireLineNumberChanged() { + int lineNumber = getLine().getLineNumber(); + firePropertyChange(PROP_LINE_NUMBER, null, lineNumber); + } + //~ Inner classes private final class PhpGroupProperties extends GroupProperties { @@ -277,6 +311,12 @@ LineBreakpoint.this); } + @Override + public void fileRenamed(FileRenameEvent fe) { + FileObject renamedFo = fe.getFile(); + firePropertyChange(PROP_URL, myFileUrl, renamedFo.toURL().toString()); + } + } private static final class StatementVisitor extends DefaultVisitor { @@ -291,6 +331,9 @@ @Override public void scan(ASTNode node) { + if (CancelSupport.getDefault().isCancelled()) { + return; + } if (node != null) { OffsetRange nodeRange = new OffsetRange(node.getStartOffset(), node.getEndOffset()); if (node instanceof Statement && nodeRange.containsInclusive(contentStart) && nodeRange.containsInclusive(contentEnd)) { diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpointBeanInfo.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpointBeanInfo.java new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/LineBreakpointBeanInfo.java @@ -0,0 +1,67 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + */ +package org.netbeans.modules.php.dbgp.breakpoints; + +import java.beans.BeanDescriptor; +import java.beans.SimpleBeanInfo; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.util.Lookup; + +/** + * Don't change this class name. If it is changed, {@link LineBreakpoint} class name + * must be changed. + */ +public class LineBreakpointBeanInfo extends SimpleBeanInfo { + + private static final Logger LOGGER = Logger.getLogger(LineBreakpointBeanInfo.class.getName()); + + @Override + public BeanDescriptor getBeanDescriptor() { + Class customizer = null; + try { + customizer = Class.forName("org.netbeans.modules.php.dbgp.ui.DbgpLineBreakpointCustomizer", // NOI18N + true, Lookup.getDefault().lookup(ClassLoader.class)); + } catch (ClassNotFoundException cnfex) { + LOGGER.log(Level.WARNING, "No BP customizer", cnfex); // NOI18N + } + return new BeanDescriptor(LineBreakpoint.class, customizer); + } +} diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/UpdatePropertiesOnSaveTask.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/UpdatePropertiesOnSaveTask.java new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/UpdatePropertiesOnSaveTask.java @@ -0,0 +1,99 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + */ +package org.netbeans.modules.php.dbgp.breakpoints; + +import javax.swing.text.Document; +import org.netbeans.api.debugger.Breakpoint; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.editor.mimelookup.MimeRegistration; +import org.netbeans.modules.editor.NbEditorUtilities; +import org.netbeans.modules.php.api.util.FileUtils; +import org.netbeans.spi.editor.document.OnSaveTask; +import org.openide.filesystems.FileObject; + +/** + * Save line number on save. + */ +public class UpdatePropertiesOnSaveTask implements OnSaveTask { + + private final Context context; + + private UpdatePropertiesOnSaveTask(Context context) { + this.context = context; + } + + @Override + public void performTask() { + Document document = context.getDocument(); + FileObject fileObject = NbEditorUtilities.getFileObject(document); + if (fileObject == null) { + return; + } + String fileUrl = fileObject.toURL().toString(); + DebuggerManager manager = DebuggerManager.getDebuggerManager(); + for (Breakpoint breakpoint : manager.getBreakpoints()) { + if (breakpoint instanceof LineBreakpoint) { + LineBreakpoint lineBreakpoint = (LineBreakpoint) breakpoint; + if (fileUrl.equals(lineBreakpoint.getFileUrl())) { + lineBreakpoint.fireLineNumberChanged(); + } + } + } + } + + @Override + public void runLocked(Runnable run) { + run.run(); + } + + @Override + public boolean cancel() { + return true; + } + + @MimeRegistration(mimeType = FileUtils.PHP_MIME_TYPE, service = OnSaveTask.Factory.class, position = 1100) + public static final class FactoryImpl implements Factory { + + @Override + public OnSaveTask createTask(Context context) { + return new UpdatePropertiesOnSaveTask(context); + } + } +} diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/breakpoints/Utils.java @@ -46,6 +46,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import org.netbeans.api.annotations.common.CheckForNull; import org.netbeans.api.debugger.Breakpoint; import org.netbeans.api.debugger.DebuggerManager; import org.netbeans.api.options.OptionsDisplayer; @@ -80,6 +81,12 @@ Utils.lineFactory = lineFactory; } + /** + * Get the current line. + * + * @return the current line if the file is php, otherwise {@code null}. + */ + @CheckForNull public static Line getCurrentLine() { FileObject fileObject = EditorContextDispatcher.getDefault().getCurrentFile(); @@ -90,6 +97,44 @@ return EditorContextDispatcher.getDefault().getCurrentLine(); } + /** + * Get the Line from FileObject. + * + * @param file the FileObject + * @param lineNumber the line number + * @return the line if it is found with the file and the line number, + * otherwise {@code null} + */ + @CheckForNull + public static Line getLine(FileObject file, int lineNumber) { + if (file == null || lineNumber < 0) { + return null; + } + + DataObject dataObject; + try { + dataObject = DataObject.find(file); + } catch (DataObjectNotFoundException ex) { + return null; + } + if (dataObject == null) { + return null; + } + LineCookie lineCookie = dataObject.getLookup().lookup(LineCookie.class); + if (lineCookie == null) { + return null; + } + Line.Set ls = lineCookie.getLineSet(); + if (ls == null) { + return null; + } + try { + return ls.getCurrent(lineNumber); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + public static BrkpntSetCommand getCommand(DebugSession session, SessionId id, AbstractBreakpoint breakpoint) { if (!breakpoint.isSessionRelated(session)) { return null; diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntCommandBuilder.java @@ -55,10 +55,15 @@ * */ public final class BrkpntCommandBuilder { + private BrkpntCommandBuilder() { } public static BrkpntSetCommand buildLineBreakpoint(SessionId id, String transactionId, FileObject localFile, int lineNumber) { + return buildLineBreakpoint(id, transactionId, localFile, lineNumber, null); + } + + public static BrkpntSetCommand buildLineBreakpoint(SessionId id, String transactionId, FileObject localFile, int lineNumber, String condition) { if (localFile == null) { // #251806 return null; @@ -71,13 +76,14 @@ command.setType(Types.LINE); command.setFile(uri); command.setLineNumber(lineNumber); + command.setExpression(condition); return command; } public static BrkpntSetCommand buildLineBreakpoint(SessionId id, String transactionId, LineBreakpoint breakpoint) { Line line = breakpoint.getLine(); FileObject fileObject = line.getLookup().lookup(FileObject.class); - BrkpntSetCommand command = buildLineBreakpoint(id, transactionId, fileObject, line.getLineNumber()); + BrkpntSetCommand command = buildLineBreakpoint(id, transactionId, fileObject, line.getLineNumber(), breakpoint.getCondition()); if (command != null) { command.setBreakpoint(breakpoint); } diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/packets/BrkpntSetCommand.java @@ -158,7 +158,7 @@ } public void setExpression(String expression) { - myException = expression; + myExpression = expression; } public void setTemporary(boolean isTemp) { diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties --- a/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/Bundle.properties @@ -41,6 +41,7 @@ # made subject to such option by the copyright holder. LBL_Settings=Settings +LBL_Condition=Condition LBL_MethodName=&Method Name: LBL_StopOn=&Stop On: A11_SettingsName=Settings @@ -88,3 +89,9 @@ LocalFilterPanel.myResource.AccessibleContext.accessibleDescription=Enable for resource LocalFilterPanel.myNull.AccessibleContext.accessibleDescription=Enable for null type LocalFilterPanel.mySelectLbl.AccessibleContext.accessibleName=Select types to show +DbgpLineBreakpointCustomizerPanel.conditionCheckBox.text=&Condition: +DbgpLineBreakpointCustomizerPanel.lineNumberTextField.text= +DbgpLineBreakpointCustomizerPanel.fileTextField.text= +DbgpLineBreakpointCustomizerPanel.lineNumberLabel.text=&Line Number: +DbgpLineBreakpointCustomizerPanel.fileLabel.text=&File: +DbgpLineBreakpointCustomizerPanel.conditionComboBox.toolTipText=Breakpoint is hit when this condition evaluates to true. diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/ControllerProvider.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/ControllerProvider.java new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/ControllerProvider.java @@ -0,0 +1,47 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + */ +package org.netbeans.modules.php.dbgp.ui; + +import org.netbeans.spi.debugger.ui.Controller; + +public interface ControllerProvider { + + Controller getController(); +} diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizer.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizer.java new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizer.java @@ -0,0 +1,97 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + */ +package org.netbeans.modules.php.dbgp.ui; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.beans.Customizer; +import javax.swing.JPanel; +import org.netbeans.modules.php.dbgp.breakpoints.LineBreakpoint; +import org.netbeans.spi.debugger.ui.Controller; +import org.openide.util.NbBundle; + +public class DbgpLineBreakpointCustomizer extends JPanel implements Customizer, Controller { + + private static final long serialVersionUID = 3626744241527549679L; + + private LineBreakpoint b; + private DbgpLineBreakpointCustomizerPanel c; + + public DbgpLineBreakpointCustomizer() { + } + + @NbBundle.Messages("ACSD_Breakpoint_Customizer_Dialog=Customize this breakpoint's properties") + public static DbgpLineBreakpointCustomizerPanel getCustomizerComponent(LineBreakpoint lineBreakpoint) { + DbgpLineBreakpointCustomizerPanel panel; + panel = new DbgpLineBreakpointCustomizerPanel(lineBreakpoint); + panel.getAccessibleContext().setAccessibleDescription(Bundle.ACSD_Breakpoint_Customizer_Dialog()); + return panel; + } + + @Override + public void setObject(Object bean) { + if (!(bean instanceof LineBreakpoint)) { + throw new IllegalArgumentException(bean.toString()); + } + this.b = (LineBreakpoint) bean; + init(b); + } + + private void init(LineBreakpoint b) { + c = getCustomizerComponent(b); + setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.BOTH; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + add(c, gbc); + } + + @Override + public boolean ok() { + return c.getController().ok(); + } + + @Override + public boolean cancel() { + return c.getController().cancel(); + } + +} diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizerPanel.form b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizerPanel.form new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizerPanel.form @@ -0,0 +1,170 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizerPanel.java b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizerPanel.java new file mode 100644 --- /dev/null +++ b/php.dbgp/src/org/netbeans/modules/php/dbgp/ui/DbgpLineBreakpointCustomizerPanel.java @@ -0,0 +1,466 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + */ +package org.netbeans.modules.php.dbgp.ui; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import org.netbeans.api.debugger.DebuggerManager; +import org.netbeans.api.debugger.Properties; +import org.netbeans.modules.php.dbgp.breakpoints.LineBreakpoint; +import org.netbeans.modules.php.dbgp.breakpoints.Utils; +import org.netbeans.spi.debugger.ui.Controller; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.text.Line; +import org.openide.util.NbBundle; + +public class DbgpLineBreakpointCustomizerPanel extends JPanel implements ControllerProvider { + + private static final int MAX_SAVED_CONDITIONS = 10; + private static final String BP_CONDITIONS = "BPConditions"; // NOI18N + private static final String DEBUGGER_PHP = "debugger.php"; // NOI18N + private static final long serialVersionUID = 6364512868561614302L; + + private final LineBreakpoint lineBreakpoint; + private final Controller controller; + private boolean createBreakpoint; + + private static LineBreakpoint createLineBreakpoint() { + Line currentLine = Utils.getCurrentLine(); + return createLineBreakpoint(currentLine); + } + + private static LineBreakpoint createLineBreakpoint(Line line) { + if (line != null) { + return new LineBreakpoint(line); + } + return null; + } + + public DbgpLineBreakpointCustomizerPanel() { + this(createLineBreakpoint(), true); + createBreakpoint = true; + } + + public DbgpLineBreakpointCustomizerPanel(Line line) { + this(createLineBreakpoint(line), true); + createBreakpoint = true; + } + + public DbgpLineBreakpointCustomizerPanel(LineBreakpoint lineBreakpoint) { + this(lineBreakpoint, false); + } + + private DbgpLineBreakpointCustomizerPanel(LineBreakpoint lineBreakpoint, boolean isEditable) { + this.lineBreakpoint = lineBreakpoint; + controller = createController(); + initComponents(); + + DocumentListener defaultDocumentListener = new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + processUpdate(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + processUpdate(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + processUpdate(); + } + + private void processUpdate() { + ((CustomizerController) controller).firePropertyChange(); + } + }; + fileTextField.setEditable(isEditable); + fileTextField.getDocument().addDocumentListener(defaultDocumentListener); + lineNumberTextField.setEditable(isEditable); + lineNumberTextField.getDocument().addDocumentListener(defaultDocumentListener); + Object[] conditions = getSavedConditions(); + conditionComboBox.setModel(new DefaultComboBoxModel(conditions)); + + if (lineBreakpoint != null) { + Line line = lineBreakpoint.getLine(); + FileObject fo = line.getLookup().lookup(FileObject.class); + updateComponents(fo, line.getLineNumber() + 1, lineBreakpoint.getCondition()); + } + } + + private void updateComponents(FileObject fileObject, int lineNumber, String condition) { + assert SwingUtilities.isEventDispatchThread(); + if (fileObject != null) { + File file = FileUtil.toFile(fileObject); + if (file != null) { + fileTextField.setText(file.getAbsolutePath()); + } else { + fileTextField.setText(fileObject.toURL().toExternalForm()); + } + } + + lineNumberTextField.setText(Integer.toString(lineNumber)); + + if (condition != null && !condition.isEmpty()) { + conditionCheckBox.setSelected(true); + conditionComboBox.setEnabled(true); + conditionComboBox.getEditor().setItem(condition); + } else { + conditionCheckBox.setSelected(false); + conditionComboBox.setEnabled(false); + } + } + + private static Object[] getSavedConditions() { + return Properties.getDefault() + .getProperties(DEBUGGER_PHP) + .getArray(BP_CONDITIONS, new Object[0]); + } + + private static void saveCondition(String condition) { + Object[] savedConditions = getSavedConditions(); + Object[] conditions = null; + boolean containsCondition = false; + for (int i = 0; i < savedConditions.length; i++) { + Object c = savedConditions[i]; + if (condition.equals(c)) { + containsCondition = true; + conditions = savedConditions; + if (i > 0) { + System.arraycopy(conditions, 0, conditions, 1, i); + conditions[0] = condition; + } + break; + } + } + if (!containsCondition) { + if (savedConditions.length < MAX_SAVED_CONDITIONS) { + conditions = new Object[savedConditions.length + 1]; + conditions[0] = condition; + System.arraycopy(savedConditions, 0, conditions, 1, savedConditions.length); + } else { + conditions = savedConditions; + System.arraycopy(conditions, 0, conditions, 1, conditions.length - 1); + conditions[0] = condition; + } + } + Properties.getDefault() + .getProperties(DEBUGGER_PHP) + .setArray(BP_CONDITIONS, conditions); + } + + private Controller createController() { + return new CustomizerController(); + } + + @Override + public Controller getController() { + return controller; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + settingsPanel = new javax.swing.JPanel(); + fileLabel = new javax.swing.JLabel(); + lineNumberLabel = new javax.swing.JLabel(); + fileTextField = new javax.swing.JTextField(); + lineNumberTextField = new javax.swing.JTextField(); + conditionPanel = new javax.swing.JPanel(); + conditionCheckBox = new javax.swing.JCheckBox(); + conditionComboBox = new javax.swing.JComboBox<>(); + + settingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "LBL_Settings"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(fileLabel, org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "DbgpLineBreakpointCustomizerPanel.fileLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(lineNumberLabel, org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "DbgpLineBreakpointCustomizerPanel.lineNumberLabel.text")); // NOI18N + + fileTextField.setText(org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "DbgpLineBreakpointCustomizerPanel.fileTextField.text")); // NOI18N + + lineNumberTextField.setText(org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "DbgpLineBreakpointCustomizerPanel.lineNumberTextField.text")); // NOI18N + + javax.swing.GroupLayout settingsPanelLayout = new javax.swing.GroupLayout(settingsPanel); + settingsPanel.setLayout(settingsPanelLayout); + settingsPanelLayout.setHorizontalGroup( + settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(settingsPanelLayout.createSequentialGroup() + .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lineNumberLabel) + .addComponent(fileLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(fileTextField) + .addComponent(lineNumberTextField))) + ); + settingsPanelLayout.setVerticalGroup( + settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(settingsPanelLayout.createSequentialGroup() + .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(fileLabel) + .addComponent(fileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(settingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lineNumberLabel) + .addComponent(lineNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + ); + + conditionPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "LBL_Condition"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(conditionCheckBox, org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "DbgpLineBreakpointCustomizerPanel.conditionCheckBox.text")); // NOI18N + conditionCheckBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + conditionCheckBoxActionPerformed(evt); + } + }); + + conditionComboBox.setEditable(true); + conditionComboBox.setToolTipText(org.openide.util.NbBundle.getMessage(DbgpLineBreakpointCustomizerPanel.class, "DbgpLineBreakpointCustomizerPanel.conditionComboBox.toolTipText")); // NOI18N + + javax.swing.GroupLayout conditionPanelLayout = new javax.swing.GroupLayout(conditionPanel); + conditionPanel.setLayout(conditionPanelLayout); + conditionPanelLayout.setHorizontalGroup( + conditionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(conditionPanelLayout.createSequentialGroup() + .addComponent(conditionCheckBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(conditionComboBox, 0, 281, Short.MAX_VALUE)) + ); + conditionPanelLayout.setVerticalGroup( + conditionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(conditionPanelLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(conditionPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(conditionCheckBox) + .addComponent(conditionComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(settingsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(conditionPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(settingsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(conditionPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void conditionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_conditionCheckBoxActionPerformed + conditionComboBox.setEnabled(conditionCheckBox.isSelected()); + if (conditionCheckBox.isSelected()) { + conditionComboBox.requestFocusInWindow(); + } + }//GEN-LAST:event_conditionCheckBoxActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox conditionCheckBox; + private javax.swing.JComboBox conditionComboBox; + private javax.swing.JPanel conditionPanel; + private javax.swing.JLabel fileLabel; + private javax.swing.JTextField fileTextField; + private javax.swing.JLabel lineNumberLabel; + private javax.swing.JTextField lineNumberTextField; + private javax.swing.JPanel settingsPanel; + // End of variables declaration//GEN-END:variables + + //~ Inner classes + private class CustomizerController implements Controller { + + private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); + private String errorMessage; + + @Override + public boolean ok() { + if (!isValid()) { + final String message = getErrorMessage(); + if (message != null) { + if (SwingUtilities.isEventDispatchThread()) { + showMessageDialog(message); + } else { + SwingUtilities.invokeLater(() -> { + showMessageDialog(message); + }); + } + } + return false; + } + + String condition = null; + if (conditionCheckBox.isSelected()) { + condition = conditionComboBox.getSelectedItem().toString().trim(); + } + + if (createBreakpoint) { + String fileName = fileTextField.getText(); + String lineNumberString = lineNumberTextField.getText(); + if (fileName == null) { + return false; + } + File file = new File(fileName.trim()); + FileObject fileObject = FileUtil.toFileObject(file); + if (fileObject == null) { + return false; + } + Line line = Utils.getLine(fileObject, Integer.parseInt(lineNumberString) - 1); + LineBreakpoint lb = createLineBreakpoint(line); + setCondition(lb, condition); + DebuggerManager.getDebuggerManager().addBreakpoint(lb); + } else { + setCondition(lineBreakpoint, condition); + } + + return true; + } + + private void setCondition(LineBreakpoint lb, String condition) { + if (condition != null && !condition.isEmpty()) { + lb.setCondition(condition); + saveCondition(condition); + } else { + lb.setCondition(null); + } + } + + @Override + public boolean cancel() { + return true; + } + + @NbBundle.Messages({ + "CustomizerController.invalid.file=Existing file must be set.", + "CustomizerController.invalid.line=Valid line number must be set." + }) + @Override + public boolean isValid() { + boolean isValid = true; + // file + String fileName = fileTextField.getText(); + if (fileName == null || fileName.trim().length() == 0) { + setErrorMessage(Bundle.CustomizerController_invalid_file()); + return false; + } + File file = new File(fileName.trim()); + if (!file.exists()) { + setErrorMessage(Bundle.CustomizerController_invalid_file()); + return false; + } + FileObject fileObject = FileUtil.toFileObject(file); + if (fileObject == null) { + setErrorMessage(Bundle.CustomizerController_invalid_file()); + return false; + } + + // line number + String lineNumberString = lineNumberTextField.getText(); + if (lineNumberString == null || lineNumberString.trim().length() == 0) { + setErrorMessage(Bundle.CustomizerController_invalid_line()); + return false; + } + try { + int lineNumber = Integer.parseInt(lineNumberTextField.getText()); + if (lineNumber <= 0) { + setErrorMessage(Bundle.CustomizerController_invalid_line()); + return false; + } + } catch (NumberFormatException nfe) { + setErrorMessage(Bundle.CustomizerController_invalid_line()); + isValid = false; + } + + if (isValid) { + setErrorMessage(null); + } + return isValid; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener l) { + propertyChangeSupport.addPropertyChangeListener(l); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener l) { + propertyChangeSupport.removePropertyChangeListener(l); + } + + void firePropertyChange() { + propertyChangeSupport.firePropertyChange(Controller.PROP_VALID, null, null); + } + + void setErrorMessage(String message) { + errorMessage = message; + propertyChangeSupport.firePropertyChange(NotifyDescriptor.PROP_ERROR_NOTIFICATION, null, message); + } + + String getErrorMessage() { + return errorMessage; + } + + private void showMessageDialog(String message) { + NotifyDescriptor descr = new NotifyDescriptor.Message(message); + DialogDisplayer.getDefault().notify(descr); + } + + } + +}