TreeView or ListView without column title bar - gtk

Is there a way to show data in TreeView or ListView without column title bar?

When you talk about column title bar without showing any code makes me think that you are asking about Header.
If so, then this is the function you need:
gtk_tree_view_set_headers_visible()
Here is with headers_visible set to TRUE (which is default):
And here is with headers_visible set to FALSE:
And here is an example Code:
#include <gtk/gtk.h>
GtkWidget *create_window ( void );
GtkWidget *create_scrolled_window ( void );
GtkWidget *create_tree_view ( void );
GtkListStore *create_list_store ( void );
int main ( void )
{
GtkWidget *window;
GtkWidget *scrolled_window;
GtkWidget *tree_view;
/// ***
gtk_init ( NULL, NULL );
/// ***
window = create_window();
/// ***
///scrolled_window = gtk_scrolled_window_new ( NULL, NULL );
scrolled_window = create_scrolled_window ( );
gtk_scrolled_window_set_kinetic_scrolling ( GTK_SCROLLED_WINDOW ( scrolled_window ), TRUE );
gtk_scrolled_window_set_capture_button_press ( GTK_SCROLLED_WINDOW ( scrolled_window ), TRUE );
/// ***
tree_view = create_tree_view ( );
gtk_container_add ( GTK_CONTAINER ( scrolled_window ), tree_view );
gtk_container_add ( GTK_CONTAINER ( window ), scrolled_window );
/// ***
gtk_widget_show_all ( window );
// ***
gtk_widget_show_all ( window );
gtk_main ();
}
GtkWidget *create_window ( void )
{
GtkWidget *window;
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gtk_window_set_default_size ( GTK_WINDOW ( window ), 150, 150 );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 5 );
/// ***
g_signal_connect ( window, "delete_event", G_CALLBACK ( gtk_main_quit ), NULL );
/// ***
return window;
}
GtkWidget *create_scrolled_window ( void )
{
GtkWidget *scrolled_window;
/// ***
scrolled_window = gtk_scrolled_window_new ( NULL, NULL );
gtk_scrolled_window_set_kinetic_scrolling ( GTK_SCROLLED_WINDOW ( scrolled_window ), TRUE );
gtk_scrolled_window_set_capture_button_press ( GTK_SCROLLED_WINDOW ( scrolled_window ), TRUE );
/// ***
return scrolled_window;
}
GtkListStore *create_list_store ( void )
{
GtkListStore *list_store;
list_store = gtk_list_store_new ( 1, G_TYPE_STRING );
/// ***
for ( gint i = 0; i < 10; i++ )
{
GtkTreeIter iter;
gchar *label = g_strdup_printf ( "Row number %d", i );
/// ***
gtk_list_store_append ( list_store, &iter );
gtk_list_store_set ( list_store, &iter, 0, label, -1 );
/// ***
g_free ( label );
}
return list_store;
}
GtkWidget *create_tree_view ( void )
{
GtkWidget *tree_view;
GtkCellRenderer *renderer;
GtkListStore *store;
/// ***
tree_view = gtk_tree_view_new ();
store = create_list_store();
/// ***
renderer = gtk_cell_renderer_text_new ();
g_object_set ( renderer, "editable", TRUE, NULL );
/// **
gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW ( tree_view ),
0, "This is the Title",
renderer,
"text", 0,
NULL );
/// ***
gtk_tree_view_set_model ( GTK_TREE_VIEW ( tree_view ), GTK_TREE_MODEL ( store ) );
g_object_unref ( store );
/// ***
gtk_tree_view_set_headers_visible ( GTK_TREE_VIEW ( tree_view ), FALSE );
/// ***
return tree_view;
}

Related

pTextServices->TxSendMessage( EM_STREAMIN, ( WPARAM ) SF_RTF, ( LPARAM ) &editStream, &lResult ) does not call EditStreamInCallback

