xref: /haiku/src/apps/webpositive/ConsoleWindow.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2014-2023 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Zhuowei Zhang
7  *		Humdinger
8  */
9 #include "ConsoleWindow.h"
10 
11 #include <Catalog.h>
12 #include <Clipboard.h>
13 #include <Message.h>
14 #include <Button.h>
15 #include <GroupLayout.h>
16 #include <GroupLayoutBuilder.h>
17 #include <LayoutBuilder.h>
18 #include <SeparatorView.h>
19 #include <StringFormat.h>
20 #include <TextControl.h>
21 #include <ListView.h>
22 #include <ScrollView.h>
23 
24 #include "BrowserWindow.h"
25 #include "BrowserApp.h"
26 #include "WebViewConstants.h"
27 
28 
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "Console Window"
31 
32 
33 enum {
34 	EVAL_CONSOLE_WINDOW_COMMAND = 'ecwc',
35 	CLEAR_CONSOLE_MESSAGES = 'ccms'
36 };
37 
38 
39 ConsoleWindow::ConsoleWindow(BRect frame)
40 	:
41 	BWindow(frame, B_TRANSLATE("Script console"), B_TITLED_WINDOW,
42 		B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS
43 			| B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
44 	fPreviousText(""),
45 	fRepeatCounter(0)
46 {
47 	SetLayout(new BGroupLayout(B_VERTICAL, 0.0));
48 
49 	fMessagesListView = new BListView("Console messages",
50 		B_MULTIPLE_SELECTION_LIST);
51 
52 	fClearMessagesButton = new BButton(B_TRANSLATE("Clear"),
53 		new BMessage(CLEAR_CONSOLE_MESSAGES));
54 	fCopyMessagesButton = new BButton(B_TRANSLATE("Copy"),
55 		new BMessage(B_COPY));
56 
57 	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
58 		.Add(new BScrollView("Console messages scroll",
59 			fMessagesListView, 0, true, true))
60 		.Add(BGroupLayoutBuilder(B_HORIZONTAL, B_USE_SMALL_SPACING)
61 			.AddGlue()
62 			.Add(fClearMessagesButton)
63 			.Add(fCopyMessagesButton)
64 			.AddGlue()
65 			.SetInsets(0, B_USE_SMALL_SPACING, 0, 0))
66 		.SetInsets(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING,
67 			B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
68 	);
69 	if (!frame.IsValid())
70 		CenterOnScreen();
71 }
72 
73 
74 void
75 ConsoleWindow::MessageReceived(BMessage* message)
76 {
77 	switch (message->what) {
78 		case ADD_CONSOLE_MESSAGE:
79 		{
80 			BString source = message->FindString("source");
81 			int32 lineNumber = message->FindInt32("line");
82 			int32 columnNumber = message->FindInt32("column");
83 			BString text = message->FindString("string");
84 			BString finalText;
85 			finalText.SetToFormat("%s:%" B_PRIi32 ":%" B_PRIi32 ": %s\n",
86 				source.String(), lineNumber, columnNumber, text.String());
87 
88 			if (finalText == fPreviousText) {
89 				finalText = "";
90 				static BStringFormat format(B_TRANSLATE("{0, plural,"
91 					"one{Last line repeated # time.}"
92 					"other{Last line repeated # times.}}"));
93 				format.Format(finalText, ++fRepeatCounter);
94 				// preserve the repeated line
95 				if (fRepeatCounter > 1) {
96 					int32 index = fMessagesListView->CountItems() - 1;
97 					BStringItem* item = (BStringItem*)fMessagesListView->ItemAt(index);
98 					item->SetText(finalText.String());
99 					fMessagesListView->InvalidateItem(index);
100 					break;
101 				}
102 			} else {
103 				fPreviousText = finalText;
104 				fRepeatCounter = 0;
105 			}
106 			fMessagesListView->AddItem(new BStringItem(finalText.String()));
107 			break;
108 		}
109 		case CLEAR_CONSOLE_MESSAGES:
110 		{
111 			fPreviousText = "";
112 			int count = fMessagesListView->CountItems();
113 			for (int i = count - 1; i >= 0; i--)
114 				delete fMessagesListView->RemoveItem(i);
115 			break;
116 		}
117 		case B_COPY:
118 		{
119 			_CopyToClipboard();
120 			break;
121 		}
122 		default:
123 			BWindow::MessageReceived(message);
124 			break;
125 	}
126 }
127 
128 
129 bool
130 ConsoleWindow::QuitRequested()
131 {
132 	if (!IsHidden())
133 		Hide();
134 	return false;
135 }
136 
137 
138 void
139 ConsoleWindow::_CopyToClipboard()
140 {
141 	BString text;
142 	int32 index;
143 	if (fMessagesListView->CurrentSelection() == -1) {
144 		for (int32 i = 0; i < fMessagesListView->CountItems(); i++) {
145 			BStringItem* item = (BStringItem*)fMessagesListView->ItemAt(i);
146 			text << item->Text();
147 		}
148 	} else {
149 		for (int32 i = 0; (index = fMessagesListView->CurrentSelection(i)) >= 0; i++) {
150 			BStringItem* item = (BStringItem*)fMessagesListView->ItemAt(index);
151 			text << item->Text();
152 		}
153 	}
154 
155 	ssize_t textLen = text.Length();
156 	if (be_clipboard->Lock()) {
157 		be_clipboard->Clear();
158 		BMessage* clip = be_clipboard->Data();
159 		if (clip != NULL) {
160 			clip->AddData("text/plain", B_MIME_TYPE, text.String(), textLen);
161 			be_clipboard->Commit();
162 		}
163 		be_clipboard->Unlock();
164 	}
165 }
166