@@ -5,7 +5,6 @@ package software.aws.toolkits.jetbrains.services.codewhisperer.popup
5
5
6
6
import com.intellij.codeInsight.hint.ParameterInfoController
7
7
import com.intellij.codeInsight.lookup.LookupManager
8
- import com.intellij.codeInsight.lookup.LookupManagerListener
9
8
import com.intellij.idea.AppMode
10
9
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_ENTER
11
10
import com.intellij.openapi.actionSystem.IdeActions.ACTION_EDITOR_ESCAPE
@@ -26,8 +25,6 @@ import com.intellij.openapi.editor.event.CaretEvent
26
25
import com.intellij.openapi.editor.event.CaretListener
27
26
import com.intellij.openapi.editor.event.DocumentEvent
28
27
import com.intellij.openapi.editor.event.DocumentListener
29
- import com.intellij.openapi.editor.event.EditorMouseEvent
30
- import com.intellij.openapi.editor.event.EditorMouseMotionListener
31
28
import com.intellij.openapi.editor.event.SelectionEvent
32
29
import com.intellij.openapi.editor.event.SelectionListener
33
30
import com.intellij.openapi.fileEditor.FileEditorManager
@@ -65,10 +62,8 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.handlers.Cod
65
62
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererAcceptButtonActionListener
66
63
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererActionListener
67
64
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererNextButtonActionListener
68
- import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererPopupIntelliSenseAcceptListener
69
65
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererPrevButtonActionListener
70
66
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererScrollListener
71
- import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.addIntelliSenseAcceptListener
72
67
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
73
68
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
74
69
import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager
@@ -224,6 +219,7 @@ class CodeWhispererPopupManager {
224
219
fun render (
225
220
states : InvocationContext ,
226
221
sessionContext : SessionContext ,
222
+ overlappingLinesCount : Int ,
227
223
isRecommendationAdded : Boolean ,
228
224
) {
229
225
updatePopupPanel(states, sessionContext)
@@ -246,7 +242,7 @@ class CodeWhispererPopupManager {
246
242
states.requestContext.latencyContext.getPerceivedLatency(states.requestContext.triggerTypeInfo.triggerType)
247
243
}
248
244
if (! isRecommendationAdded) {
249
- showPopup(states, sessionContext, states.popup, visible = sessionContext.isPopupShowing )
245
+ showPopup(states, sessionContext, states.popup, overlappingLinesCount )
250
246
}
251
247
}
252
248
@@ -285,30 +281,28 @@ class CodeWhispererPopupManager {
285
281
states : InvocationContext ,
286
282
sessionContext : SessionContext ,
287
283
popup : JBPopup ,
288
- visible : Boolean = false ,
284
+ overlappingLinesCount : Int ,
289
285
) {
290
286
val caretPoint = states.requestContext.editor.offsetToXY(states.requestContext.caretPosition.offset)
291
287
val editor = states.requestContext.editor
292
288
val detailContexts = states.recommendationContext.details
293
289
val userInputOriginal = states.recommendationContext.userInputOriginal
290
+ val userInput = states.recommendationContext.userInputSinceInvocation
294
291
val selectedIndex = sessionContext.selectedIndex
295
292
val typeaheadOriginal = sessionContext.typeaheadOriginal
296
293
val typeahead = sessionContext.typeahead
297
294
val userInputLines = userInputOriginal.split(" \n " ).size - 1
295
+ val lineCount = getReformattedRecommendation(detailContexts[selectedIndex], userInput).split(" \n " ).size
298
296
val additionalLines = typeaheadOriginal.split(" \n " ).size - typeahead.split(" \n " ).size
299
297
val popupSize = (popup as AbstractPopup ).preferredContentSize
298
+ val yBelowLastLine = caretPoint.y + (lineCount + additionalLines + userInputLines - overlappingLinesCount) * editor.lineHeight
300
299
val yAboveFirstLine = caretPoint.y - popupSize.height + (additionalLines + userInputLines) * editor.lineHeight
301
300
val editorRect = editor.scrollingModel.visibleArea
302
- val popupRect = Rectangle (caretPoint.x, yAboveFirstLine , popupSize.width, popupSize.height)
301
+ var popupRect = Rectangle (caretPoint.x, yBelowLastLine , popupSize.width, popupSize.height)
303
302
var noEnoughSpaceForPopup = false
304
303
305
304
CodeWhispererInvocationStatus .getInstance().setDisplaySessionActive(true )
306
305
307
- if (! editorRect.contains(popupRect)) {
308
- // popup location above first line don't work, so don't show the popup
309
- noEnoughSpaceForPopup = true
310
- }
311
-
312
306
// Check if the current editor still has focus. If not, don't show the popup.
313
307
val isSameEditorAsTrigger = if (! AppMode .isRemoteDevHost()) {
314
308
editor.contentComponent.isFocusOwner
@@ -321,8 +315,25 @@ class CodeWhispererPopupManager {
321
315
return
322
316
}
323
317
324
- // popup to always display above the current editing line
325
- val popupLocation = Point (caretPoint.x, yAboveFirstLine)
318
+ val popupLocation =
319
+ if (! editorRect.contains(popupRect)) {
320
+ popupRect = Rectangle (caretPoint.x, yAboveFirstLine, popupSize.width, popupSize.height)
321
+ if (! editorRect.contains(popupRect)) {
322
+ // both popup location (below last line and above first line) don't work, so don't show the popup
323
+ noEnoughSpaceForPopup = true
324
+ }
325
+ LOG .debug {
326
+ " Show popup above the first line of recommendation. " +
327
+ " Editor position: $editorRect , popup position: $popupRect "
328
+ }
329
+ Point (caretPoint.x, yAboveFirstLine)
330
+ } else {
331
+ LOG .debug {
332
+ " Show popup below the last line of recommendation. " +
333
+ " Editor position: $editorRect , popup position: $popupRect "
334
+ }
335
+ Point (caretPoint.x, yBelowLastLine)
336
+ }
326
337
327
338
val relativePopupLocationToEditor = RelativePoint (editor.contentComponent, popupLocation)
328
339
@@ -335,12 +346,9 @@ class CodeWhispererPopupManager {
335
346
}
336
347
} else {
337
348
if (! AppMode .isRemoteDevHost()) {
338
- if (visible && ! noEnoughSpaceForPopup) {
339
- // TODO: will move to a keybinding listener once I found one
340
- popupComponents.prevButton.text = popupComponents.prevButtonText()
341
- popupComponents.nextButton.text = popupComponents.nextButtonText()
342
- popup.show(relativePopupLocationToEditor)
343
- }
349
+ popupComponents.prevButton.text = popupComponents.prevButtonText()
350
+ popupComponents.nextButton.text = popupComponents.nextButtonText()
351
+ popup.show(relativePopupLocationToEditor)
344
352
} else {
345
353
// TODO: For now, the popup will always display below the suggestions, without checking
346
354
// if the location the popup is about to show at stays in the editor window or not, due to
@@ -369,27 +377,14 @@ class CodeWhispererPopupManager {
369
377
}
370
378
}
371
379
372
- bringSuggestionInlayToFront(editor, popup, sessionContext, ! visible)
373
- }
374
-
375
- // opposite == false: show Q, hide IntelliSense
376
- // opposite == true: show IntelliSense, hide Q
377
- fun bringSuggestionInlayToFront (
378
- editor : Editor ,
379
- popup : JBPopup ? ,
380
- sessionContext : SessionContext ,
381
- opposite : Boolean = false,
382
- ) {
383
- val qInlinePopupAlpha = if (opposite) 1f else 0.1f
384
- val intelliSensePopupAlpha = if (opposite) 0f else 0.8f
385
-
386
- (popup as AbstractPopup ? )?.popupWindow?.let {
387
- WindowManager .getInstance().setAlphaModeRatio(it, qInlinePopupAlpha)
388
- }
389
- ComponentUtil .getWindow(LookupManager .getActiveLookup(editor)?.component)?.let {
390
- WindowManager .getInstance().setAlphaModeRatio(it, intelliSensePopupAlpha)
380
+ // popup.popupWindow is null in remote host
381
+ if (! AppMode .isRemoteDevHost()) {
382
+ if (noEnoughSpaceForPopup) {
383
+ WindowManager .getInstance().setAlphaModeRatio(popup.popupWindow, 1f )
384
+ } else {
385
+ WindowManager .getInstance().setAlphaModeRatio(popup.popupWindow, 0.1f )
386
+ }
391
387
}
392
- sessionContext.isPopupShowing = ! opposite
393
388
}
394
389
395
390
fun initPopup (): JBPopup = JBPopupFactory .getInstance()
@@ -458,13 +453,6 @@ class CodeWhispererPopupManager {
458
453
}
459
454
}
460
455
)
461
- states.requestContext.project.messageBus.connect(states).subscribe(
462
- LookupManagerListener .TOPIC ,
463
- CodeWhispererPopupIntelliSenseAcceptListener (states)
464
- )
465
- LookupManager .getActiveLookup(states.requestContext.editor)?.let {
466
- addIntelliSenseAcceptListener(it, states)
467
- }
468
456
}
469
457
470
458
private fun addButtonActionListeners (states : InvocationContext ) {
@@ -556,18 +544,6 @@ class CodeWhispererPopupManager {
556
544
window?.addComponentListener(windowListener)
557
545
Disposer .register(states) { window?.removeComponentListener(windowListener) }
558
546
}
559
-
560
- val suggestionHoverEnterListener: EditorMouseMotionListener = object : EditorMouseMotionListener {
561
- override fun mouseMoved (e : EditorMouseEvent ) {
562
- if (e.inlay != null ) {
563
- showPopup(states, sessionContext, states.popup, visible = true )
564
- } else {
565
- bringSuggestionInlayToFront(editor, states.popup, sessionContext, opposite = true )
566
- }
567
- super .mouseMoved(e)
568
- }
569
- }
570
- editor.addEditorMouseMotionListener(suggestionHoverEnterListener, states)
571
547
}
572
548
573
549
private fun updateSelectedRecommendationLabelText (validSelectedIndex : Int , validCount : Int ) {
0 commit comments