When calling:
pTextServices->TxSendMessage( EM_STREAMIN, ( WPARAM ) SF_RTF, ( LPARAM ) &editStream, &lResult )
editSteam.EditStreamInCallback is not being called, but if SF_TEXT is used instead of SF_RTF, then editSteam.EditStreamInCallback gets called.
According to MS docs:
https://learn.microsoft.com/en-us/windows/win32/api/richedit/nc-richedit-editstreamcallback
An error occurs that prevents the rich edit control from transferring
data into or out of itself. Examples are out-of-memory situations,
failure of a system function, or an invalid character in the read
buffer.
In these cases editStream.dwError should contain a different value from zero, but it is zero.
This is the used RTF: "{\rtf1\ansi\pard test \par}" in the code escaped as:
"{\\rtf1\\ansi\\pard test \\par}"
Thank you
Fixed and working fine thanks to my friend Mr. Bruno Cantero (C3)
#include <Richedit.h>
#include <textserv.h>
typedef struct
{
char * szText;
LONG lSize;
LONG lCount;
} RTFTEXTINFO;
typedef HRESULT ( _stdcall * PCREATETEXTSERVICES ) ( IUnknown *, ITextHost *, IUnknown ** );
const IID IID_ITextServices = { 0x8d33f740, 0xcf58, 0x11ce, { 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 } };
class TTextHost : public ITextHost
{
public:
/* IUnknown */
STDMETHOD( QueryInterface )( REFIID, PVOID * ppvObject ) { * ppvObject = NULL; return S_FALSE; };
STDMETHOD_( ULONG, AddRef )( void ) { return 0; };
STDMETHOD_( ULONG, Release )( void ) { return 0; };
/* ITextHost */
HDC TxGetDC( void ) { return NULL; };
INT TxReleaseDC( HDC ) { return 1; };
BOOL TxShowScrollBar( INT, BOOL ) { return FALSE; };
BOOL TxEnableScrollBar( INT, INT ) { return FALSE; };
BOOL TxSetScrollRange( INT, LONG, INT, BOOL ) { return FALSE; };
BOOL TxSetScrollPos( INT, INT, BOOL ) { return FALSE; };
void TxInvalidateRect( LPCRECT, BOOL ) {};
void TxViewChange( BOOL ) {};
BOOL TxCreateCaret( HBITMAP, INT, INT ) { return FALSE; };
BOOL TxShowCaret( BOOL ) { return FALSE; };
BOOL TxSetCaretPos( INT, INT ) { return FALSE; };
BOOL TxSetTimer( UINT, UINT ) { return FALSE; };
void TxKillTimer( UINT ) {};
void TxScrollWindowEx( INT, INT, LPCRECT, LPCRECT, HRGN, LPRECT, UINT ) {};
void TxSetCapture( BOOL ) {};
void TxSetFocus( void ) {};
void TxSetCursor( HCURSOR, BOOL ) {};
BOOL TxScreenToClient( LPPOINT ) { return FALSE; };
BOOL TxClientToScreen( LPPOINT ) { return FALSE; };
HRESULT TxActivate( LONG * ) { return S_OK; };
HRESULT TxDeactivate( LONG ) { return S_OK; };
HRESULT TxGetClientRect( LPRECT prc ) { SetRectEmpty( prc ); return S_OK; };
HRESULT TxGetViewInset( LPRECT prc ) { SetRectEmpty( prc ); return S_OK; };
HRESULT TxGetCharFormat( const CHARFORMATW ** ppCF ) { * ppCF = FCharFormat; return S_OK; };
HRESULT TxGetParaFormat( const PARAFORMAT ** ppPF ) { * ppPF = FParaFormat; return S_OK; };
COLORREF TxGetSysColor( int iIndex ) { return GetSysColor( iIndex ); };
HRESULT TxGetBackStyle( TXTBACKSTYLE * pstyle ) { * pstyle = TXTBACK_TRANSPARENT; return S_OK; };
HRESULT TxGetMaxLength( DWORD * plength ) { * plength = INFINITE; return S_OK; };
HRESULT TxGetScrollBars( DWORD * pdwScrollBar ) { * pdwScrollBar = 0; return S_OK; };
HRESULT TxGetPasswordChar( _Out_ TCHAR * pch ) { return S_FALSE; };
HRESULT TxGetAcceleratorPos( LONG * pcp ) { * pcp = -1; return S_OK; };
HRESULT TxGetExtent( LPSIZEL ) { return E_NOTIMPL; };
HRESULT OnTxCharFormatChange( const CHARFORMATW * pCF ) { _bcopy( FCharFormat, ( void * ) pCF, pCF->cbSize ); return S_OK; };
HRESULT OnTxParaFormatChange( const PARAFORMAT * pPF ) { _bcopy( FParaFormat, ( void * ) pPF, pPF->cbSize ); return S_OK; };
HRESULT TxGetPropertyBits( DWORD, DWORD * pdwBits ) { * pdwBits = TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_WORDWRAP | TXTBIT_USECURRENTBKG; return S_OK; };
HRESULT TxNotify( DWORD, void * ) { return S_OK; };
HIMC TxImmGetContext( void ) { return NULL; };
void TxImmReleaseContext( HIMC ) {};
HRESULT TxGetSelectionBarWidth( LONG * lSelBarWidth ) { * lSelBarWidth = 100; return S_OK; };
CHARFORMATW * FCharFormat;
PARAFORMAT * FParaFormat;
};
static DWORD CALLBACK EditStreamCallback( DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb )
{
RTFTEXTINFO * pRtfTextInfo;
pRtfTextInfo = ( RTFTEXTINFO * ) dwCookie;
if( pRtfTextInfo->lSize - pRtfTextInfo->lCount < cb )
* pcb = pRtfTextInfo->lSize - pRtfTextInfo->lCount;
else
* pcb = cb;
memcpy( pbBuff, pRtfTextInfo->szText, * pcb );
pRtfTextInfo->lCount += * pcb;
return 0;
}
extern "C" void SayRTF( void )
{
LRESULT lResult;
HDC hDC;
HFONT hFont;
HMODULE hDLL;
RECT stRect;
LOGFONT stLogFont;
EDITSTREAM stEditStream;
PCREATETEXTSERVICES pCreateTextServices;
CHARFORMATW stCharFormat;
PARAFORMAT stParaFormat;
RTFTEXTINFO sRtfTextInfo;
IUnknown * pUnknown;
ITextServices * pTextServices;
TTextHost * pTextHost;
/* HDC donde dibujar. */
hDC = ( HDC ) hb_parnl( 1 ); // the hDC where you want to show the RTF
// Comentamos para probar la transperencia Rectangle( hDC, 9, 9, 202, 202 );
stRect = { 10, 10, 200, 200 };
hDLL = LoadLibrary( "Riched20.dll" );
if( hDLL == NULL )
return;
pCreateTextServices = ( PCREATETEXTSERVICES ) GetProcAddress( hDLL, "CreateTextServices" );
if( pCreateTextServices == NULL )
{
FreeLibrary( hDLL );
return;
}
/* Obtenemos las caracterĂ­sticas de la fuente del HDC. */
hFont = ( HFONT ) SelectObject( hDC, GetStockObject( SYSTEM_FONT ) );
GetObject( hFont, sizeof( LOGFONT ), &stLogFont );
SelectObject( hDC, hFont );
/* Creamos el formato de la fuente por defecto. */
memset( &stCharFormat, 0, sizeof( CHARFORMATW ) );
stCharFormat.cbSize = sizeof( CHARFORMATW );
stCharFormat.dwEffects = CFM_EFFECTS | CFE_AUTOBACKCOLOR;
stCharFormat.dwEffects &= ~( CFE_PROTECTED | CFE_LINK | CFE_AUTOCOLOR );
if( stLogFont.lfWeight < FW_BOLD )
stCharFormat.dwEffects &= ~CFE_BOLD;
if( !stLogFont.lfItalic )
stCharFormat.dwEffects &= ~CFE_ITALIC;
if( !stLogFont.lfUnderline )
stCharFormat.dwEffects &= ~CFE_UNDERLINE;
if( !stLogFont.lfStrikeOut )
stCharFormat.dwEffects &= ~CFE_STRIKEOUT;
stCharFormat.dwMask = CFM_ALL | CFM_BACKCOLOR | CFM_STYLE;
stCharFormat.bCharSet = stLogFont.lfCharSet;
stCharFormat.bPitchAndFamily = stLogFont.lfPitchAndFamily;
stCharFormat.yHeight = -stLogFont.lfHeight * 1440 / GetDeviceCaps( hDC, LOGPIXELSY );
MultiByteToWideChar( CP_ACP, 0, stLogFont.lfFaceName, LF_FACESIZE, stCharFormat.szFaceName, LF_FACESIZE );
/* Creamos el formato de párrafo por defecto. */
memset( &stParaFormat, 0, sizeof( PARAFORMAT ) );
stParaFormat.cbSize = sizeof( PARAFORMAT );
stParaFormat.dwMask = PFM_ALL;
stParaFormat.wAlignment = PFA_LEFT;
stParaFormat.cTabCount = 1;
stParaFormat.rgxTabs[ 0 ] = lDefaultTab;
/* Instanciamos nuestro objeto host. */
pTextHost = new TTextHost;
pTextHost->FCharFormat = &stCharFormat;
pTextHost->FParaFormat = &stParaFormat;
/* Creamos el objeto IUnknown y lo asociamos a nuestro objeto TTextHost. */
if( pCreateTextServices( NULL, pTextHost, &pUnknown ) != S_OK )
{
delete pTextHost;
FreeLibrary( hDLL );
return;
}
/* Obtenemos el interface ITextServices. */
pTextServices = NULL;
pUnknown->QueryInterface( IID_ITextServices, ( void ** ) &pTextServices );
/* Liberamos el objeto IUnknown. */
pUnknown->Release();
if( pTextServices != NULL )
{
// sRtfTextInfo.szText = "Plaint Text";
sRtfTextInfo.szText = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Tahoma;}{\\f1\\fswiss\\fcharset0 Arial;}}{\\colortbl ;\\red128\\green0\\blue0;\\red0\\green0\\blue128;\\red0\\green128\\blue0;}\\viewkind4\\uc1\\pard\\f0\\fs20 H\\fs24 E\\b L\\ul\\fs20 L\\i O\\ulnone\\b0\\i0 \\cf1 W\\b\\fs22 O\\cf2\\ul\\b0 R\\i\\fs28 L\\cf3\\ulnone\\b\\i0\\fs20 D\\cf0\\b0\\f1\\par}";
sRtfTextInfo.lSize = lstrlen( sRtfTextInfo.szText );
sRtfTextInfo.lCount = 0;
stEditStream.dwCookie = ( DWORD_PTR ) &sRtfTextInfo;
stEditStream.pfnCallback = EditStreamCallback;
// if( pTextServices->TxSendMessage( EM_STREAMIN, SF_TEXT, ( LPARAM ) &stEditStream, &lResult ) == S_OK )
if( pTextServices->TxSendMessage( EM_STREAMIN, SF_RTF, ( LPARAM ) &stEditStream, &lResult ) == S_OK )
pTextServices->TxDraw( DVASPECT_CONTENT, 0, NULL, NULL, hDC, NULL, ( RECTL * ) &stRect, NULL, NULL, NULL, 0, TXTVIEW_INACTIVE );
/* Liberamos el objeto ITextServices. */
pTextServices->Release();
}
delete pTextHost;
FreeLibrary( hDLL );
}

How to make placeholder text of a Gtk.SearchEntry visible even if the entry is focused?

The search entry appears when a menu button is clicked. But the problem is that, it gets automatically focused and as a result, the placeholder text is not visible. I want the placeholder text to be always visible, even when the entry is focused.
Feel free to post the solutions using any language you want but vala is preferred.
Thank you
Until you find a better solution, this is what I'll do in this case:
create an entry buffer
set the buffer on that entry
set cursor position at the end of the buffer (optional)
select the whole region text (probably this is what you need)
Now what I did was to connect the button to the "toggled" signal and put all that information in the callback, feel free to adjust it for your needs:
#include <gtk/gtk.h>
static void toggled_clbk ( GtkWidget *button, GtkWidget *search_entry )
{
g_return_if_fail ( GTK_IS_TOGGLE_BUTTON ( button ) );
g_return_if_fail ( GTK_IS_SEARCH_ENTRY ( search_entry ) );
if ( gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON ( button ) ) )
{
/// ***
GtkEntryBuffer *buffer;
/// ***
buffer = gtk_entry_buffer_new ( "Type here...", -1 );
/// ***
gtk_entry_set_buffer ( GTK_ENTRY ( search_entry ), buffer );
/// ***
///gtk_editable_set_position ( GTK_EDITABLE ( search_entry ), -1 );
gtk_editable_select_region ( GTK_EDITABLE ( search_entry ), 0, -1 );
/// ***
g_object_unref ( buffer );
}
}
int main ( void )
{
GtkWidget *window;
GtkWidget *box;
GtkWidget *search_box;
GtkWidget *search_button;
GtkWidget *search_bar;
GtkWidget *search_entry;
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
gtk_widget_set_size_request ( window, 300, -1 );
/// ***
g_signal_connect ( window, "destroy", gtk_main_quit, NULL );
/// ***
box = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, 5 );
gtk_container_add ( GTK_CONTAINER ( window ), box );
gtk_container_set_border_width ( GTK_CONTAINER ( box ), 0 );
/// ***
search_entry = gtk_search_entry_new ();
/// ***
search_box = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL, 10 );
gtk_box_pack_start ( GTK_BOX ( search_box ), search_entry, FALSE, FALSE, 0 );
/// ***
search_bar = gtk_search_bar_new ();
gtk_search_bar_connect_entry ( GTK_SEARCH_BAR ( search_bar ), GTK_ENTRY ( search_entry ) );
/// ***
gtk_container_add ( GTK_CONTAINER ( search_bar ), search_box );
gtk_box_pack_end ( GTK_BOX ( box ), search_bar, FALSE, FALSE, 0 );
/// ***
search_button = gtk_toggle_button_new_with_label ( "Search" );
g_object_bind_property ( search_button, "active", search_bar, "search-mode-enabled", G_BINDING_BIDIRECTIONAL );
/// ***
gtk_box_pack_start ( GTK_BOX ( box ), search_button, TRUE, TRUE, 0 );
/// ***
g_signal_connect ( search_button, "toggled", G_CALLBACK ( toggled_clbk ), search_entry );
/// ***
gtk_widget_show_all ( window );
/// ***
gtk_main();
}
As a result, once that you click the search button and the search bar gets revealed you will have something like this:
Before you click the button:
After you click the button:

how to auto scroll the scrollbar to bottom when window get minimized

I am working on a project which has to be in GTK-2.0 and the problem I am facing is that If the window gets Minimized after being Maximized the scrollbar does not goes back the bottom anymore.
Here is a part of the code which could be seen and tested:
#include <gtk/gtk.h>
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} Widgets;
void chatMSG ( GtkButton *, Widgets * );
int main ( void )
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
Widgets *widg = g_slice_new ( Widgets );
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
gtk_widget_set_size_request ( window, 250, 200 );
/// ***
widg->textview = gtk_text_view_new();
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
/// ***
widg->entry = gtk_entry_new();
button = gtk_button_new_with_label ( "Send" );
/// ***
g_signal_connect ( G_OBJECT ( button ), "clicked", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
/// ***
scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
gtk_widget_set_size_request ( scrolled_win, -1, 200 );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
/// ***
hbox = gtk_hbox_new ( FALSE, 5 );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
/// ***
vbox = gtk_vbox_new ( FALSE, 5 );
gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
/// ***
gtk_container_add ( GTK_CONTAINER ( window ), vbox );
gtk_widget_show_all ( window );
gtk_main();
}
void chatMSG ( GtkButton *button, Widgets *widg )
{
( void ) button;
GtkTextBuffer *buffer;
GtkTextMark *mark;
GtkTextIter iter, start, end;
const gchar *text;
/// ***
buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
text = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
/// ***
mark = gtk_text_buffer_get_insert ( buffer );
gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
gtk_text_buffer_get_bounds ( buffer, &start, &end );
if ( gtk_text_buffer_get_char_count ( buffer ) && strlen( text ) > 0 )
{
gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
}
gtk_text_buffer_insert ( buffer, &iter, text, -1 );
gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
/// ***
mark = gtk_text_buffer_create_mark ( buffer, NULL, &iter, FALSE );
gtk_text_view_scroll_mark_onscreen ( GTK_TEXT_VIEW ( widg->textview ), mark );
gtk_text_buffer_delete_mark ( buffer, mark );
}
My guess is that somehow I mixed up things in the chatMSG() Funcion.
How do I keep the scrollbar at a bottom after user minimize the Window?
I also tried the following:
GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
gtk_adjustment_set_value ( adj, adj->upper );
But it is not working too.
After a lot of search and trying different things which did not helped I searched help by Gnome-Team and managed to fix it.
I decided to share this here two, because it could help in the future other too.
Here is an working example:
#include <gtk/gtk.h>
typedef struct
{
GtkWidget *entry;
GtkWidget *textview;
} Widgets;
void chatMSG ( GtkButton *, Widgets * );
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data );
void scroll_bottom_gravity ( GtkWidget *scrolled_window, gpointer user_data );
int main ( void )
{
GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
Widgets *widg = g_slice_new ( Widgets );
double from_bottom = 0.0;
/// ***
gtk_init ( NULL, NULL );
/// ***
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
gtk_widget_set_size_request ( window, 250, 200 );
/// ***
widg->textview = gtk_text_view_new();
gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
/// ***
widg->entry = gtk_entry_new();
button = gtk_button_new_with_label ( "Send" );
/// ***
g_signal_connect ( G_OBJECT ( button ), "clicked", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
/// ***
scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
gtk_widget_set_size_request ( scrolled_win, -1, 200 );
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
g_signal_connect ( scrolled_win, "size-allocate", ( GCallback ) scroll_bottom_gravity, &from_bottom );
g_signal_connect ( adjustment, "value-changed", ( GCallback ) scroll_value_changed, &from_bottom );
gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
/// ***
hbox = gtk_hbox_new ( FALSE, 5 );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
/// ***
vbox = gtk_vbox_new ( FALSE, 5 );
gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
/// ***
gtk_container_add ( GTK_CONTAINER ( window ), vbox );
gtk_widget_show_all ( window );
gtk_main();
}
void chatMSG ( GtkButton *button, Widgets *widg )
{
( void ) button;
GtkTextMark *mark;
GtkTextIter iter;
/// ***
GtkTextBuffer *buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
const gchar *text = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
/// ***
mark = gtk_text_buffer_get_insert ( buffer );
gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
if ( gtk_text_buffer_get_char_count ( buffer ) && strlen ( text ) > 0 )
{
gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
}
gtk_text_buffer_insert ( buffer, &iter, text, -1 );
gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
}
void scroll_bottom_gravity ( GtkWidget *scrolled_window, gpointer user_data )
{
GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_window ) );
double *from_bottom = user_data;
double upper = gtk_adjustment_get_upper ( adjustment );
double page_size = gtk_adjustment_get_page_size ( adjustment );
gtk_adjustment_set_value ( adjustment, upper - page_size - *from_bottom );
}
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data )
{
double *from_bottom = user_data;
double value = gtk_adjustment_get_value ( adjustment );
double upper = gtk_adjustment_get_upper ( adjustment );
double page_size = gtk_adjustment_get_page_size ( adjustment );
*from_bottom = upper - page_size - value;
}

Function gtk_cell_renderer_toggle_set_active does not work properly

I would like to put a Checkbox in treeview.
When I clicked the Checkbox, it should ckeck. But Checkbox keeps being not checked.
I have written a sample code in C and GTK3:
#include <gtk/gtk.h>
GtkTreeModel* create_model ()
{
GtkTreeIter gti;
GtkListStore *gls = gtk_list_store_new ( 1, G_TYPE_BOOLEAN );
gtk_list_store_append ( gls, &gti );
gtk_list_store_set ( gls, &gti, 0, FALSE, -1 );
return GTK_TREE_MODEL ( gls );
}
void check ( GtkCellRendererToggle *cell )
{
int active = gtk_cell_renderer_toggle_get_active ( cell );
g_print ( "%d\n", active );
if ( active )
{
//fail
gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE ( cell ), FALSE );
}
else
{
//fail
gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE ( cell ), TRUE) ;
}
return;
}
int main ( int argc, char *argv[] )
{
gtk_init ( &argc, &argv );
//window
GtkWidget *window_main = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
//tree view
GtkWidget *treeview = gtk_tree_view_new_with_model ( create_model () );
//cell_renderer_toggle
GtkCellRenderer *cell = gtk_cell_renderer_toggle_new ();
gtk_tree_view_append_column ( GTK_TREE_VIEW ( treeview ), gtk_tree_view_column_new_with_attributes ( "test", cell, "active", 0, NULL ) );
g_signal_connect ( cell, "toggled", G_CALLBACK ( check ), NULL );
gtk_container_add ( GTK_CONTAINER ( window_main ), treeview );
gtk_widget_show_all ( window_main );
gtk_main();
return 0;
}
Function gtk_cell_renderer_toggle_set_active call fails and does not set the cell active.
Please help me fix my code.
With the call of
gtk_tree_view_column_new_with_attributes ("test", cell, "active", 0, NULL);
you bind the "active" property of each cell renderer in any row of the column to the value in the first column of the related data model. Although the state of any GtkCellRendererToggle instance is represented by its own properties its "active" property reflects the corresponding value in the data model at the same time.
If you activate a single cell renderer by means of gtk_cell_renderer_toggle_set_active you just set the "active" property of the specific GtkCellRendererToggle instance. Unfortunately the instance has no knowledge about the data model from which it represent a value and therefore has no access to it. That means that on the next draw of the treeview the "active" property corresponds with the related value from the data model again. Your change is simply overwritten.
Nevertheless you can still safely set all other properties of a cell renderer that are not connected to the data model. I included an example for that in my example.
That means that your callback have to change the value in the data model instead of changing the property of the cell renderer.
The appended modification of your example code illustrates what i've described
#include <gtk/gtk.h>
GtkListStore *
create_model ()
{
GtkTreeIter gti;
GtkListStore *gls;
gls = gtk_list_store_new (1, G_TYPE_BOOLEAN);
gtk_list_store_append (gls, &gti);
gtk_list_store_set (gls, &gti, 0, TRUE, -1);
return gls;
}
void
check (GtkCellRendererToggle * cell, gchar * path, GtkListStore * model)
{
GtkTreeIter iter;
gboolean active;
active = gtk_cell_renderer_toggle_get_active (cell);
gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (model), &iter, path);
if (active) {
gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(cell), 0, 0);
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, FALSE, -1);
}
else {
gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(cell), 0.5, 0.5);
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, TRUE, -1);
}
}
int
main (int argc, char *argv[])
{
GtkTreeViewColumn *column;
GtkWidget *window_main;
GtkWidget *treeview;
GtkCellRenderer *cell;
GtkListStore *store;
gtk_init (&argc, &argv);
store = create_model ();
//window
window_main = gtk_window_new (GTK_WINDOW_TOPLEVEL);
//tree view
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
//cell_renderer_toggle
cell = gtk_cell_renderer_toggle_new ();
column =
gtk_tree_view_column_new_with_attributes ("test",
cell, "active", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
g_signal_connect (cell, "toggled", G_CALLBACK (check), store);
g_signal_connect (window_main, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (window_main), treeview);
gtk_widget_show_all (window_main);
gtk_main ();
return 0;
}

GTK and SFML 2 Blurred sprites

I want to use GTK+ and SFML 2.0 together. I created a simple window to test that, but doesn't work well. Sprites are blurred. Below is a screenshot describing the problem.
/edit:
The window renders only the first pixel of a texture.
It should look like this:
The code:
#include <gtk/gtk.h>
#include <SFML/Graphics.hpp>
#include <gdk/gdkwin32.h>
sf::RenderWindow Win;
sf::Sprite tile[ MAP_SIZE ][ MAP_SIZE ];
void on_expose( GtkWidget * widget, gpointer data )
{
MapView * view =( MapView * ) data;
sf::Event event;
while( Win.pollEvent( event ) )
{
if( event.type == sf::Event::Closed )
Win.close();
view->updateEvents( & event, Win );
}
Win.clear( sf::Color::White );
view->render( tile, Win );
Win.display();
gtk_widget_queue_draw(widget);
}
int main( int argc, char ** argv )
{
sf::Texture tex; // Testing texture
if( !tex.loadFromFile( "gfx/7.png" ) )
std::cout << "Unable to load texture!\n";
for( int i = 0; i < MAP_SIZE; ++i )
for( int j = 0; j < MAP_SIZE; ++j )
tile[ j ][ i ].setTexture( tex ); // Default texture, a.k.a MAP_NONE
MapView view( tile, sf::Vector2f( 0, 0 ) );
gtk_init( & argc, & argv );
GtkWidget * window;
GtkWidget * area;
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
area = gtk_drawing_area_new();
gtk_container_add( GTK_CONTAINER( window ), area );
GdkEventMask mask;
mask = GDK_ALL_EVENTS_MASK;
gtk_widget_add_events( area, mask );
gtk_widget_set_can_focus( area, true );
gtk_widget_set_size_request( area, 16 * 25, 16 * 25 ); // Preview size.
gtk_widget_realize( area );
gtk_widget_set_double_buffered( area, false );
Win.create( sf::WindowHandle( GDK_WINDOW_HWND( area->window ) ) ); // Windows-only solution
Win.setFramerateLimit( 30 );
g_signal_connect( window, "destroy", G_CALLBACK( gtk_main_quit ), NULL );
g_signal_connect( area, "expose-event", G_CALLBACK( on_expose ), & view );
gtk_widget_show_all( window );
gtk_main();
return 0;
}
I had to call
gdk_window_resize(area->window, MAP_SIZE*25, MAP_SIZE*25);
before creating a SFML window inside drawing-area.
My wild guess:
Use the second argument of sf::Sprite::setTexture to correctly reset the size of the sprite.
for( int i = 0; i < MAP_SIZE; ++i )
for( int j = 0; j < MAP_SIZE; ++j )
tile[ j ][ i ].setTexture( tex, true );