Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,8 @@ This configuration file holds user interface color settings. Default content:
dialog_attr_selected=reverse
dialog_color_bg=
dialog_color_fg=
dialog_color_selected_bg=
dialog_color_selected_fg=
entry_attr=
entry_color_bg=
entry_color_fg=
Expand All @@ -949,6 +951,8 @@ This configuration file holds user interface color settings. Default content:
help_color_fg=white
history_name_attr=bold
history_name_attr_selected=reverse
history_name_color_selected_bg=
history_name_color_selected_fg=
history_name_recv_color_bg=
history_name_recv_color_fg=
history_name_recv_group_color_bg=
Expand All @@ -959,6 +963,8 @@ This configuration file holds user interface color settings. Default content:
history_text_attachment_color_fg=gray
history_text_attr=
history_text_attr_selected=reverse
history_text_color_selected_bg=
history_text_color_selected_fg=
history_text_quoted_color_bg=
history_text_quoted_color_fg=gray
history_text_reaction_color_bg=
Expand All @@ -973,6 +979,8 @@ This configuration file holds user interface color settings. Default content:
list_attr_selected=reverse
list_color_bg=
list_color_fg=
list_color_selected_bg=
list_color_selected_fg=
list_color_unread_bg=
list_color_unread_fg=
listborder_attr=
Expand Down Expand Up @@ -1020,6 +1028,12 @@ parameters also supports the special value `usercolor`. When set, nchat will
determine which color to use for a user, based on a hash of their user id
used to pick a color from the list in `~/.config/nchat/usercolor.conf`.

The `list_color_selected`, `dialog_color_selected`, `history_name_color_selected`
and `history_text_color_selected` parameters allow specifying explicit colors
for the currently selected item, instead of (or in addition to) the
corresponding `_attr_selected` attribute. When left empty (default), only the
attribute styling is applied, preserving previous behavior.

Themes
------
Color themes are available in the source package under the `themes` directory
Expand Down
13 changes: 13 additions & 0 deletions src/uicolorconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ void UiColorConfig::Init()
{ "list_attr_selected", "reverse" },
{ "list_color_bg", "" },
{ "list_color_fg", "" },
{ "list_color_selected_bg", "" },
{ "list_color_selected_fg", "" },
{ "list_color_unread_fg", "" },
{ "list_color_unread_bg", "" },
{ "listborder_attr", "" },
Expand All @@ -58,6 +60,8 @@ void UiColorConfig::Init()

{ "history_text_attr", "" },
{ "history_text_attr_selected", "reverse" },
{ "history_text_color_selected_bg", "" },
{ "history_text_color_selected_fg", "" },
{ "history_text_sent_color_bg", "" },
{ "history_text_sent_color_fg", defaultSentColor },
{ "history_text_reaction_color_bg", "" },
Expand All @@ -73,6 +77,8 @@ void UiColorConfig::Init()

{ "history_name_attr", "bold" },
{ "history_name_attr_selected", "reverse" },
{ "history_name_color_selected_bg", "" },
{ "history_name_color_selected_fg", "" },
{ "history_name_sent_color_bg", "" },
{ "history_name_sent_color_fg", defaultSentColor },
{ "history_name_recv_color_bg", "" },
Expand All @@ -84,6 +90,8 @@ void UiColorConfig::Init()
{ "dialog_attr_selected", "reverse" },
{ "dialog_color_bg", "" },
{ "dialog_color_fg", "" },
{ "dialog_color_selected_bg", "" },
{ "dialog_color_selected_fg", "" },
{ "dialog_shaded_color_bg", "" },
{ "dialog_shaded_color_fg", defaultShadedColor },

Expand Down Expand Up @@ -128,6 +136,11 @@ int UiColorConfig::GetColorPair(const std::string& p_Param)
return colorPairs[p_Param];
}

bool UiColorConfig::HasColor(const std::string& p_Param)
{
return !m_Config.Get(p_Param + "_fg").empty() || !m_Config.Get(p_Param + "_bg").empty();
}

