@@ -10,8 +10,8 @@ import com.intellij.openapi.project.Project
1010import com.intellij.openapi.wm.ToolWindow
1111import com.intellij.openapi.wm.ToolWindowFactory
1212import com.intellij.openapi.wm.ex.ToolWindowEx
13- import com.intellij.ui.content.Content
14- import com.intellij.ui.content.ContentManager
13+ import com.intellij.ui.components.panels.Wrapper
14+ import com.intellij.util. ui.components.BorderLayoutPanel
1515import software.aws.toolkits.core.utils.debug
1616import software.aws.toolkits.core.utils.getLogger
1717import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
@@ -22,20 +22,31 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
2222import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES
2323import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState
2424import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProviderListener
25+ import software.aws.toolkits.jetbrains.core.notifications.NotificationFollowupActions
26+ import software.aws.toolkits.jetbrains.core.notifications.ShowCriticalNotificationBannerListener
27+ import software.aws.toolkits.jetbrains.core.notifications.getBannerActionList
2528import software.aws.toolkits.jetbrains.core.webview.BrowserState
2629import software.aws.toolkits.jetbrains.services.amazonq.QWebviewPanel
2730import software.aws.toolkits.jetbrains.services.amazonq.RefreshQChatPanelButtonPressedListener
2831import software.aws.toolkits.jetbrains.services.amazonq.gettingstarted.openMeetQPage
2932import software.aws.toolkits.jetbrains.utils.isQConnected
3033import software.aws.toolkits.jetbrains.utils.isQExpired
3134import software.aws.toolkits.jetbrains.utils.isQWebviewsAvailable
35+ import software.aws.toolkits.jetbrains.utils.notifyInfo
3236import software.aws.toolkits.resources.message
3337import software.aws.toolkits.telemetry.FeatureId
3438import java.awt.event.ComponentAdapter
3539import java.awt.event.ComponentEvent
40+ import javax.swing.JComponent
3641
3742class AmazonQToolWindowFactory : ToolWindowFactory , DumbAware {
43+ private val notificationPanel = NotificationPanel ()
44+ private val qPanel = QPanel ()
3845 override fun createToolWindowContent (project : Project , toolWindow : ToolWindow ) {
46+ val mainPanel = BorderLayoutPanel ()
47+ mainPanel.addToTop(notificationPanel)
48+ mainPanel.add(qPanel)
49+
3950 if (toolWindow is ToolWindowEx ) {
4051 val actionManager = ActionManager .getInstance()
4152 toolWindow.setTitleActions(listOf (actionManager.getAction(" aws.q.toolwindow.titleBar" )))
@@ -46,7 +57,7 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
4657 ToolkitConnectionManagerListener .TOPIC ,
4758 object : ToolkitConnectionManagerListener {
4859 override fun activeConnectionChanged (newConnection : ToolkitConnection ? ) {
49- onConnectionChanged(project, newConnection, toolWindow )
60+ onConnectionChanged(project, newConnection)
5061 }
5162 }
5263 )
@@ -56,55 +67,62 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
5667 object : RefreshQChatPanelButtonPressedListener {
5768 override fun onRefresh () {
5869 runInEdt {
59- contentManager.removeAllContents(true )
60- prepareChatContent(project, contentManager)
70+ prepareChatContent(project)
6171 }
6272 }
6373 }
6474 )
6575
76+ project.messageBus.connect().subscribe(
77+ ShowCriticalNotificationBannerListener .TOPIC ,
78+ object : ShowCriticalNotificationBannerListener {
79+ override fun onReceiveEmergencyNotification (title : String , message : String , actions : List <NotificationFollowupActions >? ) {
80+ notificationPanel.updateNotificationPanel(title, message, actions)
81+ }
82+ }
83+ )
84+
6685 project.messageBus.connect().subscribe(
6786 BearerTokenProviderListener .TOPIC ,
6887 object : BearerTokenProviderListener {
6988 override fun onChange (providerId : String , newScopes : List <String >? ) {
7089 if (ToolkitConnectionManager .getInstance(project).connectionStateForFeature(QConnection .getInstance()) == BearerTokenAuthState .AUTHORIZED ) {
71- val content = contentManager.factory.createContent(AmazonQToolWindow .getInstance(project).component, null , false ).also {
90+ // change this
91+ val qComponent = AmazonQToolWindow .getInstance(project).component
92+
93+ val content = contentManager.factory.createContent(qComponent, null , false ).also {
7294 it.isCloseable = true
7395 it.isPinnable = true
7496 }
7597
7698 runInEdt {
77- contentManager.removeAllContents(true )
78- contentManager.addContent(content)
99+ qPanel.updateQPanel(qComponent)
79100 }
80101 }
81102 }
82103 }
83104 )
84105
85- val content = prepareChatContent(project, contentManager )
106+ prepareChatContent(project)
86107
108+ val content = contentManager.factory.createContent(mainPanel, null , false ).also {
109+ it.isCloseable = true
110+ it.isPinnable = true
111+ }
87112 toolWindow.activate(null )
88- contentManager.setSelectedContent (content)
113+ contentManager.addContent (content)
89114 }
90115
91116 private fun prepareChatContent (
92117 project : Project ,
93- contentManager : ContentManager ,
94- ): Content {
118+ ) {
95119 val component = if (isQConnected(project) && ! isQExpired(project)) {
96120 AmazonQToolWindow .getInstance(project).component
97121 } else {
98122 QWebviewPanel .getInstance(project).browser?.prepareBrowser(BrowserState (FeatureId .Q ))
99123 QWebviewPanel .getInstance(project).component
100124 }
101-
102- val content = contentManager.factory.createContent(component, null , false ).also {
103- it.isCloseable = true
104- it.isPinnable = true
105- }
106- contentManager.addContent(content)
107- return content
125+ qPanel.updateQPanel(component)
108126 }
109127
110128 override fun init (toolWindow : ToolWindow ) {
@@ -125,8 +143,7 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
125143
126144 override fun shouldBeAvailable (project : Project ): Boolean = isQWebviewsAvailable()
127145
128- private fun onConnectionChanged (project : Project , newConnection : ToolkitConnection ? , toolWindow : ToolWindow ) {
129- val contentManager = toolWindow.contentManager
146+ private fun onConnectionChanged (project : Project , newConnection : ToolkitConnection ? ) {
130147 val isNewConnectionForQ = newConnection?.let {
131148 (it as ? AwsBearerTokenConnection )?.let { conn ->
132149 val scopeShouldHave = Q_SCOPES
@@ -151,15 +168,8 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
151168 LOG .debug { " returning login window; no Q connection found" }
152169 QWebviewPanel .getInstance(project).component
153170 }
154-
155- val content = contentManager.factory.createContent(component, null , false ).also {
156- it.isCloseable = true
157- it.isPinnable = true
158- }
159-
160171 runInEdt {
161- contentManager.removeAllContents(true )
162- contentManager.addContent(content)
172+ qPanel.updateQPanel(component)
163173 }
164174 }
165175
@@ -169,3 +179,41 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
169179 private const val MINIMUM_TOOLWINDOW_WIDTH = 325
170180 }
171181}
182+
183+ class NotificationPanel : BorderLayoutPanel () {
184+ private val wrapper = Wrapper ()
185+ init {
186+ isOpaque = false
187+ addToCenter(wrapper)
188+ }
189+
190+ private fun removeNotificationPanel () = runInEdt {
191+ wrapper.removeAll()
192+ }
193+
194+ fun updateNotificationPanel (title : String , message : String , actions : List <NotificationFollowupActions >? ) {
195+ val editorNotificationPanel = getBannerActionList(actions, title, message)
196+
197+ editorNotificationPanel.createActionLabel(" Dismiss" ) {
198+ removeNotificationPanel()
199+ }
200+
201+ wrapper.setContent(editorNotificationPanel)
202+ }
203+ }
204+
205+ class QPanel : BorderLayoutPanel () {
206+ private val wrapper = Wrapper ()
207+ init {
208+ isOpaque = false
209+ addToCenter(wrapper)
210+ }
211+
212+ fun updateQPanel (content : JComponent ) {
213+ try {
214+ wrapper.setContent(content)
215+ } catch (e: Exception ) {
216+ notifyInfo(" Error while creating window" )
217+ }
218+ }
219+ }
0 commit comments