Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hot UI implementation #4160

Merged
merged 2 commits into from
Dec 4, 2019
Merged

Conversation

jacob314
Copy link
Contributor

@jacob314 jacob314 commented Dec 3, 2019

If I had more time I would have written less code.
I've commented on files that are not-enabled in the checked in code and files that are simple refactors of existing code to improve reuse.
High level: support in the outline view is exposed by this CL. Support directly in the code editor is protected by a flag in FlutterSettings that is hard coded to false to reduce the risk of a memory leak or performance regression.

Screenshots:
Setting to enable Hot Ui. Happy to hear suggestions for a better name for this setting. We could also call it Hot UI.
Screen Shot 2019-12-02 at 6 32 14 PM

Screen Shot 2019-12-02 at 6 33 33 PM

Screenshot showing what it looks like before the app is run.
A reasonable easy UI tweak would be to hide the screen mirror completely when the app is not running.
Screen Shot 2019-12-02 at 6 33 33 PM

Screenshot showing when the app is running
Screen Shot 2019-12-02 at 6 56 11 PM

Screenshot showing what happens when an outline node that isn't a simple NEW_INSTANCE outline node is selected.
Screen Shot 2019-12-02 at 7 09 51 PM

Proof that Hot UI is disabled by default with no changes to the outline view or code editor.
Screen Shot 2019-12-02 at 6 27 54 PM

@@ -0,0 +1,398 @@
/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class isn't executed in the checked in code for now as showing previews directly in the code editor is disabled to avoid risking memory leaks or rendering performance issues on slow machines.

@@ -0,0 +1,37 @@
/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is also disabled behind a non-user configurable flag in the checked in code.

private final int offset;
private final int endOffset;
@Nullable
class TextRangeTracker {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helper class was extracted out as we now want to track two text ranges per outline location. One to render the ui guides and one that tracks the entire body of the outline node that is used for the inline widget previews.

@@ -0,0 +1,152 @@
/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class isn't enabled in the actual running application as the inline widget previews are disabled without an experimental flag to enable them as described earlier.

* Copyright 2019 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a refactor of existing code that was directly in the OutlineView class.

@@ -84,35 +81,30 @@
@NotNull
private final FlutterDartAnalysisServer flutterAnalysisServer;

final QuickAssistAction actionCenter;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this code for assists is still around it just got moved into a separate toolbar class for reuse across multiple locations.
The reuse across multiple locations isn't actually used in the enabled code so I could go through and pull out that refactor from this CL but the refactor seems reasonable and should be useful in the future showing widget refactors directly in the code editor when the outline view is not enabled.


private boolean isSettingSplitterProportion = false;
private Splitter splitter;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This CL was based on re-applying the existing PreviewArea code from the OutlineView which was reverted earlier in the year. For example, PreviewArea should sound familiar.


private final Set<FlutterOutline> outlinesWithWidgets = Sets.newHashSet();
private final Map<FlutterOutline, DefaultMutableTreeNode> outlineToNodeMap = Maps.newHashMap();

private VirtualFile currentFile;
private final EventStream<VirtualFile> currentFile;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

state that needs to be shared with subviews is moved into EventStream classes for easy listening.


private final WidgetEditToolbar widgetEditToolbar;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is where all the toolbar logic went.

final ActionManager actionManager = ActionManager.getInstance();
final ActionPopupMenu popupMenu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group);
popupMenu.getComponent().show(comp, x, y);
widgetEditToolbar.createPopupMenu(comp, x, y);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The popup menu is displayed identically as before, this code has just moved to the toolbar class.

}
finally {
currentEditor.getCaretModel().addCaretListener(caretListener);
}
}
}

private void updateActionsForOutlines(List<FlutterOutline> outlines) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to toolbar class.

@@ -548,45 +501,13 @@ private FlutterOutline getOutlineOfPath(@Nullable TreePath path) {
return getOutlineOfNode(node);
}

private int getConvertedFileOffset(int offset) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these outline location helpers were moved to the outline coverter helper class as they were needed a bunch of places.

