From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stephen Berman via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#69942: 30.0.50; Fontification of radio-button widget labels Date: Mon, 25 Mar 2024 01:40:36 +0100 Message-ID: <87msqnqh2z.fsf@gmx.net> References: <87frwinw9c.fsf@rub.de> <864jcy1dt3.fsf@gnu.org> <259fef2b-e0bf-46c4-8b42-5e26f906accb@gmail.com> <87v85bqxfv.fsf@gmx.net> Reply-To: Stephen Berman Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="33594"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: 69942@debbugs.gnu.org, Eli Zaretskii To: Mauro Aranda Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Mar 25 01:41:49 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1roYPN-0008cW-Ea for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 25 Mar 2024 01:41:49 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1roYOw-0005Bd-8u; Sun, 24 Mar 2024 20:41:22 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1roYOu-0005BA-Ui for bug-gnu-emacs@gnu.org; Sun, 24 Mar 2024 20:41:20 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1roYOu-0003Ud-E7 for bug-gnu-emacs@gnu.org; Sun, 24 Mar 2024 20:41:20 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1roYPa-0003tC-8j for bug-gnu-emacs@gnu.org; Sun, 24 Mar 2024 20:42:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stephen Berman Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 25 Mar 2024 00:42:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 69942 X-GNU-PR-Package: emacs Original-Received: via spool by 69942-submit@debbugs.gnu.org id=B69942.171132729314912 (code B ref 69942); Mon, 25 Mar 2024 00:42:02 +0000 Original-Received: (at 69942) by debbugs.gnu.org; 25 Mar 2024 00:41:33 +0000 Original-Received: from localhost ([127.0.0.1]:47606 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1roYP6-0003sS-8g for submit@debbugs.gnu.org; Sun, 24 Mar 2024 20:41:32 -0400 Original-Received: from mout.gmx.net ([212.227.17.22]:35011) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1roYP1-0003s4-1W for 69942@debbugs.gnu.org; Sun, 24 Mar 2024 20:41:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmx.net; s=s31663417; t=1711327238; x=1711932038; i=stephen.berman@gmx.net; bh=mUWGQ4Cx0uXJyCIdBAJ9Bw5F6Dk4KazOKktjUOkfL6A=; h=X-UI-Sender-Class:From:To:Cc:Subject:In-Reply-To:References: Date; b=ZFDDMPORtaUj0+m5ocnrh1+soTXmtKHV086J0AOQSH7WVcta2WObX2DMkw1OtSl7 eWcQRJdBD6olaeLZjJYgTbGLWeijKfpNuJSatdrLmBA/9ZSVUEvxU5J40A71o+vIB xKHxxGL+tbHQPUZqVYQAJvMQ8JSiZkmo+c8tMQ14VV133q+C4G9X6qfya9QHGl2BW cjpciatWyA8AGQcQwGhUvo7h4cuOjaAfkszpnmmhtmHLXz93Z86RqSEBHO6Wr9VKi VFDHtyeDGfR9aWgqJlfU8K/cnMmrAFwGlFHp/hXmRd4nZqI04baM300hMOgwksvbn XABDa3e1t1cXeXnGOQ== X-UI-Sender-Class: 724b4f7f-cbec-4199-ad4e-598c01a50d3a Original-Received: from strobelfs2 ([88.130.49.213]) by mail.gmx.net (mrgmx105 [212.227.17.168]) with ESMTPSA (Nemesis) id 1MFsUp-1s5vcA3qV5-00HMqr; Mon, 25 Mar 2024 01:40:38 +0100 In-Reply-To: <87v85bqxfv.fsf@gmx.net> (Stephen Berman's message of "Sun, 24 Mar 2024 19:47:16 +0100") X-Provags-ID: V03:K1:xsQoWlO5upcD7+yGXG+kHXyq7L48wXnzbeNVP23oQyOw3SaDLxy Pfd470wxwH9IdtEAs5NFykRT/89ocUgmrNIleI0kYMJSZ3qtF4W79Zd4qMpkNptBdd+jXmI ALOXsQacaZCivQHhAETjmqAgyxrL8dvxXQiU4WSd3pjqj7b9TPTxGeeucA1y2Wb9wI069L+ h0yH0s9VdrYZrEKwBWqTA== UI-OutboundReport: notjunk:1;M01:P0:G13i/vwtsK0=;QPaulkP+THhYTS+dtP8jLMW9MHR 5N5Peoj2k4dV8ydoMHvpEedEe90qBuaD0V+Ci9yJ2AzHJ7B8HCn4NM+LU4QxR4z3M9Ydxnv6I NJdyC4TU5KLxwXkaCifnvfP98k/SMl1NcY/n2nC2fLfuuT2CThIoHONuyjA9Dt6VGoOSQD8DC xE4ZJSsSD0V/uroXEXmpq8bAOFQhdN+tmGuRar4oVmGllrPYm5Vmm1EVdAEKSqUbtbfw2oRBk fznaJ+VV7kaoGZaP9O//cdF7wv1FrMOuBTmCQ49CEn5YJfQWnIzkJSvJKdbU0XF5pJJo8SqGM fcorYbnvus51FCbDXNR+Yfb0lonqQ4pIrmGswcHIMS8Z7umxSu6oe1EdZ9aYNRjA9K+a3zAVq qR+qLF3xmsFEauiZwCo8tKv5RV93civcWsgTXaIC6rMCHc44ETr+m2kUpessU1wgDmOskLABJ OvxzDD9iz/B/RJ1z0OwTH5zElea32zt53I7Bzgzm7bZffK1mqWl78ksRz0G/fj0nBTTXXKcMW 0MoAbIh7rr5nJLp6CZsd8EmdqZU0Yuxd3ceGHs/xJMzsoMOeqvFO756Mbpyn4JyJCvsUS22JB oIDwkdUFMluwvXcYxxgQG5uOwf6Ob+Z87LEf4VFf6Doe7/OSTYdP5ZIGws0RIO9qZw1eJDD5f /l1Wb1WUL8w9JqhiohSb28plBgvI4a+/sLMCrkV+AY7C/Jm+RCn/9Vl1Ks8x96T65m5x6b9sB NVyju+pap2sm1io6OZya/i3bPeDmH9ycM+BeH1+Ef5yeqwG8eJzVV5aSYIxnF5NEjPZBZMmC X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:282039 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sun, 24 Mar 2024 19:47:16 +0100 Stephen Berman = wrote: > On Sat, 23 Mar 2024 18:05:30 -0300 Mauro Aranda = wrote: > >> Stephen Berman writes: >> >>> In bug#69941 I reported a faulty fontification of radio-button widgets >>> and noted in passing that the labels associated with the radio buttons >>> also have unexpected faces, namely, the widget-inactive face regardless >>> of whether the associated radio buttons are inactive or active (except >>> for the label of a radio button that has been pressed, which has the >>> default face).=C2=A0 While the faulty fontification discussed in bug#69= 941 >>> appears to be a real bug, the widget-inactive face assigned to >>> radio-button labels is apparently by design -- it was present in the >>> initial commit of the widget library.=C2=A0 But this seems to me to hav= e been >>> a UX mistake, since it effectively ignores the semantics implied by the >>> name widget-inactive.=C2=A0 I think a less surprising UI would be for t= he >>> labels to be fontified according to the widget's activation state: >>> default face when the widget is active and widget-inactive face when >>> it's inactive.=C2=A0 The attached patches provide two possible >>> implementations of this UI. >>> >>> The first patch makes the change unconditionally, treating the current >>> fontification as a UI/UX bug.=C2=A0 But it may be argued that this aspe= ct of >>> the widget UI should not be unconditionally changed, since it was >>> apparently a deliberate design choice and there have been (AFAIK) no >>> complaints about the semantic discrepancy till now.=C2=A0 The lack of >>> complaint could be because the widget-inactive face inherits the shadow >>> face, so it is not sharply different from the default face. But if one >>> uses a very different face (as I did for illustrative purposes in >>> bug#69941), the inconsistency is very obvious and (IMO) jarring. >>> Nevertheless, to allow keeping the current fontification, the second >>> patch conditionalizes the change from the current fontification by means >>> of a user option (with the default being the current fontification). >>> >>> Is either of these changes acceptable? >> >> Thanks for working on this.=C2=A0 What about adding a widget-unselected = face? >> I think that might be the intention with using the widget-inactive face >> for unselected radio items. > > Yes, I agree that was likely the intention. But I think it's > superfluous: after all, the distinction between selected (or chosen) and > unselected items is already clear from the appearance of the radio > buttons or, with checklist widgets, the check boxes (my patch neglected > checklists, but it's straightforward to account for them: in > widget-checklist-add-item the (widget-apply child :deactivate) sexp > should be wrapped in an (unless widget-radio-face-from-state ...)). > > On the other hand, with an unselected face for the labels of the radio > button or check boxes, if it defaults to inheriting the shadow face for > unselected items, that corresponds to the current appearance with the > widget-inactive face, and by setting the widget-unselected face to the > default face, all labels would appear the same, which is what I want. > So for me that's an acceptable alternative to my proposed defcustom. I > tried to implement it, but I'm not very conversant with the workings of > widget properties and how to apply faces depending on the widget's > state, and I haven't managed to come up with a working implementation > yet. I'll keep trying, but you or someone else might be able to do it > sooner. > > (There is another argument, besides superfluousness, against using a > separate face for unselected items: using multiple check boxes instead > of a checklist, as e.g. recentf-edit-list does. With these the label of > each check box is supplied by the :tag property, so it is not touched by > the current handling in terms of the child widget's activation state. > I'm not sure if using an unselected face here would be unproblematic or > not.) Ok, I've gotten further with implementing disinguishing by faces selected (chosen) and unselected radio buttons in radio-button-choice widgets and check boxes in checklist widgets, see the attached patch. Initial tests seem ok, but it definitely needs more testing. Steve Berman --=-=-= Content-Type: text/x-patch Content-Disposition: attachment Content-Description: selected and unselected widgets Content-Transfer-Encoding: quoted-printable diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 172da3db1e0..005aa918087 100644 =2D-- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -555,6 +555,27 @@ widget-specify-active (delete-overlay inactive) (widget-put widget :inactive nil)))) +(defface widget-unselected + '((t :inherit shadow)) + "Face used for unselected widgets." + :group 'widget-faces + :version "30.1") + +(defun widget-specify-unselected (widget from to) + "Fontify WIDGET as unselected (not chosen)." + (let ((overlay (make-overlay from to nil t nil))) + (overlay-put overlay 'face 'widget-unselected) + (overlay-put overlay 'evaporate t) + (overlay-put overlay 'priority 100) + (widget-put widget :unselected overlay))) + +(defun widget-specify-selected (widget) + "Remove fontification of WIDGET as unselected (not chosen)." + (let ((unselected (widget-get widget :unselected))) + (when unselected + (delete-overlay unselected) + (widget-put widget :unselected nil)))) + ;;; Widget Properties. (defsubst widget-type (widget) @@ -2415,10 +2436,16 @@ 'checkbox (defun widget-checkbox-action (widget &optional event) "Toggle checkbox, notify parent, and set active state of sibling." (widget-toggle-action widget event) - (let ((sibling (widget-get-sibling widget))) + (let* ((sibling (widget-get-sibling widget)) + (from (widget-get sibling :from)) + (to (widget-get sibling :to))) (when sibling - (widget-apply sibling - (if (widget-value widget) :activate :deactivate)) + (if (widget-value widget) + (progn + (widget-apply sibling :activate) + (widget-specify-selected sibling)) + :deactivate + (widget-specify-unselected sibling from to)) (widget-clear-undo)))) ;;; The `checklist' Widget. @@ -2474,15 +2501,19 @@ widget-checklist-add-item ((eq escape ?v) (setq child (cond ((not chosen) - (let ((child (widget-create-child widget type))) - (widget-apply child :deactivate) + (let* ((child (widget-create-child widget type)) + (from (widget-get child :from)) + (to (widget-get child :to))) + (widget-specify-unselected child from to) child)) ((widget-inline-p type t) (widget-create-child-value - widget type (cdr chosen))) + widget type (cdr chosen)) + (widget-specify-selected child)) (t (widget-create-child-value - widget type (car (cdr chosen))))))) + widget type (car (cdr chosen))) + (widget-specify-selected child))))) (t (error "Unknown escape `%c'" escape))))) ;; Update properties. @@ -2653,8 +2684,11 @@ widget-radio-add-item (widget-create-child-value widget type value) (widget-create-child widget type))) - (unless chosen - (widget-apply child :deactivate))) + (if chosen + (widget-specify-selected child) + (let ((from (widget-get child :from)) + (to (widget-get child :to))) + (widget-specify-unselected child from to)))) (t (error "Unknown escape `%c'" escape))))) ;; Update properties. @@ -2704,14 +2738,17 @@ widget-radio-value-set (dolist (current (widget-get widget :children)) (let* ((button (widget-get current :button)) (match (and (not found) - (widget-apply current :match value)))) + (widget-apply current :match value))) + (from (widget-get current :from)) + (to (widget-get current :to))) (widget-value-set button match) (if match - (progn - (widget-value-set current value) - (widget-apply current :activate)) - (widget-apply current :deactivate)) - (setq found (or found match)))))) + (progn + (widget-value-set current value) + (widget-apply current :activate) + (widget-specify-selected current)) + (widget-specify-unselected current from to)) + (setq found (or found match)))))) (defun widget-radio-validate (widget) ;; Valid if we have made a valid choice. @@ -2731,13 +2768,16 @@ widget-radio-action (let ((buttons (widget-get widget :buttons))) (when (memq child buttons) (dolist (current (widget-get widget :children)) - (let* ((button (widget-get current :button))) + (let* ((button (widget-get current :button)) + (from (widget-get current :from)) + (to (widget-get current :to))) (cond ((eq child button) (widget-value-set button t) - (widget-apply current :activate)) + (widget-apply current :activate) + (widget-specify-selected current)) ((widget-value button) (widget-value-set button nil) - (widget-apply current :deactivate))))))) + (widget-specify-unselected current from to))))))) ;; Pass notification to parent. (widget-apply widget :notify child event)) --=-=-=--