File 2581-observer-Support-darkmode-gui.patch of Package erlang

From 528e55e44cf1ee32d90d8c4c4d5790d18cae79bc Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Wed, 19 Jun 2019 15:23:04 +0200
Subject: [PATCH 1/2] observer: Support darkmode gui

---
 lib/observer/src/cdv_virtual_list_wx.erl |  9 +++---
 lib/observer/src/observer_app_wx.erl     | 30 +++++++++++++------
 lib/observer/src/observer_lib.erl        | 51 +++++++++++++++++++-------------
 lib/observer/src/observer_perf_wx.erl    | 30 ++++++++++++-------
 lib/observer/src/observer_port_wx.erl    | 14 +++++----
 lib/observer/src/observer_pro_wx.erl     |  2 +-
 lib/observer/src/observer_tv_table.erl   |  5 ++--
 lib/observer/src/observer_tv_wx.erl      |  2 +-
 8 files changed, 90 insertions(+), 53 deletions(-)

diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl
index 14877b7eab..51e85e17c1 100644
--- a/lib/observer/src/cdv_virtual_list_wx.erl
+++ b/lib/observer/src/cdv_virtual_list_wx.erl
@@ -96,8 +96,9 @@ start_detail_win_2(Callback,Id) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 init([ParentWin, Callback, Owner]) ->
-    {Holder,TW} = spawn_table_holder(Callback, Owner),
     Panel = wxPanel:new(ParentWin),
+    Attrs = observer_lib:create_attrs(Panel),
+    {Holder,TW} = spawn_table_holder(Callback, Owner, Attrs),
     {Grid,MenuCols}  = create_list_box(Panel, Holder, Callback, Owner),
     Sizer = wxBoxSizer:new(?wxVERTICAL),
     wxSizer:add(Sizer, Grid, [{flag, ?wxEXPAND bor ?wxALL},
@@ -233,7 +234,8 @@ handle_call(new_dump, _From,
     Ref = erlang:monitor(process,Holder),
     Holder ! stop,
     receive {'DOWN',Ref,_,_,_} -> ok end,
-    {NewHolder,TW} = spawn_table_holder(Callback, all),
+    Attrs = observer_lib:create_attrs(Grid),
+    {NewHolder,TW} = spawn_table_holder(Callback, all, Attrs),
     {reply, ok, State#state{detail_wins=[],holder=NewHolder,trunc_warn=TW}};
 
 handle_call(Msg, _From, State) ->
@@ -329,9 +331,8 @@ handle_event(Event, State) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%TABLE HOLDER%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-spawn_table_holder(Callback, Owner) ->
+spawn_table_holder(Callback, Owner, Attrs) ->
     {Info,TW} = Callback:get_info(Owner),
-    Attrs = observer_lib:create_attrs(),
     Parent = self(),
     Holder =
 	case Owner of
diff --git a/lib/observer/src/observer_app_wx.erl b/lib/observer/src/observer_app_wx.erl
index 8c3eef5411..c4527ba063 100644
--- a/lib/observer/src/observer_app_wx.erl
+++ b/lib/observer/src/observer_app_wx.erl
@@ -48,7 +48,7 @@
 	  usegc = false
 	}).
 
--record(paint, {font, pen, brush, sel, links}).
+-record(paint, {font, fg, pen, brush, sel, links}).
 
 -record(app, {ptree, n2p, links, dim}).
 -record(box, {x,y, w,h, s1}).
@@ -92,7 +92,8 @@ init([Notebook, Parent, _Config]) ->
     Extra = wxBoxSizer:new(?wxVERTICAL),
     DrawingArea = wxScrolledWindow:new(P2, [{winid, ?DRAWAREA},
 					    {style,?wxFULL_REPAINT_ON_RESIZE}]),
-    wxWindow:setBackgroundColour(DrawingArea, ?wxWHITE),
+    BG = wxWindow:getBackgroundColour(Apps),
+    wxWindow:setBackgroundStyle(DrawingArea, ?wxBG_STYLE_SYSTEM),
     wxWindow:setVirtualSize(DrawingArea, 800, 800),
     wxSplitterWindow:setMinimumPaneSize(Splitter,50),
     wxSizer:add(Extra, DrawingArea, [{flag, ?wxEXPAND},{proportion, 1}]),
@@ -127,7 +128,17 @@ init([Notebook, Parent, _Config]) ->
            Font0
 	   end,
     SelCol   = wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT),
-    GreyBrush = wxBrush:new({230,230,240}),
+    {Fg,BGBrush,Pen} =
+        case observer_lib:is_darkmode(BG) of
+            false ->
+                {wxSystemSettings:getColour(?wxSYS_COLOUR_BTNTEXT),
+                 wxBrush:new(wxSystemSettings:getColour(?wxSYS_COLOUR_BTNSHADOW)),
+                 wxPen:new({80,80,80}, [{width, Scale * 2}])};
+            true ->
+                {wxSystemSettings:getColour(?wxSYS_COLOUR_BTNTEXT),
+                 wxBrush:new(wxSystemSettings:getColour(?wxSYS_COLOUR_BTNSHADOW)),
+                 wxPen:new({0,0,0}, [{width, Scale * 2}])}
+        end,
     SelBrush = wxBrush:new(SelCol),
     LinkPen  = wxPen:new(SelCol, [{width, Scale * 2}]),
     process_flag(trap_exit, true),
@@ -137,8 +148,9 @@ init([Notebook, Parent, _Config]) ->
 		   app_w =DrawingArea,
 		   usegc = UseGC,
 		   paint=#paint{font = Font,
-				pen  = wxPen:new({80,80,80}, [{width, Scale * 2}]),
-				brush= GreyBrush,
+                                fg   = Fg,
+				pen  = Pen,
+				brush= BGBrush,
 				sel  = SelBrush,
 				links= LinkPen
 			       }