@@ -8,6 +8,7 @@
import com.intellij.util.EventDispatcher;
import com.intellij.util.xmlb.annotations.Attribute;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the changes to this file are from re-applying the reverted PreviewArea CL.

*/
package io.flutter.preview;

import com.google.common.util.concurrent.Uninterruptibles;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a simple refactor of the toolbar code from the PreviewView into its own class.
No functionality was added or changed. The one difference is EventStream objects are used to ensure this class is reliably notified on changes to the selected outline and selected file.

@@ -249,6 +249,15 @@
<toolTipText value="Provides advanced editing capabilities for Java and Kotlin code. Uses Gradle to find Android libraries then links them into the Flutter project."/>
</properties>
</component>
<component id="33088" class="javax.swing.JCheckBox" binding="myEnableHotUiCheckBox">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could also add a checkbox to enable previews in the code editor but that is more risky as described elsewhere.

Copy link
Contributor Author

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevemessick do you have any tips on where I need to put code that works in IntelliJ but not Android Studio? I need to have separate AndroidStudio and IntelliJ implementations of the color picker. For now I just skip on IntelliJ as I can't figure out the spot in the code base to put classes that will compile under IntelliJ but not android studio.
Here's my android studio specific version.
https://github.com/flutter/flutter-intellij/pull/4160/files#diff-be782206a290e2b3713047e010c87ff8

I'd like to provide an IntelliJ version here but it seems like Android Studio has stripped out the IntelliJ ColorPicker classes replacing them with very similar and slightly improved versions so I get compile errors on "bin/plugin build" when building the android studio version.
https://github.com/flutter/flutter-intellij/pull/4160/files#diff-3974bfa36da17f0302b990dff03077fc

@jacob314
Copy link
Contributor Author

jacob314 commented Dec 3, 2019

Screen Shot 2019-12-03 at 12 01 45 AM

Screenshot of the color picker on android studio.

// component but for some reason it throws exceptions even though there
// are examples of it being used identically without throwing exceptions
// elsewhere in the IntelliJ code base.
.addSaturationBrightnessComponent()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on your comment, should this be commented out then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this comment. It is copy pasta from my late night port of this code to use the AndroidStudio specific classes. The AndroidStudio version doesn't have the same bug.

@@ -216,6 +216,7 @@ shout.level.title=Shout
settings.try.out.features.still.under.development=Try out features still under development (a restart may be required)
settings.experimental.flutter.logging.view=Replace the Run and Debug console output with a custom Flutter Logging view
settings.enable.android.gradle.sync=Enable code completion, navigation, etc. for Java / Kotlin (requires restart to do Gradle build)
settings.enable.hot.ui=Enable property editing in the outline view (some features require Flutter dev channel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "Enable Hot UI editing in the outline view" to brand the Hot UI name? Or "Enable Hot UI - property editing in the outline view"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about
"Enable Hot UI -- early preview of property editing in the outline view"
?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm

src/io/flutter/editor/FlutterEditorColors.java Outdated Show resolved Hide resolved

final List<FlutterOutline> children = outlineNode.getChildren();
if (children == null || children.isEmpty()) return;
// if (children == null || children.isEmpty()) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this line be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that optimization can be added back. history is there is a separate block of work to render previews of property values inline split off from this cl.

src/io/flutter/editor/WidgetIndentsHighlightingPass.java Outdated Show resolved Hide resolved
src/io/flutter/preview/PreviewArea.java Outdated Show resolved Hide resolved
/**
* Class that provides the glue to render the preview view in a regular JPanel.
*/
public class PreviewViewModelPanel extends JPanel {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here: rename class, fields, comments to use DeviceMirror instead of PreviewView

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added this to #4162

src/io/flutter/preview/PreviewViewModelPanel.java Outdated Show resolved Hide resolved
});
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps add a comment here and for mouseDragged explaining why these methods are overridden and left empty

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

final int endOffset = Math.min(startOffset + location.getLength(), docLength);

