2222use std:: collections:: HashMap ;
2323use std:: fs:: File ;
2424use std:: io:: Read ;
25+ use std:: mem;
2526use std:: sync:: Mutex ;
2627
2728use quote:: { Tokens , ToTokens } ;
@@ -150,6 +151,7 @@ pub enum EitherWidget {
150151#[ derive( Debug ) ]
151152pub struct GtkWidget {
152153 pub child_events : HashMap < ( String , String ) , Event > ,
154+ pub construct_properties : HashMap < syn:: Ident , Tokens > ,
153155 pub events : HashMap < String , Event > ,
154156 pub relm_name : Option < Ty > ,
155157 pub save : bool ,
@@ -159,6 +161,7 @@ impl GtkWidget {
159161 fn new ( ) -> Self {
160162 GtkWidget {
161163 child_events : HashMap :: new ( ) ,
164+ construct_properties : HashMap :: new ( ) ,
162165 events : HashMap :: new ( ) ,
163166 relm_name : None ,
164167 save : false ,
@@ -228,8 +231,12 @@ fn parse_widget(tokens: &[TokenTree], save: bool) -> (Widget, &[TokenTree]) {
228231 let mut child_properties = HashMap :: new ( ) ;
229232 gtk_widget. save = save;
230233 if let TokenTree :: Delimited ( Delimited { delim : Paren , ref tts } ) = tokens[ 0 ] {
231- let parameters = parse_comma_list ( tts) ;
232- init_parameters = parameters;
234+ if let TokenTree :: Delimited ( Delimited { delim : Brace , ref tts } ) = tts[ 0 ] {
235+ gtk_widget. construct_properties = parse_hash ( tts) ;
236+ }
237+ else {
238+ init_parameters = parse_comma_list ( tts) ;
239+ }
233240 tokens = & tokens[ 1 ..] ;
234241 }
235242 if let TokenTree :: Delimited ( Delimited { delim : Brace , ref tts } ) = tokens[ 0 ] {
@@ -357,6 +364,56 @@ fn parse_comma_ident_list(tokens: &[TokenTree]) -> Vec<syn::Ident> {
357364 params
358365}
359366
367+ enum HashState {
368+ InName ,
369+ AfterName ,
370+ InValue ,
371+ }
372+
373+ use self :: HashState :: * ;
374+
375+ fn parse_hash ( tokens : & [ TokenTree ] ) -> HashMap < syn:: Ident , Tokens > {
376+ let mut params = HashMap :: new ( ) ;
377+ let mut current_param = Tokens :: new ( ) ;
378+ let mut state = InName ;
379+ let mut name = syn:: Ident :: new ( "" ) ;
380+ for token in tokens {
381+ match state {
382+ InName => {
383+ // FIXME: support ident with dash (-).
384+ if let Token ( Ident ( ref ident) ) = * token {
385+ name = ident. clone ( ) ;
386+ state = AfterName ;
387+ }
388+ else {
389+ panic ! ( "Expected ident, but found `{:?}` in view! macro" , token) ;
390+ }
391+ } ,
392+ AfterName => {
393+ if * token == Token ( Colon ) {
394+ state = InValue ;
395+ }
396+ else {
397+ panic ! ( "Expected colon, but found `{:?}` in view! macro" , token) ;
398+ }
399+ } ,
400+ InValue => {
401+ if * token == Token ( Comma ) {
402+ let ident = mem:: replace ( & mut name, syn:: Ident :: new ( "" ) ) ;
403+ params. insert ( ident, current_param) ;
404+ current_param = Tokens :: new ( ) ;
405+ }
406+ else {
407+ token. to_tokens ( & mut current_param) ;
408+ }
409+ } ,
410+ }
411+ }
412+ // FIXME: could be an empty hash.
413+ params. insert ( name, current_param) ;
414+ params
415+ }
416+
360417fn parse_comma_list ( tokens : & [ TokenTree ] ) -> Vec < Tokens > {
361418 let mut params = vec ! [ ] ;
362419 let mut current_param = Tokens :: new ( ) ;
@@ -369,6 +426,7 @@ fn parse_comma_list(tokens: &[TokenTree]) -> Vec<Tokens> {
369426 token. to_tokens ( & mut current_param) ;
370427 }
371428 }
429+ // FIXME: could be an empty list.
372430 params. push ( current_param) ;
373431 params
374432}
0 commit comments