int UiColorConfig::GetUserColorPair(const std::string& p_Param, const std::string& p_UserId)
{
if (!has_colors()) return 0;
Expand Down
1 change: 1 addition & 0 deletions src/uicolorconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class UiColorConfig
static void Init();
static void Cleanup();
static int GetColorPair(const std::string& p_Param); // ex: "top_color"
static bool HasColor(const std::string& p_Param); // ex: "list_color_selected"
static int GetUserColorPair(const std::string& p_Param, const std::string& p_UserId);
static bool IsUserColor(const std::string& p_Param); // ex: "top_color"
static int GetAttribute(const std::string& p_Param); // ex: "top_attr"
Expand Down
16 changes: 16 additions & 0 deletions src/uihistoryview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ void UiHistoryView::Draw()
int attributeText = isSelectedMessage ? attributeTextSelected : attributeTextNormal;
int colorPairText = [&]()
{
// selected color takes precedence over sent/recv/usercolor for the selected message
static bool hasColorSelected = UiColorConfig::HasColor("history_text_color_selected");
if (isSelectedMessage && hasColorSelected)
{
static int colorPairSelected = UiColorConfig::GetColorPair("history_text_color_selected");
return colorPairSelected;
}

if (msg.isOutgoing) return colorPairTextSent;

if (msg.senderId == currentChat.second) return colorPairTextRecv;
Expand Down Expand Up @@ -365,6 +373,14 @@ void UiHistoryView::Draw()
int attributeName = isSelectedMessage ? attributeNameSelected : attributeNameNormal;
int colorPairName = [&]()
{
// selected color takes precedence over sent/recv/usercolor for the selected message
static bool hasColorSelected = UiColorConfig::HasColor("history_name_color_selected");
if (isSelectedMessage && hasColorSelected)
{
static int colorPairSelected = UiColorConfig::GetColorPair("history_name_color_selected");
return colorPairSelected;
}

if (msg.isOutgoing) return colorPairNameSent;

if (msg.senderId == currentChat.second) return colorPairNameRecv;
Expand Down
16 changes: 15 additions & 1 deletion src/uilistdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ void UiListDialog::Draw()
static int shadedColorPair = UiColorConfig::GetColorPair("dialog_shaded_color");
static int attribute = UiColorConfig::GetAttribute("dialog_attr");
static int attributeSelected = UiColorConfig::GetAttribute("dialog_attr_selected");
static bool hasColorSelected = UiColorConfig::HasColor("dialog_color_selected");
static int colorPairSelected = hasColorSelected ? UiColorConfig::GetColorPair("dialog_color_selected") : colorPair;
static std::wstring hiddenIndicator = L".";

werase(m_Win);
Expand All @@ -190,7 +192,9 @@ void UiListDialog::Draw()
for (int i = offset; i < std::min((offset + m_H), (int)m_Items.size()); ++i)
{
const std::wstring& wdisp = m_Items.at(i);
const bool isShaded = m_ShadeHidden && (wdisp.rfind(hiddenIndicator, 0) == 0);
// selected color takes precedence over shaded color for the highlighted item
const bool isSelectedColor = (i == m_Index) && hasColorSelected;
const bool isShaded = m_ShadeHidden && !isSelectedColor && (wdisp.rfind(hiddenIndicator, 0) == 0);

if (isShaded)
{
Expand All @@ -202,6 +206,11 @@ void UiListDialog::Draw()
{
wattroff(m_Win, attribute);
wattron(m_Win, attributeSelected);
if (isSelectedColor)
{
wattroff(m_Win, colorPair);
wattron(m_Win, colorPairSelected);
}
}

mvwaddnwstr(m_Win, (i - offset), 0, wdisp.c_str(), std::min((int)wdisp.size(), m_W));
Expand All @@ -210,6 +219,11 @@ void UiListDialog::Draw()
{
wattroff(m_Win, attributeSelected);
wattron(m_Win, attribute);
if (isSelectedColor)
{
wattroff(m_Win, colorPairSelected);
wattron(m_Win, colorPair);
}
}

if (isShaded)
Expand Down
21 changes: 20 additions & 1 deletion src/uilistview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ void UiListView::Draw()
static int attribute = UiColorConfig::GetAttribute("list_attr");
static int attributeSelected = UiColorConfig::GetAttribute("list_attr_selected");
static int colorPairUnread = UiColorConfig::GetColorPair("list_color_unread");
static bool hasColorSelected = UiColorConfig::HasColor("list_color_selected");
static int colorPairSelected = hasColorSelected ? UiColorConfig::GetColorPair("list_color_selected") : colorPair;

int index = std::max(0, m_Model->GetCurrentChatIndexLocked());
const std::vector<std::pair<std::string, std::string>>& p_ChatVec = m_Model->GetChatVecLocked();
Expand Down Expand Up @@ -84,6 +86,11 @@ void UiListView::Draw()
{
wattroff(m_PaddedWin, attribute);
wattron(m_PaddedWin, attributeSelected);
if (hasColorSelected)
{
wattroff(m_PaddedWin, colorPair);
wattron(m_PaddedWin, colorPairSelected);
}
}

int y = i - offset;
Expand All @@ -96,8 +103,11 @@ void UiListView::Draw()
std::wstring wname = StrUtil::ToWString(name).substr(0, m_PaddedW);
wname = StrUtil::TrimPadWString(wname, m_PaddedW);

if (unreads[i])
// selected color takes precedence over unread color for the highlighted row
const bool useUnreadColor = unreads[i] && !((i == index) && hasColorSelected);
if (useUnreadColor)
{
wattroff(m_PaddedWin, colorPair);
wattron(m_PaddedWin, colorPairUnread);
}

Expand All @@ -108,14 +118,23 @@ void UiListView::Draw()
static const std::string unreadIndicator = " " + UiConfig::GetStr("unread_indicator");
static const std::wstring wunread = StrUtil::ToWString(unreadIndicator);
mvwaddnwstr(m_PaddedWin, y, (m_PaddedW - StrUtil::WStringWidth(wunread)), wunread.c_str(), wunread.size());
}

if (useUnreadColor)
{
wattroff(m_PaddedWin, colorPairUnread);
wattron(m_PaddedWin, colorPair);
}

if (i == index)
{
wattroff(m_PaddedWin, attributeSelected);
wattron(m_PaddedWin, attribute);
if (hasColorSelected)
{
wattroff(m_PaddedWin, colorPairSelected);
wattron(m_PaddedWin, colorPair);
}
}
}
}
Expand Down
Loading