marker = document.createRangeMarker(startOffset, endOffset);
// nodeStartingWord = OutlineLocation.getCurrentWord(document, nameExpression);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed. the helper class for tracking a location now has that functionality.


void showColorFieldPopup() {
disposeColorPicker();
colorPicker = ColorPickerFactory.create();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe assert(colorPicker == null) before create?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// The color picker is currently only supported in the AndroidStudio version of the plugin.
// TODO(jacobr): show a toast message explaining it is missing on IntelliJ for now.
if (colorPicker != null) {
colorAtPopupLaunch = currentColor;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can currentColor be passed to the show? and reset when colorPicker is disposed? Since colorPicker is created each time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is a bug. fixed to pass in currentColor.


public void createPopupMenu(Component comp, int x, int y) {
// The corresponding tree item may have just been selected.
// Wait short time for receiving assists from the server.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this existing code? We wait up to 100ms in 5ms increments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. This is completely unchanged from the existing code and example of why we need to do a real audit of all the times we are locking the UI thread from the IntelliJ plugin.
Good news is this case is only triggered on right click in the outline view so it won't cause UI hangs any other times.

// the action has just been canceled.
return;
}
// TODO(jacobr): how recently was this implemented?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DAS was updated in https://dart-review.googlesource.com/c/sdk/+/41520/
Look for the history of DartServerExtractMethodHandler in IntelliJ, somehow I cannot do it locally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that analysis server change landed Feb 14, 2018.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. I've addressed the TODO and verified it still works. Not much changes as IntelliJ just selects the whole block anyway so this is what the user sees.
image

screenshotBounds = new Rectangle(lastScreenshotBoundsWindow);
screenshotBounds.translate(visibleRect.x, visibleRect.y);
} else {
boolean lockUpdate =false;
Copy link
Contributor

@terrylucas terrylucas Dec 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: need space?
boolean lockUpdate = false;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed. ran the formatter on this file.

}

@Override
TextRange getActiveRange() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume null return is okay?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is. annotated the base class method as @nullable to get warnings.

forceRender();
}

// @Override
Copy link
Contributor

@terrylucas terrylucas Dec 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really override or just some comment to be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the comment. The method still applies but is no longer specified by an interface.

Copy link
Contributor

@terrylucas terrylucas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestions and questions.

@stevemessick stevemessick mentioned this pull request Dec 3, 2019
@jacob314
Copy link
Contributor Author

jacob314 commented Dec 3, 2019

Done with the first round of review comments. PTAL.
Separately, I'm following Steve's offline suggestion to use extension_points to cleanup the android only code dependency.

import java.awt.*;
import javax.swing.*;

