jcs
/wallops
/amendments
/40
chatter: Implement window resizing
Since our input field is taller than a scrollbar, we have to draw our
own grow icon that is a little taller.
jcs made amendment 40 about 1 year ago
--- chatter.c Wed Nov 30 23:20:30 2022
+++ chatter.c Thu Dec 1 21:49:35 2022
@@ -27,9 +27,12 @@
static Handle scrp_rec_h = NULL;
void chatter_layout(struct chatter *chatter, bool init, Rect *init_bounds);
+void chatter_draw_grow_icon(struct chatter *chatter);
+void chatter_autoscroll(struct chatter *chatter);
short chatter_wait_type(struct focusable *focusable);
void chatter_key_down(struct focusable *focusable, EventRecord *event);
void chatter_mouse_down(struct focusable *focusable, EventRecord *event);
+void chatter_resize(struct focusable *focusable, EventRecord *event);
bool chatter_menu(struct focusable *focusable, short menu, short item);
void chatter_idle(struct focusable *focusable, EventRecord *event);
void chatter_update(struct focusable *focusable, EventRecord *event);
@@ -96,6 +99,7 @@ chatter_init(const char *server, const unsigned short
focusable->close = chatter_close;
focusable->atexit = chatter_atexit;
focusable->quit = chatter_quit;
+ focusable->resize = chatter_resize;
focusable->menu = chatter_menu;
focusable->resume = chatter_resume;
add_focusable(focusable);
@@ -131,7 +135,7 @@ chatter_layout(struct chatter *chatter, bool init, Rec
/* input */
bounds.left = win_bounds.left;
- bounds.right = win_bounds.right - 3;
+ bounds.right = win_bounds.right - SCROLLBAR_WIDTH - 3;
bounds.top = win_bounds.bottom - SCROLLBAR_WIDTH;
bounds.bottom = win_bounds.bottom;
if (init) {
@@ -163,7 +167,7 @@ chatter_layout(struct chatter *chatter, bool init, Rec
(*(chatter->nick_list))->selFlags = lOnlyOne | lNoNilHilite;
} else {
(*(chatter->nick_list))->rView = bounds;
- LSize(bounds.right - bounds.left, bounds.bottom - bounds.top - 10,
+ LSize(bounds.right - bounds.left, bounds.bottom - bounds.top,
chatter->nick_list);
}
@@ -194,9 +198,13 @@ chatter_layout(struct chatter *chatter, bool init, Rec
InsetRect(&bounds, 4, 4);
(*(chatter->messages_te))->destRect = bounds;
TECalText(chatter->messages_te);
+
+ chatter_autoscroll(chatter);
}
- InvalRect(chatter->win->visRgn);
+ InvalRect(&win_bounds);
+ DrawControls(chatter->win);
+ chatter_draw_grow_icon(chatter);
}
void
@@ -299,7 +307,6 @@ chatter_update(struct focusable *focusable, EventRecor
EraseRect(&chatter->win->portRect);
r = (*(chatter->nick_list))->rView;
- EraseRect(&r);
LUpdate(chatter->win->visRgn, chatter->nick_list);
InsetRect(&r, -1, -1);
FrameRect(&r);
@@ -313,6 +320,7 @@ chatter_update(struct focusable *focusable, EventRecor
TEUpdate(&(*(chatter->input_te))->viewRect, chatter->input_te);
DrawControls(chatter->win);
+ chatter_draw_grow_icon(chatter);
break;
case activateEvt:
if (event->modifiers & activeFlag) {
@@ -329,6 +337,43 @@ chatter_update(struct focusable *focusable, EventRecor
}
void
+chatter_draw_grow_icon(struct chatter *chatter)
+{
+ Rect r, *te;
+ RgnHandle tmp;
+ WindowPtr win = chatter->win;
+
+ /*
+ * Our input bar is taller than a scrollbar, so we can't use the
+ * normal DrawGrowIcon or our DrawGrowIconOnly
+ */
+ HLock(*(chatter->input_te));
+ te = &(*(chatter->input_te))->viewRect;
+
+ r = win->portRect;
+ r.top = r.bottom - (te->bottom - te->top + 1) - 1;
+ r.left = r.right - SCROLLBAR_WIDTH + 1;
+ r.right += 1;
+ r.bottom += 1;
+ FrameRect(&r);
+
+ r.bottom -= 2;
+ r.right -= 2;
+ r.top = r.bottom - 9;
+ r.left = r.right - 9;
+ FrameRect(&r);
+
+ r.top -= 5;
+ r.left -= 2;
+ r.bottom -= 5;
+ r.right -= 3;
+ FillRect(&r, white);
+ FrameRect(&r);
+
+ HUnlock(*(chatter->input_te));
+}
+
+void
chatter_mouse_down(struct focusable *focusable, EventRecord *event)
{
struct chatter *chatter = (struct chatter *)(focusable->cookie);
@@ -409,6 +454,27 @@ chatter_mouse_down(struct focusable *focusable, EventR
}
}
+void
+chatter_resize(struct focusable *focusable, EventRecord *event)
+{
+ struct chatter *chatter = (struct chatter *)(focusable->cookie);
+ Rect bounds;
+ long newsize, width, height;
+
+ bounds.left = 100;
+ bounds.top = 100;
+ bounds.right = screenBits.bounds.right;
+ bounds.bottom = screenBits.bounds.bottom;
+
+ newsize = GrowWindow(focusable->win, event->where, &bounds);
+
+ height = HiWord(newsize);
+ width = LoWord(newsize);
+ SizeWindow(focusable->win, width, height, true);
+ EraseRect(&chatter->win->portRect);
+ chatter_layout(chatter, false, NULL);
+}
+
bool
chatter_menu(struct focusable *focusable, short menu, short item)
{
@@ -441,30 +507,7 @@ chatter_menu(struct focusable *focusable, short menu,
return false;
}
-#if 0
void
-chatter_grow(Point p)
-{
- GrafPtr old_port;
- long res;
- Rect r;
-
- GetPort(&old_port);
-
- SetPort(chatter_win);
- SetRect(&r, 80, 80, screenBits.bounds.right, screenBits.bounds.bottom);
- res = GrowWindow(chatter_win, p, &r);
- if (res != 0) {
- SizeWindow(chatter_win, LoWord(res), HiWord(res), false);
- InvalRect(&chatter_win->portRect);
- chatter_layout();
- }
-
- SetPort(old_port);
-}
-#endif
-
-void
chatter_key_down(struct focusable *focusable, EventRecord *event)
{
struct chatter *chatter = (struct chatter *)(focusable->cookie);
@@ -633,15 +676,21 @@ no_overflow:
TESetSelect(SHRT_MAX, SHRT_MAX, chatter->messages_te);
TEStylInsert(buf_out, buf_out_len, scrp_rec_h, chatter->messages_te);
HUnlock(scrp_rec_h);
-
+ HUnlock(chatter->messages_te);
+
+ chatter_autoscroll(chatter);
+
+ return buf_out_len;
+}
+
+void
+chatter_autoscroll(struct chatter *chatter)
+{
TEPinScroll(0, -INT_MAX, chatter->messages_te);
SetCtlValue(chatter->messages_scroller,
GetCtlMax(chatter->messages_scroller));
UpdateScrollbarForTE(chatter->win, chatter->messages_scroller,
chatter->messages_te, false);
- HUnlock(chatter->messages_te);
-
- return buf_out_len;
}
void
--- main.c Wed Nov 30 23:22:52 2022
+++ main.c Thu Dec 1 13:53:21 2022
@@ -159,6 +159,14 @@ main(void)
case inDrag:
DragWindow(event_win, event.where, &screenBits.bounds);
break;
+ case inGrow:
+ if (event_win != FrontWindow() && found_focusable) {
+ cancel_notification();
+ show_focusable(found_focusable);
+ }
+ if (found_focusable && found_focusable->resize)
+ found_focusable->resize(found_focusable, &event);
+ break;
case inGoAway:
if (TrackGoAway(event_win, event.where) &&
found_focusable && found_focusable->close)