@@ -306,11 +318,11 @@ handle_info({delivery, _Pid, app, _Curr, {[], [], [], []}},
 
 handle_info({delivery, Pid, app, Curr, AppData},
 	    State = #state{panel=Panel, appmon=Pid, current=Curr, usegc=UseGC,
-			   app_w=AppWin, paint=#paint{font=Font}}) ->
+			   app_w=AppWin, paint=#paint{fg=Fg, font=Font}}) ->
     GC = if UseGC -> {?wxGC:create(AppWin), false};
 	    true ->  {false, wxWindowDC:new(AppWin)}
 	 end,
-    setFont(GC, Font, {0,0,0}),
+    setFont(GC, Font, Fg),
     App = build_tree(AppData, GC),
     destroy_gc(GC),
     setup_scrollbar(AppWin, App),
@@ -508,13 +520,13 @@ tree_map([], _ , Acc) -> Acc.
 draw(_DC, undefined, _, _) ->
     ok;
 draw(DC, #app{dim={_W,_H}, ptree=Tree, links=Links}, Sel,
-     #paint{font=Font, pen=Pen, brush=Brush, links=LPen, sel=SelBrush}) ->
+     #paint{font=Font, fg=Fg, pen=Pen, brush=Brush, links=LPen, sel=SelBrush}) ->
     setPen(DC, LPen),
     [draw_xlink(Link, DC) || Link <- Links],
     setPen(DC, Pen),
     %% ?wxGC:drawRectangle(DC, 2,2, _W-2,_H-2), %% DEBUG
     setBrush(DC, Brush),
-    setFont(DC, Font, {0,0,0}),
+    setFont(DC, Font, Fg),
     draw_tree(Tree, root, DC),
     case Sel of
 	undefined -> ok;
diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl
index 7c68b0ebb6..5cb6645cb9 100644
--- a/lib/observer/src/observer_lib.erl
+++ b/lib/observer/src/observer_lib.erl
@@ -28,8 +28,8 @@
 	 interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1,
 	 display_info/2, display_info/3, fill_info/2, update_info/2, to_str/1,
 	 create_menus/3, create_menu_item/3,
-	 create_attrs/0,
-	 set_listctrl_col_size/2,
+	 is_darkmode/1, create_attrs/1,
+	 set_listctrl_col_size/2, mix/3,
 	 create_status_bar/1,
 	 html_window/1, html_window/2,
          make_obsbin/2,
@@ -373,26 +373,37 @@ create_menu_item(separator, Menu, Index) ->
     wxMenu:insertSeparator(Menu, Index),
     Index+1.
 
-create_attrs() ->
+create_attrs(Window) ->
+    DarkMode = is_darkmode(wxWindow:getBackgroundColour(Window)),
     Font = wxSystemSettings:getFont(?wxSYS_DEFAULT_GUI_FONT),
     Text = case wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOXTEXT) of
-	       {255,255,255,_} -> {10,10,10};  %% Is white on Mac for some reason
-	       Color -> Color
-	   end,
-    #attrs{even = wxListItemAttr:new(Text, ?BG_EVEN, Font),
-	   odd  = wxListItemAttr:new(Text, ?BG_ODD, Font),
-	   deleted = wxListItemAttr:new(?FG_DELETED, ?BG_DELETED, Font),
-	   changed_even = wxListItemAttr:new(Text, mix(?BG_CHANGED,?BG_EVEN), Font),
-	   changed_odd  = wxListItemAttr:new(Text, mix(?BG_CHANGED,?BG_ODD), Font),
-	   new_even = wxListItemAttr:new(Text, mix(?BG_NEW,?BG_EVEN), Font),
-	   new_odd  = wxListItemAttr:new(Text, mix(?BG_NEW, ?BG_ODD), Font),
-	   searched = wxListItemAttr:new(Text, ?BG_SEARCHED, Font)
-	  }.
-
-mix(RGB,_) -> RGB.
-
-%% mix({R,G,B},{MR,MG,MB}) ->
-%%     {trunc(R*MR/255), trunc(G*MG/255), trunc(B*MB/255)}.
+               {255,255,255,_} when not DarkMode -> {10,10,10}; %% Is white on Mac for some reason
+               Color -> Color
+           end,
+    Even = wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOX),
+    Odd = mix(Even, wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT), 0.8),
+    #attrs{even = wxListItemAttr:new(Text, Even, Font),
+           odd  = wxListItemAttr:new(Text, Odd, Font),
+           deleted = wxListItemAttr:new(?FG_DELETED, ?BG_DELETED, Font),
+           changed_even = wxListItemAttr:new(Text, mix(?BG_CHANGED, ?BG_EVEN, 0.9), Font),
+           changed_odd  = wxListItemAttr:new(Text, mix(?BG_CHANGED, ?BG_ODD, 0.9), Font),
+           new_even = wxListItemAttr:new(Text, mix(?BG_NEW, ?BG_EVEN, 0.9), Font),
+           new_odd  = wxListItemAttr:new(Text, mix(?BG_NEW, ?BG_ODD, 0.9), Font),
+           searched = wxListItemAttr:new(Text, ?BG_SEARCHED, Font)
+          }.
+
+mix(RGB,{MR,MG,MB,_}, V) ->
+    mix(RGB, {MR,MG,MB}, V);
+mix({R,G,B,_}, RGB, V) ->
+    mix({R,G,B}, RGB, V);
+mix({R,G,B},{MR,MG,MB}, V) when V =< 1.0 ->
+    {min(255, round(R*V+MR*(1.0-V))),
+     min(255, round(G*V+MG*(1.0-V))),
+     min(255, round(B*V+MB*(1.0-V)))}.
+
+
+is_darkmode({R,G,B,_}) ->
+    ((R+G+B) div 3) < 100.
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
diff --git a/lib/observer/src/observer_perf_wx.erl b/lib/observer/src/observer_perf_wx.erl
index 79271addf2..50a6d6a915 100644
--- a/lib/observer/src/observer_perf_wx.erl
+++ b/lib/observer/src/observer_perf_wx.erl
@@ -55,7 +55,7 @@
 
 -define(wxGC, wxGraphicsContext).
 
--record(paint, {font, small, pen, pen2, pens, dot_pens, usegc = false}).
+-record(paint, {font, small, fg, pen, pen2, pens, dot_pens, usegc = false}).
 
 start_link(Notebook, Parent, Config) ->
     wx_object:start_link(?MODULE, [Notebook, Parent, Config], []).
@@ -126,7 +126,16 @@ setup_graph_drawing(Panels) ->
 		  SF = wxFont:new(Scale * (DefSize-2), DefFamily, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_NORMAL),
 		  {F, SF}
 	  end,
-    BlackPen = wxPen:new({0,0,0}, [{width, Scale}]),
+    BG = wxWindow:getBackgroundColour((hd(Panels))#win.panel),
+    Fg = case observer_lib:is_darkmode(BG) of
+             false -> {0,0,0};
+             true  -> wxSystemSettings:getColour(?wxSYS_COLOUR_BTNTEXT)
+         end,
+
+    PenColor = case observer_lib:is_darkmode(BG) of
+                   false -> {0,0,0};
+                   true  -> {0,0,0}
+               end,
     Pens = [wxPen:new(Col, [{width, Scale}, {style, ?wxSOLID}])
             || Col <- tuple_to_list(colors())],
     DotPens = [wxPen:new(Col, [{width, Scale}, {style, ?wxDOT}])
@@ -134,8 +143,9 @@ setup_graph_drawing(Panels) ->
     #paint{usegc = UseGC,
 	   font  = Font,
 	   small = SmallFont,
-	   pen   = ?wxGREY_PEN,
-	   pen2  = BlackPen,
+           fg    = Fg,  %% Text color
+	   pen   = wxPen:new(PenColor),
+	   pen2  = wxPen:new(PenColor, [{width, Scale}]),
 	   pens  = list_to_tuple(Pens),
            dot_pens = list_to_tuple(DotPens)
 	  }.
@@ -525,7 +535,7 @@ draw_win(DC, #win{name=Name, no_samples=Samples, geom=#{scale:={WS,HS}},
     DrawBs(),
     ok;
 
-draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{small=Small}=Paint) ->
+draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{fg=Fg, small=Small}=Paint) ->
     %% Draw Error Msg
     try draw_borders(DC, Ti, Win, Paint) of
 	{X0,_Y0,DrawBs} ->
@@ -533,7 +543,7 @@ draw_win(DC, #win{no_samples=Samples} = Win,Ti, #paint{small=Small}=Paint) ->
 		       true  -> "Waiting for data";
 		       false -> "Information not available"
 		   end,
-	    setFont(DC, Small, {0,0,0}),
+	    setFont(DC, Small, Fg),
 	    {_,WW} = getSize(DC),
 	    drawText(DC, Text, X0 + 100, WW div 2),
 	    DrawBs(),
@@ -628,7 +638,7 @@ spline_tan(Y0, Y1, Y2, Y3) ->
 
 draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
 	     #win{name=Type, geom=Geom, info=Info, max={_,_,Unit,_}},
-	     #paint{pen=Pen, pen2=Pen2, font=Font, small=Small}) ->
+	     #paint{pen=Pen, pen2=Pen2, fg=Fg, font=Font, small=Small}) ->
     #{p0:={GraphX0, GraphY0}, p1:={GraphX1,GraphY1}, scale:={ScaleW0,_},
       txsz:={TW,TH,SpaceW}, txt:={BottomTextY, MaxTextY}, strs:={Str1,Str2,Str3}} = Geom,
 
@@ -640,7 +650,7 @@ draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
     GraphY50 = GraphY0 + (GraphY1 - GraphY0) / 2,
     GraphY75 = GraphY0 + 3*(GraphY1 - GraphY0) / 4,
 
-    setFont(DC, Small, {0,0,0}),
+    setFont(DC, Small, Fg),
     Align = fun(Str, Y) ->
 		    {StrW, _} = getTextExtent(DC, Str),
 		    drawText(DC, Str, GraphX0 - StrW - ?BW, Y)
@@ -670,11 +680,11 @@ draw_borders(DC, #ti{secs=Secs, fetch=FetchFreq},
     strokeLine(DC, GraphX0-3, GraphY50, GraphX1, GraphY50),
     strokeLine(DC, GraphX0-3, GraphY75, GraphX1, GraphY75),
 
-    setFont(DC, Font, {0,0,0}),
+    setFont(DC, Font, Fg),
 
     Text = fun(X,Y, Str, PenId) ->
 		   if PenId == 0 ->
-			   setFont(DC, Font, {0,0,0});
+			   setFont(DC, Font, Fg);
 		      PenId > 0 ->
 			   Id = 1 + ((PenId-1) rem tuple_size(colors())),
 			   setFont(DC, Font, element(Id, colors()))
diff --git a/lib/observer/src/observer_port_wx.erl b/lib/observer/src/observer_port_wx.erl
index 00cf1b5fba..5cb6d9bc22 100644
--- a/lib/observer/src/observer_port_wx.erl
+++ b/lib/observer/src/observer_port_wx.erl
@@ -61,7 +61,8 @@
          inet}).
 
 -record(opt, {sort_key=2,
-	      sort_incr=true
+	      sort_incr=true,
+              odd_bg
 	     }).
 
 -record(state,
@@ -111,7 +112,10 @@ init([Notebook, Parent, Config]) ->
     wxListCtrl:connect(Grid, size, [{skip, true}]),
 
     wxWindow:setFocus(Grid),
-    {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer=Config}}.
+    Even = wxSystemSettings:getColour(?wxSYS_COLOUR_LISTBOX),
+    Odd = observer_lib:mix(Even, wxSystemSettings:getColour(?wxSYS_COLOUR_HIGHLIGHT), 0.8),
+    Opt = #opt{odd_bg=Odd},
+    {Panel, #state{grid=Grid, parent=Parent, panel=Panel, timer=Config, opt=Opt}}.
 
 handle_event(#wx{id=?ID_REFRESH},
 	     State = #state{node=Node, grid=Grid, opt=Opt}) ->
@@ -553,7 +557,7 @@ filter_monitor_info() ->
 
 update_grid(Grid, Sel, Opt, Ports) ->
     wx:batch(fun() -> update_grid2(Grid, Sel, Opt, Ports) end).
-update_grid2(Grid, Sel, #opt{sort_key=Sort,sort_incr=Dir}, Ports) ->
+update_grid2(Grid, Sel, #opt{sort_key=Sort,sort_incr=Dir, odd_bg=BG}, Ports) ->
     wxListCtrl:deleteAllItems(Grid),
     Update =
 	fun(#port{id = Id,
@@ -563,8 +567,8 @@ update_grid2(Grid, Sel, #opt{sort_key=Sort,sort_incr=Dir}, Ports) ->
 		  controls = Ctrl},
 	    Row) ->
 		_Item = wxListCtrl:insertItem(Grid, Row, ""),
-		if (Row rem 2) =:= 0 ->
-			wxListCtrl:setItemBackgroundColour(Grid, Row, ?BG_EVEN);
+		if (Row rem 2) =:= 1 ->
+			wxListCtrl:setItemBackgroundColour(Grid, Row, BG);
 		   true -> ignore
 		end,
 
diff --git a/lib/observer/src/observer_pro_wx.erl b/lib/observer/src/observer_pro_wx.erl
index 4ab4a78462..6b359f3c44 100644
--- a/lib/observer/src/observer_pro_wx.erl
+++ b/lib/observer/src/observer_pro_wx.erl
@@ -94,7 +94,7 @@ start_link(Notebook, Parent, Config) ->
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 init([Notebook, Parent, Config]) ->
-    Attrs = observer_lib:create_attrs(),
+    Attrs = observer_lib:create_attrs(Notebook),
     Self = self(),
     Acc = maps:get(acc, Config, false),
     Holder = spawn_link(fun() -> init_table_holder(Self, Acc, Attrs) end),
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index 7bd67a0f0b..32d75f77d4 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -116,8 +116,8 @@ init([Parent, Opts]) ->
 	TabId = table_id(Table),
 	ColumnNames = column_names(Node, Source, TabId),
 	KeyPos = key_pos(Node, Source, TabId),
-
-	Attrs = observer_lib:create_attrs(),
+	Panel = wxPanel:new(Frame),
+	Attrs = observer_lib:create_attrs(Panel),
 
 	Self = self(),
 	Holder = spawn_link(fun() ->
@@ -125,7 +125,6 @@ init([Parent, Opts]) ->
 						      length(ColumnNames), Node, Attrs)
 			    end),
 
-	Panel = wxPanel:new(Frame),
 	Sizer = wxBoxSizer:new(?wxVERTICAL),
 	Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
 	Grid = wxListCtrl:new(Panel, [{style, Style},
diff --git a/lib/observer/src/observer_tv_wx.erl b/lib/observer/src/observer_tv_wx.erl
index 9743a6ed42..d622b1423b 100644
--- a/lib/observer/src/observer_tv_wx.erl
+++ b/lib/observer/src/observer_tv_wx.erl
@@ -71,7 +71,7 @@ init([Notebook, Parent, Config]) ->
 
     Style = ?wxLC_REPORT bor ?wxLC_VIRTUAL bor ?wxLC_SINGLE_SEL bor ?wxLC_HRULES,
     Self = self(),
-    Attrs = observer_lib:create_attrs(),
+    Attrs = observer_lib:create_attrs(Panel),
     Holder = spawn_link(fun() -> init_table_holder(Self, Attrs) end),
     CBs = [{onGetItemText, fun(_, Item,Col) -> get_row(Holder, Item, Col) end},
            {onGetItemAttr, fun(_, Item) -> get_attr(Holder, Item) end}],
-- 
2.16.4

openSUSE Build Service is sponsored by