public class ColorPickerAndroidStudio implements GenericColorPicker {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chatted about using a new extension point to create different color picker instances depending on whether the flutter-studio module was loaded.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

assert(colorPicker == null);
colorPicker = ColorPickerFactory.create();
// The color picker is currently only supported in the AndroidStudio version of the plugin.
// TODO(jacobr): show a toast message explaining it is missing on IntelliJ for now.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully this TODO can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

static GenericColorPicker create() {
// TODO(jacobr): provide an implementation of GenericColorPicker that works
// in IntelliJ. com.intellij.ui.colorpicker.ColorPickerBuilder would work
// if we could figure out how to make it work with bin/plugin build.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we modify the plugin tool to edit code during the build to handle compile problems. We could use git branches but for the small amount of changes we need to make that is more trouble than it's worth.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to expand the way it was modifying code a little to make it work as otherwise I get exceptions. see the stub placeholder file added.

* The regular IntelliJ color picker implementation can't be used on Android
* Studio and vice versa.
*/
public interface GenericColorPicker {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See src/io/flutter/android/GradleSyncProvider.java for an example of defining an extension point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// Don't want to render on the wrong editor. This shouldn't happen.
return;
}
if (getEditor().isPurePaintingMode()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can getEditor() return a different value here? If not, just use editor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value should never change. However, the rest of the code will assume getEditor() versus passing in the editor to the paint call so I think using getEditor() everywhere is reasonable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This weird api is due to supporting RangeHighlighter where the editor is typically passed in rather than tightly coupled to the object as it is in this case.

}

@Override
public void dispose() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expected to see
isDisposed = true;

isDisposed is initialized but apparently never set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so much cruft form all the prototyping that went into this. I've removed isDisposed.
In general the code now follows the IntelliJ best practice of managing disposables by passing in the parent Disposable object wherever possible and not manually call dispose() directly as that leads to bugs.

@jacob314
Copy link
Contributor Author

jacob314 commented Dec 4, 2019

PTAL. All comments so far are addressed.

@stevemessick
Copy link
Member

I'm looking now. I'll focus on the multi-IDE support and build changes. I'll let others cover things they are more familiar with.

Copy link
Member

@stevemessick stevemessick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a few nits, which can be corrected in a follow-up PR. Going to finish this review to see if having a pending review is confusing the patch generator. Still working on more substantive review.

@@ -1029,10 +1029,19 @@
<extensionPoint name="gradleSyncProvider" interface="io.flutter.android.GradleSyncProvider"/>
</extensionPoints>

<extensionPoints>
<extensionPoint name="colorPickerProvider" interface="io.flutter.editor.ColorPickerProvider"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should only have one <extensionPoints> tag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doh. done

<extensions defaultExtensionNs="io.flutter">
<gradleSyncProvider implementation="io.flutter.android.IntellijGradleSyncProvider" order="last"/>
</extensions>

<extensions defaultExtensionNs="io.flutter">
<colorPickerProvider implementation="io.flutter.editor.IntellijColorPickerProvider" order="last"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, this tag can be combined with the other <extensions> for io.flutter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -211,10 +211,19 @@
<extensionPoint name="gradleSyncProvider" interface="io.flutter.android.GradleSyncProvider"/>
</extensionPoints>

<extensionPoints>
<extensionPoint name="colorPickerProvider" interface="io.flutter.editor.ColorPickerProvider"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments I made on plugin.xml actually belong here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@@ -16,6 +16,10 @@
<gradleSyncProvider implementation="io.flutter.android.AndroidStudioGradleSyncProvider" order="first"/>
</extensions>

<extensions defaultExtensionNs="io.flutter">
<colorPickerProvider implementation="io.flutter.editor.AndroidStudioColorPickerProvider" order="first"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like with plugin.xml, combine the blocks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -14,6 +14,10 @@
<gradleSyncProvider implementation="io.flutter.android.AndroidStudioGradleSyncProvider" order="first"/>
</extensions>

<extensions defaultExtensionNs="io.flutter">
<colorPickerProvider implementation="io.flutter.editor.AndroidStudioColorPickerProvider" order="first"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine this one with previous, too.

disposeColorPicker();
assert (colorPicker == null);
colorPicker = ColorPickerProvider.EP_NAME.getExtensionList().get(0);
;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra semicolon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member

@kenzieschmoll kenzieschmoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a few nits

Comment on lines 512 to 514
/*if (expression == null || expression.isEmpty()) {
continue;
}*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be either uncommented or removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed.

public int getEndOffset() {
if (marker == null) {
final Location location = attribute.getValueLocation();
final int startOffset = attribute.getValueLocation().getOffset();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use location.getOffset() here since you already have attribute.getValueLocation() stored

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// to the column of the actual entity.
final int docLength = document.getTextLength();
final Location location = attribute.getValueLocation();
final int startOffset = Math.min(attribute.getValueLocation().getOffset(), docLength);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

path.add(outline);
if (converter.getConvertedOutlineOffset(outline) <= offset && offset <= converter.getConvertedOutlineEnd(outline)) {
if (outline.getChildren() != null) {
for (FlutterOutline child : outline.getChildren()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: pull outline.getChildren() out into its own variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@jacob314 jacob314 merged commit 525eca5 into flutter:master Dec 4, 2019
@jacob314 jacob314 deleted the hot_ui_implementation branch December 4, 2019 18:47
alexander-doroshko pushed a commit to alexander-doroshko/flutter-intellij that referenced this pull request Jan 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants